{"id":35692,"date":"2016-12-13T06:00:09","date_gmt":"2016-12-13T11:00:09","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=35692"},"modified":"2016-12-15T07:11:41","modified_gmt":"2016-12-15T12:11:41","slug":"object-oriented-debate-part-2-okay-so-what-is-oop","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=35692","title":{"rendered":"Object-Oriented Debate Part 2: Okay, so what is OOP?"},"content":{"rendered":"<p>To discuss what Object Oriented Programming is, let&#8217;s discuss the problem it was designed to solve. Well, let&#8217;s get as close as we can to an explanation while keeping this readable for non-coders.<\/p>\n<p>Originally, programming was procedural&#8230;<\/p>\n<div class=\"dmnotes\">Note: This is different from the kind of &#8220;procedural&#8221; you find in No Man&#8217;s Sky or FUEL. In those games, when we say &#8220;procedural&#8221; we mean the art assets are created by the program using a set of procedures. In the field of writing code, when we say &#8220;procedural&#8221; we just mean a program is nothing more than a set of procedures to follow, one after the other.  It&#8217;s the most obvious and direct way to go about writing software: You tell the computer what to do.<\/div>\n<p>&#8230;but the problem (the argument goes) is that procedural programming (PP) can get out of hand in terms of complexity. <\/p>\n<p>Let&#8217;s say we&#8217;ve got a game. We&#8217;ve got a big list of (say) space marines taking part in the simulation. Each space marine is nothing more than a block of data describing where it is, how it&#8217;s moving, what weapon it has, how many hit points it has, what team it&#8217;s on, what it&#8217;s AI is up to, what character model it&#8217;s using, if it&#8217;s dead, and so on. <\/p>\n<p>Here, let&#8217;s make up a pretend data structure to hold our marine:<\/p>\n<p><!--more--><\/p>\n<pre lang=\"cpp\" line=\"1\">\r\nstruct space_marine\r\n{\r\n  char*      name;\r\n  int        character_model;\r\n  int        current_weapon;\r\n  int        ammo;\r\n  bool       dead;\r\n  int        hitpoints;\r\n  vector3d   location;\r\n  vector3d   velocity;\r\n  int        animation;\r\n  int        animation_frame;\r\n};\r\n<\/pre>\n<p>Somewhere else in our code we&#8217;ll loop over all the space marines and see if they&#8217;ve been crushed under any vehicles. Another bit of code checks to see if they&#8217;ve been hit with bullets. Another checks if they&#8217;ve been eaten by aliens. Another checks to see if they have picked up weapons. Using vehicles. Interacting with doors. Reaching checkpoints. Using cover. Often these systems need to change the space marine in same way. If they get hit with bullets they need to take damage. If they are knocked into the air they need to play a new animation. And so on.<\/p>\n<h3>The first problem.<\/h3>\n<p>Every single programmer that writes code to change the state of a space marine needs to know exactly how the internal systems of a space marine works. If they don&#8217;t, then they will write code in a way that makes sense to them, but doesn&#8217;t work with the code that already exists.<\/p>\n<p>The guy coding the &#8220;getting crushed by machinery&#8221; code just subtracts a million hitpoints when a marine is crushed. He didn&#8217;t notice the variable called &#8220;dead&#8221;, which is what actually causes the marine to <b>behave<\/b> like it is dead. You&#8217;re supposed to see if HP is at or below zero, and then set the variable &#8220;dead&#8221; to &#8220;true&#8221;. Since this programmer didn&#8217;t, you wind up with a bug where a character has negative one million hitpoints and yet is still running around alive. <\/p>\n<p>Maybe another coder comes along. She&#8217;s a little more careful, so when she writes a new system for characters running into forcefields she notices the &#8220;dead&#8221; variable and correctly intuits what she&#8217;s supposed to do. However, she writes it so that the &#8220;dead&#8221; flag is set if hitpoints are <b>below<\/b> zero. Which means that if you&#8217;re damaged by a forcefield, it&#8217;s possible to have exactly zero hitpoints and still be alive, while most other kinds of damage kill you at or below zero. This creates annoying inconsistencies that are hard to track down. <\/p>\n<p>Our space marine example above is pretty simple, but in real applications things aren&#8217;t always this straightforward. In my game <a href=\"http:\/\/www.shamusyoung.com\/goodrobot\/\">Good Robot<\/a>, the data structure for enemy robots has over 70 fields in it. And that&#8217;s just a simple 2D game. As the data becomes more complex, it becomes unreasonable (and infeasible) to expect that every programmer on the project should be able to fully understand every data structure. As the number of different types of data (space marines, weapons, vehicles, multiplayer connections, particle emitters, physics objects, HUD elements, projectiles, menus, etc etc etc.) grows it becomes difficult for any one person to get a a handle on the whole thing and how it all connects. <\/p>\n<p>So now you&#8217;ve got half a dozen people all interacting with data structures they don&#8217;t fully understand, which can lead to bugs. This leads us to&#8230;<\/p>\n<h3>The second problem.<\/h3>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/ood_spacemarines.jpg' width=100% alt='These guys are bad dudes who don&apos;t play by the rules. Specifically, they clip through scenery, get stuck on terrain, or end up locked into a fixed pose while running.' title='These guys are bad dudes who don&apos;t play by the rules. Specifically, they clip through scenery, get stuck on terrain, or end up locked into a fixed pose while running.'\/><\/div><div class='mouseover-alt'>These guys are bad dudes who don&apos;t play by the rules. Specifically, they clip through scenery, get stuck on terrain, or end up locked into a fixed pose while running.<\/div><\/p>\n<p>In PP, any part of the code can act on any bit of data at any time. <\/p>\n<p>Let&#8217;s say a bug crops up. At the end of a game loop you find a space marine is in an invalid state. Maybe it has a negative one million hit points, yet isn&#8217;t marked as &#8220;dead&#8221;. Or perhaps it has a negative number of bullets. Perhaps it&#8217;s far outside the game area, or swimming when it shouldn&#8217;t be. Maybe they&#8217;re holding a six-shooter that somehow has 400 bullets in it.<\/p>\n<p>The programmer discovers this incorrect state, but they have no idea where in the code this might have happened. A hundred different systems modify space marines every frame. There&#8217;s no way to even begin the search for the problem. As the number of systems that can act on one another grows, the program quickly becomes a terrifying mass of chaos.<\/p>\n<h3>Managing State<\/h3>\n<p>In the most abstract sense, the program is nothing more than a bunch of logic designed to change the state of variables. At one point in Half-Life 2 Gordon Freeman is running around the city with no weapon, and at another point he&#8217;s out in the abandoned highway, running over combine soldiers in his laser buggy. It&#8217;s still the same program. The only thing that&#8217;s changed are the values stored in all the variables. A particular arrangement of variables is called the &#8220;state&#8221; of the program. A program like Half-Life 2 does a lot of changing state. A lot of bugs are the result of some unforeseen change in state.<\/p>\n<p>Maybe your game is processing animations for various objects in the scene. A door moves along its open animation and bumps into an explosive barrel. It nudges the barrel, which suddenly can&#8217;t cope with the fact that it&#8217;s sharing space with another object. This triggers an explosion, which kills the player character.<\/p>\n<p>Meanwhile, somewhere in the high-level code of the game we might have something like this:<\/p>\n<pre lang=\"cpp\" line=\"1\">\r\n\/\/See if the player is dead.\r\nif (player.Dead ()) {\r\n  OpenGameOverMenu ();\r\n  return; \/\/no need to process the scene from here.\r\n}\r\nUpdateAnimations ();\r\nUpdatePlayer ();\r\nUpdateAI ();\r\nUpdateNetwork ();\r\n<\/pre>\n<p>On line 2 we abort processing if the player is dead. Because of this, we assume the player MUST be alive when we update them on line 7. But in the scenario above, we found an edge case where the player could die during the animation update. <\/p>\n<p>It&#8217;s not possible for a programmer to understand how every object in the game can impact every other object in every situation, and it&#8217;s certainly not possible for them to grasp all of the cascading changes that might result from interconnected systems. Which means they probably didn&#8217;t ever imagine that it would be possible for the player character to be dead when we reach line 7. All of the code in UpdatePlayer () is probably written under the assumption that the player is 100% guaranteed to be alive at this point.<\/p>\n<p>We refer to this problem as &#8220;side effects&#8221;. Running a bit of code has unexpected side effects on the state of the program, and there&#8217;s no way to account for all of the possible side effects of any given action. The systems are too large, the connections between them are too numerous, and the possible side-effects are too complex to be fully understood. The above example is trivial(ish) to detect and fix, but in a real game subtle stuff like this can hide in the crevices of the structure and bedevil our poor programmer.<\/p>\n<h3>The Solution<\/h3>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/ood_objects.jpg' width=100% alt='These represent class objects. Look, just go with it.' title='These represent class objects. Look, just go with it.'\/><\/div><div class='mouseover-alt'>These represent class objects. Look, just go with it.<\/div><\/p>\n<p>Here is where we see the desire to use Object-Oriented programming. Instead of a program where any part of the software can reach in and modify any part of a space marine at any time, we hide all of those internal variables away and build an interface for them.<\/p>\n<p>We create a &#8220;class&#8221; called SpaceMarine, we stick the variables inside of it, and we lock those variables away so that other parts of the program can&#8217;t change them whenever they like. Then we build an interface &#8211; a set of controls &#8211; by which other programmers can manipulate a SpaceMarine. The variables are essentially in a black box and (we hope) the object can be used without knowing how it works on the inside.<\/p>\n<p><a href=\"?p=35550\">Back in November<\/a>, I talked about building a good API. At the time I said:<\/p>\n<blockquote><p>There is a certain art to making a good API. You want the controls to be as simple as possible without taking away functionality. A well-designed library should be obvious to use and shouldn&#39;t require you to worry about any messy details of what might be going on inside of that black box.<\/p>\n<p>When you&#39;re using a toaster, you don&#39;t care about the voltage the device is using, the temperature of the heating coils, or the specific electrical resistance being used by the heating elements. You just know you want your toast to be medium. If a toaster forced you to worry about all those details, then the controls would be too complicated. If it just had an on and off button with no way to choose how dark to make the toast, then it would be too simple. A good API should be designed to hit that sweet spot between complexity and features, and it should gracefully hide everything you don&#39;t need to worry about.<\/p><\/blockquote>\n<p>Making a good API has a lot in common with a good class interface. In both cases you&#8217;re trying to insulate the other programmer from needing to know too much about how something works internally.<\/p>\n<p>To solve the problem we had above:<\/p>\n<p>You can&#8217;t change a SpaceMarine&#8217;s hitpoints directly. Now there are a couple of functions to do this for you. Maybe you&#8217;ll call SpaceMarine.Damage(<i>value<\/i>) and SpaceMarine.Heal(<i>value<\/i>). Now you don&#8217;t need to know about the dead flag. When you inflict damage, the SpaceMarine does some internal checks and will mark <em>itself<\/em> as dead if needed.<\/p>\n<p>This is good. Now rules are enforced consistently for all types of damage, and coders don&#8217;t need to carefully study a page of space marine data before they know how to properly interact with it. <\/p>\n<p>This solves half of the problem. The other half of the problem is solved by creating object hierarchies. SpaceMarines belong to (say) some new system that&#8217;s in charge of managing actors in the scene. Maybe the person writing this new code takes a cue from Hollywood and names this thing the Director. So only the Director is allowed change the state of the marine by calling things like Damage() or Heal(). If some system needs to alter a SpaceMarine, they have to go through the Director.<\/p>\n<p>This supposedly solves the problem where playing a door opening animation might result in a dead SpaceMarine due to cascading side effects. <\/p>\n<p>Next time I&#8217;ll get into <a href=\"https:\/\/www.youtube.com\/watch?v=QM1iUe6IofM\">the original arguments<\/a> that Brian Will brings up.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>To discuss what Object Oriented Programming is, let&#8217;s discuss the problem it was designed to solve. Well, let&#8217;s get as close as we can to an explanation while keeping this readable for non-coders. Originally, programming was procedural&#8230; Note: This is different from the kind of &#8220;procedural&#8221; you find in No Man&#8217;s Sky or FUEL. In [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-35692","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/35692","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=35692"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/35692\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=35692"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=35692"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=35692"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}