Practical Object Oriented Design for Ruby

In the past week at Launch Academy we dived into object oriented programming. Here is a definition by tutorialspoint.

Ruby is pure object-oriented language and everything appears to Ruby as an object. Every value in Ruby is an object, even the most primitive things: strings, numbers and even true and false. Even a class itself is an object that is an instance of the Class class.

My definition is classes are there to help organize and structure the program so that it may be easily consumed by others. Todays post is about POODR that adds on top of my definition. It is a way to organize and structure program so that it may be easily consumed AND changed as new features are added.

I love that! As programmers, not only should we be thinking to making a working app, but also an app that has low replacement cost in the future. The idea is to write code that is SOLID (Single responsibility, Open-closed, Liskov substitution, Interface segregation, and Dependancy Inversion). I’m currently focusing on the single responsibility section of the SOLID. I find it difficult as a programming beginner to write classes that are loosely coupled as I want them to be. I started with classes that were family and knew everything about each other. However, with some easy to implement tricks and tips from the book I am learning to write more loosely coupled programs.

For instance, I wrote a program about a company with many employees, who wanted to know if their employee owed taxes or was due a refund. My first instinct was to create a company class and an employee class. I was having difficulty of instantiating a single employee. The problem was that I was iterating and saving the employees into a single hash, then passing the hash to the employee class. This caused 2 problems. First all my employees were a single instance. Second, because they are a single instance when I passed in the instance to the Employee class, the employee class was not reading in 1 employee at a time, but the whole slob.

class Company

def load_data(file)

employees = [] CSV.foreach(file, :headers => true) do |row|

employee = row.to_hash

employees << employee

end

employees

end

end

Employee.new(employees)

For an experienced developer the solution was right in front of them. The fix was quite simple. I just needed to change where I was instantiating the object. The previous code changed to the following.

class Company

self.load_data(file)

employees = [] CSV.foreach(file, :headers => true) do |row|

employee = Employee.new(row.to_hash)

employees << employee

end

employees

end

This instantiates each employee separately as I pull data from the CSV file. Now when I pass my employee to the Employee class, it will be of 1 instance of an employee. The benefit is that I won’t have to do an iterator in my employee class but instead I can iterate inside my company class.

Another trick I found very useful was passing in hashes as arguments instead of a multiple variables. The benefits are that you don’t have to worry about in what order you pass in the arguments. If you don’t pass in a value for a specific instance, you can simply give it a default value.

class Employee

def initialize(arguments)

@employee = arguments[‘employee’] || ‘missing name’ @tax_owed = arguments[‘tax_owed’] || ‘0’ @tax_paid = arguments[‘tax_paid’] || ‘0’

end

end

Hope you learned something from that. If you have any cool tricks feel free to share in the comments.


Happy coding!

John