I'm working on a movie playback related app and I'm running into some design issues at the moment.
As you would expect, I have a movie class with properties for things like the file path, file size and others.
The movie class does not know anything about the movie internals and it doesn't decode the movie file directly.
To achieve that, I have another large class: the decoder.
This class knows all movie internals like the duration, the frame rate etc.
It also offers methods to retrieve video or audio data from the file.
Breaking up the decoder into smaller chunks would not make much sense as the decoder uses a third party library and a lot of C pointers would need to be handed around. I'd rather avoid that for the sake of simplicity regarding memory management etc.
A movie holds a decoder with a clearly defined interface as the decoder itself is implemented using the strategy pattern in my movie class.
Movie ----------------> Decoder (implements interface)
| |
v v
File related variables Movie internals
I'm wondering if this design is good in terms of information hiding and SRP.
All outside classes know that a movie has a decoder with a bunch of properties.
Wouldn't it be better to have them only know that there's a movie?
But then the movie class would get enormous and there would be a lot of stub methods only accessing the decoder's properties.
Any advice would be appreciated.
Edit:
I took a deeper look at the Facade pattern (inspired by #Erik's answer) and it looks like the perfect match here. I can subdivide the Movie class a bit further but the "outside world" shouldn't need to know about the details to avoid complexity. However, this will yield a Facade class with lots of methods.
Thus, it looks like it is a huge class from the outside while it's nicely separated into logical bricks when looking on the inside.
Do you think it is ok then?
Rather than pulling all the code into a new class, you could make a new class that itself contains no logic, but simply wraps around a Movie and exposes a large collection of methods that each call the neccesary methods on Movie and Decoder.
This is basically an implementation of the Facade Pattern:
https://en.wikipedia.org/wiki/Facade_pattern
It has the advantage that outside classes have no knowledge about how a movie works other than "it's this class with all these properties we can ask for", while on the inside you don't end up with huge classes.
Movie is a data object that contains attributes of a Movie whereas Decoder is a processing element, that seems to offer APIs to perform various operations with a Movie object.
You can modify your Decoder to accept a Movie object and perform those operations. Movie doesn't need to have a reference to a Decoder object. Decoder is more like a Visitor of Movie object. If the decoder class cannot be modified, then, you can create a Proxy class that provides these APIs that take the Movie object and calls the methods in Decoder class with appropriate attributes of Movie object.
Related
I am reading Clean Code by Robert Martin and there is a chapter called "Objects and Data Structures" which discusses how a class should either be a data structure or an object. The essence is:
"Objects hide their data behind abstractions and expose functions to operate on their data"
"Data structures expose their data and have no meaningful functions"
It then continues to describe "Hybrids" which are "indicative of a muddled design".
In a framework like MVC, typically a model exposes all of its properties, but also contains functions to operate on its data and do stuff (providing the model isn't just a class of properties). Does this not lean towards a model being a hybrid structure, or am I misunderstanding something?
I have seen Martin's Clean Code video series and I remember in one video when he talked about the Entity-Boundary-Interactor structure he said that entities (so basically your model classes) should only have application independent methods, meaning functions that are valid no matter which application they're used in.
For example, let's say you have a class Line. Some valid methods (in my opinion) would be:
getLength() - that's pretty much what Martin refers to when he says hiding your data behind abstraction I think. It doesn't tell you anything about the actual start and end points, but rather only their distance to each other.
moveBy(double dx, double dy) - that would be a good example of a method that's valid in any application, since it just moves the line by a specified delta. Note that this operates only on the line data and has nothing to do with moving a line on the screen.
This is sort of a methodology question.
When writing software that makes use of object-oriented libraries to abstract OpenGL and the like, should you (or would you) choose to extend the OpenGL helper objects and add your own business logic onto them, or create your basic business objects and then have the OpenGL helpers as a property of them.
For example
Let's say I have an OpenGL library that provides a class
OpenGLBillboard
which draws a 2D sprite that faces the camera
if I have some sort of business object that is going to be rendered using that class, is it wise to simply extend OpenGLBillboard and build on top of it, or should I just have an OpenGLBillboard object that is a property on what is essentially a base class in my software?
It seems like inheritance in this case could be dangerous because if the base class ever has to change due to requirements, the refactoring could be painful ... whereas if I just go the property route, I have a little more upfront boilerplate to write.
Your thoughts?
Thanks
P.S. forgive me for saying "business object". I just didn't want to say "model" a whole lot in a topic about 3D and have people be confused as to my meaning.
Personally, I would probably have my business object contain (privately) a "Billboard" instance, and not tie it directly to OpenGL at all.
The business object would just be asked to render, and redirect it's methods through the Billboard instance. This would allow you to swap out a different implementation (if you decide to go with something other than a Billboard) or a different backend (ie: a Direct3D rendering pipeline) without changing the business object at all.
I’m fairly new to OO. If I have two classes A and B that need to exchange data, or call each other’s methods, I need to be able to access an instance of class B from class A. Should I maintain the address of the instance object in a global variable? Should I appoint a (singleton) master class, and make (pointers to) instances of A and B properties of the master class? (AppDelegate comes to mind.)
Is there a straightforward by-the-book way to implement this? Somehow I‘m missing some "best practice" here. I’ve looked through Apple's examples, but didn't find an answer.
EDIT: Since I'm fairly new to MVC design patterns, my question is essentially "Who creates who"?
We're talking about an Audio Player here. 1. When the user selects a song, the UI displays its waveform by creating a viewController which creates the appropriate view. 2. When the user hits play, the UI displays a timeline while the song is playing by overlaying a new view over the waveform. Now, the latter view needs some info from the waveform display viewController. Right now, I'm storing a pointer to the viewController in an instance variable of my appDelegate. This works, but feels extremely strange.
Should I outsource the info that is needed by both classes to some third entity that every class can access easily?
Classes aren't simply departments of code. They are templates for the creation of objects, which you should think of as actors in your program, doing things within their areas of responsibility (which you define—you decide what each object does) and interacting with each other.
While you can handle a class as you would an object, classes generally do not talk to each other. Most of the time, you will create and use instances of the classes—which is what we normally mean by “objects”—and have those talking to each other. One object sends another a message, telling the receiver to do something or changing one of the receiver's properties. These messages are the interactions between your program's objects.
Those weird expressions in the square brackets are message expressions. Nearly everything you'll do with a class or object will involve one or more messages. You can send messages to classes the same as to objects, and classes can send messages just as objects can.
In Cocoa and Cocoa Touch, you typically have model objects, view objects, controller objects, data objects (such as NSString, NS/UIImage, and NSURL), and helper objects (such as NSFileManager). The classes you'll write for your application will mainly be model, view, and controller objects (MVC). The model represents (models) what the user will see themselves manipulating; the view displays the model to the user; the controller implements logic and makes sure the model gets saved to and loaded from persistent storage.
For more information, see Object-Oriented Programming in Objective-C and the Cocoa Fundamentals Guide.
Since I'm fairly new to MVC design patterns, my question is essentially "Who creates who"?
Controllers create and load the model, and load the views, and pass the model to the view for display. Certain controllers may also create other controllers.
It's good to keep a straightforward tree-like graph of ownership from a single root of your program—typically the application object—down through controllers to leaf objects in the models and views. If two objects own each other, that's a problem. If an object is not owned by anything outside of its own class (a singleton), that's usually a problem as well—a sign you need to think some more about where that code belongs. (Helper objects are the main exception; most of those are singletons. Again, see NSFileManager for an example. But they are few and far between.)
Further situation analysis require more information. At first place you should more specify the relation between classes and what exactly do you mean by exchanging data.
Singletons should be generally avoided. If you want to exchange information it is usually sufficient to provide for example instance of the class A to the instance of the class B by some method or constructor. The instance of B is then capable of calling public methods (and accessing public properties) of the instance of A.
A little bit of "best practices" can be learn by searching up "Design Patterns".
You should decide if one class can be an object of another class (encapsulation), or if one class can inherit from the other class (inheritance). If neither of these is an option, then maybe you could make one class (or some of its members) static?
Thanks for your contributions. Additionally, I found information on this page very useful. It lays out MCV considerations for cocoa in a hands-on way and practical language.
I try to realize a little game project to dive deeper into OO programming (winforms c++/cli).
I already started coding but now I´d like to make a re-design.
For the beginning the game should consist of four parts like game-engine, user interface, highscore and playground. Heres a little (non-UML-conform) class diagramm to visualize my purposes
Would this be the right way?
In my eyes the game engine is responsible to control the game sequences (state machine?) and exchanges information betweens all other classes.
I appreciate any help!
EDIT:
so it´s a really simple game, no big deal! here´s a link of what I made by now:
http://www.file-upload.net/download-2595287/conways_project.exe.html
(no virus :) but I guess you need .NET framwork to get it work)
Unfortunately, your current design sucks :)
I won't say what I will suggest is actually the best solution available, because in game design there is generally "no best" solution, but still I think it would make you think appropriately.
Larger UML here.
alt text http://yuml.me/1924128b
Let's say you have your basic class Game. It's something abstract class, that wraps all your game logics and works as a sort of Swiss knife.
You should create two another classes - UI and State (which, obviously, encapsulate game UI operations and store current game state). Let your Game class hold UI and State instances.
Now, your Game class should have basic methods to control your game. They could be plain render(...) and update(...) methods and this part is actually a bit tricky. If your game is real-time, you would have to update your state every Y milliseconds, so your update(...) should be called in a loop.
If your game isn't actually real-time, your updates should happen only when user does something or you actually know that you need to change something. You could implement a message queue here and update(...) call would simply flush all those messages.
Now, the render(...) method. Create some class and call it Backend - let this class encapsulate all your drawing possibilities. There is one really cool thing here - you could let your Backend be an abstract superclass and create some concrete backends, which derive from Backend. And that would actually give you an opportunity to switch your Backends with simple code manipulations.
After that, you should pass your Backend instance to your render(...) method, which would do appropriate drawing and it's logic could be written the following way:
foreach (const Object& object, game_state) {
object->render(backend); // Or something like that
}
The last thing to mention, your game state. You could have a plain structure to hold all your current objects, score, etc, etc. Let every object access that GameState structure and everything will be fine.
Actually, there are many things to think about, if you wish to, I could write more about this game design approach and share some tricks :)
Your 'Game Engine' would probably be considered more of a 'Math Library.' You might want to insert another object in between 'Game' and the other Server Classes that 'Delegates' the requirements of 'Game' to the Server Classes and call that 'Game Engine'.
Also maybe 'High Score' and 'Playground' could be combined into a Class which represents 'Game State' and port that directly to 'Game.' 'Playground' could be a Server Class which encapsulates any code to do the actual presenting of said background where this would usually represent a 'Rendering Class.'
IMHO
I'll be as direct as I can concerning this problem, because there must be something I'm totally missing coming from a structured programming background.
Say I have a Player class. This Player class does things like changing its position in a game world. I call this method warp() which takes a Position class instance as a parameter to modify the internal position of the Player. This makes total sense to me in OO terms because I'm asking the player "to do" something.
The issue comes when I need to do other things in addition to just modifying the players position. For example, say I need to send that warp event to other players in an online game. Should that code also be within Player's warp() method? If not, then I would imagine declaring some kind of secondary method within say the Server class like warpPlayer(player, position). Doing this seems to reduce everything a player does to itself as a series of getters and setters, or am I just wrong here? Is this something that's totally normal? I've read countless times that a class that exposes everything as a series of getters/setters indicates a pretty poor abstraction (being used as a data structure instead of a class).
The same problem comes when you need to persist data, saving it to a file. Since "saving" a player to a file is at a different level of abstraction than the Player class, does it make sense to have a save() method within the player class? If not, declaring it externally like savePlayer(player) means that the savePlayer method would need a way to get every piece of data it needs out of the Player class, which ends up exposing the entire private implementation of the class.
Because OOP is the design methodology most used today (I assume?), there's got to be something I'm missing concerning these issues. I've discussed it with my peers who also do light development, and they too have also had these exact same issues with OOP. Maybe it's just that structured programming background that keeps us from understanding the full benefits of OOP as something more than providing methods to set and get private data so that it's changed and retrieved from one place.
Thanks in advance, and hopefully I don't sound too much like an idiot. For those who really need to know the languages involved with this design, it's Java on the server side and ActionScript 3 on the client side.
I advise you not to fear the fact, that player will be a class of getters and setters. What is object anyway? It's compilation of attributes and behaviours. In fact the more simple your classes are, the more benefits of an OOP you'll get in the development process.
I would breakdown your tasks/features into classes like that:
Player:
has hitpoints attribute
has position attribute
can walkTo(position), firing "walk" events
can healUp(hitpoints)
can takeDamage(hitpoints), firing "isHurt" event
can be checked for still living, like isAlive() method
Fighter extends Player (you should be able to cast Player to Fighter, when it's needed) :
has strength and other fighting params to calculate damage
can attack() firing "attack" event
World keeps track of all players:
listens to "walk" events (and prevents illegal movements)
listents to "isHurt" events (and checks if they are still alive)
Battle handles battles between two fighters:
constructor with two fighters as parameters (you only want to construct battle between players that are really fighting with each other)
listens to "attack" events from both players, calculates damage, and executes takeDamage method of the defending player
PlayerPersister extends AbstractPersister:
saves player's state in database
restores player's state from database
Of course, you game's breakdown will be much more complicated, but i hope this helps you to start thinking of problems in "more OOP" way :)
Don't worry too much about the Player class being a bunch of setters and getters. The Player class is a model class, and model classes tend to be like that. It's important that your model classes are small and clean, because they will be reused all over the program.
I think you should use the warpPlayer(player, position) approach you suggested. It keeps the Player class clean. If you don't want to pass the player into a function, maybe you could have a PlayerController class that contains a Player object and a warp(Position p) method. That way you can add event posting to the controller, and keep it out of the model.
As for saving the player, I'd do it by making Player implement some sort of serialisation interface. The player class is responsible for serializing and unserializing itself, and some other class would be responsible for writing the serialised data to/from a file.
I would probably consider having a Game object that keeps track of the player object. So you can do something like game.WarpPlayerTo(WarpLocations.Forest); If there are multiple players, maybe pass a player object or guid with it. I feel you can still keep it OO, and a game object would solve most of your issues I think.
The problems you are describing don't belong just to game design, but to software architecture in general. The common approach is to have a Dependency Injection (DI) and Inversion of Control (IoC) mechanisms. In short what you are trying to achieve is to be able to access a local Service of sorts from your objects, in order for example to propagate some event (e.g warp), log, etc.
Inversion of control means in short that instead of creating your objects directly, you tell some service to create them for you, that service in turn uses dependency injection to inform the objects about the services that they depend on.
If you are sharing data between different PCs for multiplayer, then a core function of the program is holding and synchronising that piece of state between the PCs. If you keep these values scattered about in many different classes, it will be difficult to synchronise.
In that case, I would advise that you design the data that needs to be synchronised between all the clients, and store that in a single class (e.g. GameState). This object will handle all the synchronisation between different PCs as well as allowing your local code to request changes to the data. It will then "drive" the game objects (Player, EnemyTank, etc) from its own state. [edit: the reason for this is that keeping this state as small as possible and transferring it efficiently between the clients will be a key part of your design. By keeping it all in one place it makes it much easier to do this, and encourages you to only put the absolute essentials in that class so that your comms don't become bloated with unnecessary data]
If you're not doing multiplayer, and you find that changing the player's position needs to update multiple objects (e.g. you want the camera to know that the player has moved so that it can follow him), then a good approach is to make the player responsible for its own position, but raise events/messages that other objects can subscribe/listen to in order to know when the player's position changes. So you move the player, and the camera gets a callback telling it that the player's position has been updated.
Another approach for this would be that the camera simply reads the player's position every frame in order to updaet itself - but this isn't as loosely coupled and flexible as using events.
Sometimes the trick to OOP is understanding what is an object, and what is functionality of an object. I think its often pretty easy for us to conceptually latch onto objects like Player, Monster, Item, etc as the "objects" in the system and then we need to create objects like Environment, Transporter, etc to link those objects together and it can get out-of-control depending on how the concepts work together, and what we need to accomplish.
The really good engineers I have worked with in the past have had a way of seeing systems as collections of objects. Sometimes in one system they would be business objects (like item, invoice, etc) and sometimes they would be objects that encapsulated processing logic (DyeInjectionProcessor, PersistanceManager) which cut across several operations and "objects" in the system. In both cases the metaphors worked for that particular system and made the overall process easier to implement, describe, and maintain.
The real power of OOP is in making things easier to express and manage in large complex systems. These are the OOP principles to target, and not worry as much whether it fits a rigid object hierarchy.
I havent worked in game design, so perhaps this advice will not work as well, in the systems I do work on and develop it has been a very beneficial change to think of OOP in terms of simplification and encapsulation rather than 1 real world object to 1 OOP class.
I'd like to expand on GrayWizardx's last paragraph to say that not all objects need to have the same level of complexity. It may very well fit your design to have objects that are simple collections of get/set properties. On the other hand, it is important to remember that objects can represent tasks or collections of tasks rather than real-world entities.
For example, a player object might not be responsible for moving the player, but instead representing its position and current state. A PlayerMovement object might contain logic for changing a player's position on screen or within the game world.
Before I start simply repeating what's already been said, I'll point towards the SOLID principles of OOP design (Aviad P. already mentioned two of them). They might provide some high-level guidelines for creating a good object model for a game.