Breaking Down a Problem by Building Helper Methods
As programs become more complex, one lesson that I have learned is that it is important to break a complex problem down into smaller components. When I was reading through the Flatiron course materials, one particular lesson advised us to keep our methods five to lines or fewer. After overcoming some initial dismay when reflecting on the 10-line methods I had been creating earlier that week, I decided to zero in on ways that I could make my code more concise and bite-sized. While creating methods, now I consider how I might be able to refactor the complex methods into smaller “helper methods” that are more reusable, and thus more functional.
In a problem that I was working with yesterday, I was creating several models to simulate different relationships in an IMDB-type app. In this app, there are movies, characters, and actors. Movies have many characters, and characters can be in multiple movies. Actors can also play more than one characters. For the sake of this particular problem, we will assume that characters can only be played by one actor (they “belong to” an instance of the Actor class). Here is a diagram of these relationships:
For the Movie class, the problem asked that I write a class method .most_actors that returned a Movie that had the most Actors in it. In order to this, I would have to complete the following steps:
- Create a list of Characters in a particular instance of a Movie (through the MovieCharacter table).
- Create a list of Actors who play the Characters from list in Step #1.
- Iterate through all Movie instances and return the Movie instance with the highest number of actors.
I could write all of this in one method, but I decided that it would be more fruitful to break down the different steps into concise methods that could later be used again in other complex methods.
For Step #1, I created a helper method called #characters that collected all characters that appeared in that Movie instance.
Next, for Step 2, I wrote a helper method called #actors that looped through the #characters method and returned an array of corresponding actors who played those characters in a particular Movie instance. I wanted to make sure that all actors were unique, so I included a conditional statement that checks if the actor is already in the array (line 38).
Once I had written these building blocks, I was able to call upon the #actors method to find the Movie instance with the highest number of actors in .most_actors method.
In this method, I iterate through all the Movie instances, then find the Movie instance with longest array of actors (by calling the #actors) method. By drawing upon the helper method #actors, I was able to keep my .most_actors method concise and readable. Additionally, I also creating other Lego blocks of code that I could later use to create other higher-order methods.
Moral of the Story: Breaking Methods Down into Smaller Methods Can Create More Functional and Enduring Programs
Not only is it important to understand the steps of achieving a certain goal in a program, but a coder can also translate those steps into concise helper methods that are reusable later on. Creating more functional building blocks leads to more sustainable code that can continue evolving to execute more complex tasks.