For Beginners: The Importance Of Object Oriented Design

Started by
6 comments, last by jpetrie 11 years, 6 months ago
I'm sure all of the senior programmers here understand the fundamentals of object oriented design, but this is for the beginners. First, let's define object oriented-design:
Object-oriented design is the process of planning a system of interacting objects for the purpose of solving a software problem.[/quote]
That hits the nail on the head. One important thing to note about object oriented design is this, you're planning a system of interacting objects. That means you're objects will work together. Many a beginner programmer, including me smile.png, don't grasp this. You're objects should work together. They shouldn't be isolated from each other so you only make separate instances of them, you should be using them together.

This leads into the first Principle of good object-oriented design

The Single Responsibility Principle

In object-oriented programming, the single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.[/quote]

This is the fundamental building block of object-oriented design. Before we continue, let's take a closer look at what a responsibility is. In programming, a responsibility is something the class handles or does. Let's use a pong example:

When I first programmed pong, I had my Paddle class drawing itself, checking for collision, and updating itself. <-This was how all my other classes were designed too. This led to fragile code that would break if I changed any class, and the only way to fix it was to go through all my source and header files to fix the problem. The single responsibility principles goal is to make the above problems nonexistent in your code, and it largely succeeds.

Let's look at how we could fix this:
Have the paddle classes main goal to only update the paddles position and values. It doesn't draw the Paddle to the screen anymore. Do the same for the Ball class and the AIPaddle class. Then create another class called GameDraw. This has one AIPaddle, one Paddle, and a Ball. All this class does is use my get() functions to draw my objects to the screen. This means making a change to how I draw the screen doesn't affect my classes at all, and changing how I update my variables doesn't change how I draw my objects. Then I create a gamelogic class. This class calls all my Update() functions, thus making a change to how I update my objects won't change this class, and making a change to the order I update or what I update won't change the other Object's classes. Then, I create a BaseGame class. This class' responsibility is to run the game. It includes the gameobjects I need and a GameDraw/GameLogic class. Now, changing my class' won't mess up the rest of my code, because my classes are handling their responsibility, and the rest of my classes don't have to deal with them.

I hope all beginner programmers can read either this, or another article about this, because the Single Responsiblity Principle is extremely important to writing bug/error-free code, and will save you a lot of headaches by isolating what's causing problems, while still letting your classes work together.

On to Data:

Encapsulation

Encapsulation is also fundamental, and it isn't something I'm going to go into length about, because considering almost every tutorial you will see uses it in the correct way, and in most books it is expressed at length. But, it is worth a mention. In fact, it's worth more than a mention. If you don't use the single responsibility principle, this is the next best thing. The idea behind encapsulation is:

Hide implementation details in a class from users of the class, exposing only a public interface[/quote]

This goes hand-in-hand with the Single Responsibility Principle. You only want the users of your class to use your member functions to do what your classes intent, or responsibility, was. You don't want some other user using your classes member data to do something that the class has no intention to do. The most common way to go about this is to make the data members your class needs private and only use them in your classes member functions. This brings on get() and set() functions.

A get() function returns one of your classes data members.

A set() function changes the value of one of your classes data members.

Let's get this out of the way: Set functions are not object oriented. The only time set functions should be used is in cases where they are part of your classes responsibility. Get functions, on the other hand, are very important. Let's use the pong example from earlier. Imagine this:
The paddle class' responsibility is to update the data values. If it is gong to update the position it needs the Sprite and Image that the class is using. I include the Sprite and Image in the classes data members. Now, to draw the class in GameDraw I need to use a sprite. Instead of making an all new sprite or going through pointers, I just use a get() function. I say screen.draw(Paddle.GetPaddleSprite()). This is object oriented, because it allows the other class to perform it's responsibility, and allows my class too, while not making my class more fragile. This is the basics of encapsulation, but there's far more to it.


Closing:

I would add more Principles, and I will later. I just have to go eat lunch. I hope this helped many a-new developer, and feel free to add your own principles, ideas, and corrections below smile.png!

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

Advertisement
This is good stuff, please keep it coming!

Enumerated Types
I am not sure what this is called, but I would like to add the concept of not using strings as enumerated types. For example


void foo(string gender)
{
if (gender == "male")
{
// do stuff
}
else if (gender == "female")
{
// do other stuff
}
}


