One Easy Trick to Understanding Object Relations in Ruby
One of the first obstacles to understanding Object Oriented Programming (OOP) in Ruby, is visualizing how objects relate to each other. In the first week at Flatiron School, you move quickly from isolated class-level objects, to objects that “belong-to” other objects who “have-many” objects that “belong-to” them. Finally, by the end of the week, you start working with objects that “have-many” objects through objects that also “have-many” objects. Lyft drivers, for example, have many passengers and Lyft passengers have many drivers. How are these two groups related to each other? They are connected through rides. But before ever writing a line of code, how do we make sense of these relationships? We diagram them!
One of the most important abilities of a developer is being able to represent complex data relationships visually, whether you’re drawing it out on a whiteboard or in your notebook. By making a habit of diagramming object associations, we can build rich connections in our programs and keep them bug free. Beginning with a simple schema we can start to visualize how our object relationships will take shape.
In our Lyft example, drivers and passengers are related to one another through rides. The easiest way to figure this out is by drawing out our ride, passenger, and driver classes. By diagramming out the three classes, we can see that passengers and rides related through drivers, or drivers and rides through passengers. Because the ride belongs to both the passenger and the driver, we know that the single-source-of-truth (SSOT) of our driver-passenger relation should be the ride. So in our diagram we put Rides as the middle object, which Passenger and Driver relations pass through.
Here we can see that many drivers are related to many passengers through rides — their relationship passes through it. Most simple economic transactions like those between a customer and waiter, a guest and an Airbnb listing, are fairly straightforward; both sides of the interaction have a relationship with each other through the transaction.
When I was preparing for the Mod 1 code challenge one of the things I did to prepare was simply diagram object oriented relationships when I was too tired and burned out to code all the associated methods. Based on their difficulty, each exercise would describe the relationships between models in more or less detail, and some examples had even four or five models to work with.
One of the more difficult models we were given is the example of a bakery that has many desserts that are made up of many ingredients. This exercise is not a simple “has-many-through” transactional relationship. Many desserts belong to the bakery, which are made up of many ingredients, that belong to the desserts. The bakery has many ingredients through desserts. We can imagine this almost like a tree, with the top representing the bakery, branching off wider as we go down into desserts and ingredients.
In this example, because we know that an object is the single source of truth about the object it belongs to, desserts are initialized with a bakery object and ingredients are initialized with a dessert object. Through desserts, we know that the bakery class will be able to get information about the ingredients it needs. By diagramming the relationship between objects we are able to organize our classes, and keep track of what will be initialized by our attribute macros before we even define them.
One of the other difficult object relationships in the practice exercises, rated “hard”, involved clients, locations, and trainers of a chain of gyms. In our gym model, locations have many trainers and clients, and clients and trainers can work out of any location, but clients have one trainer. Because clients can go to any of the gym’s locations, they are limited to the trainers available that day. I struggled with mapping out these relationships and understanding how clients are related to locations through trainers. But because I took the time to diagram the relations before writing a bunch of code that I wasn’t sure about, I saved a lot of time I might have spent on fixing mistakes in my object relations.
By the end of the second week at Flatiron School we learn that the associations between classes that we expressed in code can be simply automated by using Active Record. But this doesn’t make diagramming any less important! As the associations between classes, and their tables, become even more complex we can express this complexity through macros like hasandbelongstomany, but it becomes even more necessary to visualize how these associations take shape as you enter Mod 1 project week. If you practice diagramming your model relationships from the beginning of Objected Oriented Ruby, drawing out the schema for your project should be a breeze.