Advertisement

Snake using SDL

Started by February 20, 2017 03:55 PM
9 comments, last by Oberon_Command 7 years, 9 months ago

This being said, writing getters and setters like this is often a code smell. The purpose of encapsulation is to enforce design contracts. If you have a private member variable that's hidden behind get and set functions that do nothing but get and set that variable, you have effectively made that variable public in a complicated way - there isn't any kind of design contract being enforced by the get/set functions, so you should either rethink making the variable private or rethink the design that led to you needing both the get and the set. On classes that aren't just aggregations of data, preferably the latter first.


This is something that has always confused me and is the biggest stumbling block for my adoption of OOP. It's been said that, for example, the player class has no need to call the physics or rendering engines, and yet, both of those require player data, like position. So, player->render() is bad OOP, but so it renderer->render(player). In order for the latter to work, the data from the player class would need to be retrieved by the render member function via getters.


There are more options than you've mentioned. Two goals: players shouldn't need to know about the renderer's existence until it's time to render them, and renderers shouldn't have behaviour specific to players - that behaviour belongs in the player or the subsystem that owns player data.

So, we could do:

- player->render(renderer). Here the player uses the provided renderer interface to draw itself. This is nice because we could have multiple renderers, and the player isn't tied to either of them.

- renderer->render(player->generate_draw_call()). Here we have some sort of high-level "draw command" structure (which would be just data, no methods or private fields) and have the player generate one, then pass it to the renderer. Now neither the player nor the renderer know anything about each other, but you have this extra data structure in play. That can be to your advantage if you want to do nice things like queue up and sort your draw calls before actually pushing them to the GPU, or do visibility testing/culling in a separate pass. It would also let us built up a queue of things that need to be drawn without knowing about the renderer, and pass that to the renderer somewhere else.

This topic is closed to new replies.

Advertisement