This is bad for a couple of reasons. First of all it allows gender to be any arbitrary string. Meaning "Male", "MALE", "m", and "darth vadar" are all valid string values, but may not be valid gender values. So as a programmer trying to figure out what valid values I can pass as a gender I may have to dig around in the source code how it is used. Also, passing around and comparing string values is slower than enumerated types.

This is how it should be done

typedef enum _Gender
{
Unspecified,
Female,
Male
} Gender;

void foo(Gender gender)
{
if (gender == Male)
{
// Do Stuff
}
else if (gender == Female)
{
// Do Other Stuff
}
}



Now a programmer can know what valid values are just by looking at the enumerated type. The compiler can catch a typo if I accidentally typed one the enumerated types wrong and passing and comparing enumerated types is super fast as it is merely and integer.

Assertions

Assertions are great for catching bugs right when arise rather than when their effects have been propagated through your code. Whenever you write a function and you are making assumptions on the data you are going to operate on. Put this assumptions on as assertions. For example.


public void foo(int index)
{
assert index >= 0;
// do stuff
}

public bool binarySearch(Array data, int value)
{
assert isSorted(data);
// do search
}


These assertions will take more processing time in a debug environment but once you release the final product they will be gone. Using assertions is very useful for tracking down bugs early rather than later. It is almost counter intuitive but making your program crash when something is wrong rather than silently ignoring it will result is code has less bugs as it will help you track down problems sooner. If you aren't familiar with assertions I would definitely look into it.

My current game project Platform RPG
[sub]

We got good stuff here! Amazing how each time that I come to this website the people, information, and help causes my understanding to grow.[/sub]

[sub]

Thanks, so much! biggrin.png [/sub]


[sub]

Clinton[/sub]

Personal life and your private thoughts always effect your career. Research is the intellectual backbone of game development and the first order. Version Control is crucial for full management of applications and software. The better the workflow pipeline, then the greater the potential output for a quality game. Completing projects is the last but finest order.

by Clinton, 3Ddreamer


Assertions

Assertions are great for catching bugs right when arise rather than when their effects have been propagated through your code. Whenever you write a function and you are making assumptions on the data you are going to operate on. Put this assumptions on as assertions. For example.

public void foo(int index)
{
assert index >= 0;
// do stuff
}

public bool binarySearch(Array data, int value)
{
assert isSorted(data);
// do search
}


These assertions will take more processing time in a debug environment but once you release the final product they will be gone. Using assertions is very useful for tracking down bugs early rather than later. It is almost counter intuitive but making your program crash when something is wrong rather than silently ignoring it will result is code has less bugs as it will help you track down problems sooner. If you aren't familiar with assertions I would definitely look into it.

I think when talking about assertiions there should be a discussion of when to use assertions and when to use exceptions. I'm not saying for you to do it. But the question has been raised before. And beginners tend to think that one can be used for the other. Which is not always correct.

Beginner in Game Development?  Read here. And read here.

 


I think when talking about assertiions there should be a discussion of when to use assertions and when to use exceptions. I'm not saying for you to do it. But the question has been raised before. And beginners tend to think that one can be used for the other. Which is not always correct.
This. Assertions are there to evaluate the results of a function/method/subrutine/etc, not to validate incoming data (in that case you validate by hand and/or use exceptions).

When you need to ask the program "Is this result any good?" then you use assertions to check up if the algorithm works. If you need to ask "Is this input any good?" then you use exceptions (and normal data consistency checks of course).

In the case of binary search, you'd use the assertion after the search was completed to check if the object that was returned is the correct one.

Now if the input of the binary search method is incorrect, you'd raise an exception. Or at most, use an assertion after trying to sort the collection to check if the sorting algorithm works.

That's why ideally you'd get rid of assertions when you finish up your software. Because they're not there to validate data but to validate the results of the things you do with the data, to know if the algorithm you implemented works as intended. When the algorithms works as intended, assertions aren't useful anymore, thus you get rid of them.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator


Now if the input of the binary search method is incorrect, you'd raise an exception. Or at most, use an assertion after trying to sort the collection to check if the sorting algorithm works.

Interesting. I've always wondered about pre-conditions and post-conditions for a method. I thought that something that you'd use assertions for. Whereas exceptions are to handle "unexpected" errors.

Beginner in Game Development?  Read here. And read here.

 

This forum isn't a place for people to post resources for beginners, but rather one for beginners to ask questions and engage in discussion. It's not your blog either; this kind of thread is more appropriate for a journal post or for hosting on your own blog.

This topic is closed to new replies.

Advertisement