Development Journal

Student at Flatiron School NYC

Modules and Method Encapsulation

Week four at the Flatiron School began with a Columbus Day catch up session on Monday. We did not have lectures but campus was open for us to work on older assignments.

My group – Team High Five – spent the day putting together a picture matching game as a way to practice working with the Nokogiri gem as well as ERB files and HTML template generation.

Yesterday, we had our first look at Modules during lecture. Modules are a Ruby construct that allows us the ability to share features and method sets between objects. Unlike classes, which only allow for singe inheritance in Ruby,modules can be required as need. Interestingly enough, classes actually inherit from modules. Per my command line just a moment ago:

1
2
3
ruby -v -e "p Class.ancestors"
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.3.0]
[Class, Module, Object, Kernel, BasicObject]

Up until this point at Flatiron, we have been including methods within the body of our classes that we have had to repeat again and again. Modules help us to avoid this an allows us to share methods between multiple classes.

when to use which

Since the construct class describes an object and a module describes abilities, the first rule of thumb we can use is that if we find ourselves building classes that never are used to create an instance of that class, then we should be using a module. Another use case for a module is when we have built a method set we know many classes are going to need. We can encapsulate these behaviors in a module. I like to think of modules as gems for our classes. Let’s take a look at some code from last week.

1
2
3
4
5
6
7
8
9
class Student
  def self.find_by_name(name)
    @@all.select { |s| s.name == name }
  end

  def self.find(id)
    @@all.select { |s| s.id == id }.first
  end
end

The code above represents two methods of a 70-line Student class. We had been using a class level variable all to store every instance of the Student class. As our domain would be expanding throughout the assignment, this same functionality would be desired for many objects in the domain such as Teachers or Lectures. Since I want to share these methods among many classes but don’t want to build a rigid inheritance chain, I can create a module called findable and mix it into my classes as needed.

1
2
3
4
5
6
7
8
9
module Findable
  def find_by_name(name)
    @@all.select { |s| s.name == name }
  end

  def find(id)
    @@all.select { |s| s.id == id }.first
  end
end

Now as my school domain project grows, I can just include the Module Findable .

1
2
3
class Teachers
include Findable
end

Going forward, the use of modules will help us keep our inheritance structure succinct and extendable.