So far in this series, we’ve discussed object-oriented programming in general, and the OOP principle of cohesion. In this article, we’ll look at the principle of coupling and how it helps in game development.
Note: Although this tutorial is written using Java, you should be able to use the same techniques and concepts in almost any game development environment.
What Is Coupling?
Coupling is the principle of “separation of concerns”. This means that one object doesn’t directly change or modify the state or behavior of another object.
Coupling looks at the relationship between objects and how closely connected they are. A Relations Diagram is a great way to visualise the connections between objects. In such a diagram, boxes represent objects and arrows represent a connection between two objects where one object can directly affect another object.
A relations diagram
A good example of coupling is HTML and CSS. Before CSS, HTML was used for both markup and presentation. This created bloated code that was hard to change and difficult to maintain. With the advent of CSS, HTML became used just for markup, and CSS took over for presentation. This made the code fairly clean and easily changeable. The concerns of presentation and markup were separated.
Why Is Coupling Helpful?
Objects that are independent from one another and do not directly modify the state of other objects are said to be loosely coupled. Loose coupling lets the code be more flexible, more changeable, and easier to work with.
A loosely coupled system
Objects that rely on other objects and can modify the states of other objects are said to be tightly coupled. Tight coupling creates situations where modifying the code of one object also requires changing the code of other objects (also known as a ripple effect). Tightly coupled code is also harder to reuse because it can’t be separated.
A tightly coupled system
A common phrase you’ll hear is “strive for low coupling and high cohesion“. This phrase is a helpful reminder that we should strive for code that separates tasks and doesn’t rely heavily on each other. Thus, low (or loose) coupling is generally good, while high (or tight) coupling is generally bad.
How to Apply It
Asteroids
First, lets look at the objects of Asteroids and how they are connected. Recall that the objects are a ship, an asteroid, a flying saucer, and a bullet. How are these objects related or connected to each other?
In Asteroids, a ship can fire a bullet, a bullet can hit an asteroid and a flying saucer, and an asteroid and a flying saucer can hit the ship. Our relations diagram then looks as follows:
As you can see the objects are all pretty well interrelated. Because of this, we have to be careful of how we write the code, otherwise we will end up with a tightly coupled system. Lets take for example the ship firing a bullet. If the ship were to create a bullet object, keep track of its position, and then modify the asteroid when the bullet hits, our system would be very tightly coupled.
Instead, the ship should create a bullet object, but not worry about it after that point. Another class would be responsible for keeping track of the bullet’s position as well as what happens when a bullet hits an asteroid. With an intermediary class in between our relationships, the diagram would look as follows:
This relations diagram looks a lot better and creates a very loosely coupled system. In this system, if we were to add an object, such as a meteor, we could easily do so without having to change how the ship or bullet objects function – we’d just let our intermediary class take care of it all.
Tetris
Since there is only one object in Tetris, the Tetrimino, coupling isn’t really a problem as there cannot be any relationships with other objects.
Pac-Man
For Pac-Man, tight coupling could occur when Pac-Man eats a power pellet. When a power pellet is eaten, Pac-Man can then eat ghosts and the ghost’s state changes to eatable
. If the Pac-Man object were to track when it ate a power pellet and then initiate the change state of each ghost, the system would be tightly coupled.
Again, another class is required to keep track of this information and process it so that our objects can be loosely coupled. Below is an example of how an intermediary class could track Pac-Man eating a power pellet.
/** * Intermediary Class that keeps track of game events */ public class Game { ... if (Pac-Man.eats(Power_Pellet)) { Ghosts.changeState(); } ... }
Conclusion
Coupling is the principle of reducing how objects directly affect the states and behaviors of other objects. Coupling helps to create code that is easier to read as well as easier to change.
In the next Quick Tip, we’ll discuss the principle of encapsulation and why it helps with creating maintainable code. Follow us on Twitter, Facebook, or Google+ to keep up to date with the latest posts.