Everything is an object in ruby.
Thus visualising everything as an
object and modeling your problem based on the principles of Object
Oriented Programming (OOP) becomes very important.
During my second week at
Codeignition, we started with a very simple problem and then extended it
everyday to understand some OOP principles such as inheritance,
namespacing and method overriding. Thanks to our mentor, Shobhit Srivastava, some software
engineering skills always step in to show us the beauty of this world in
bright sunlight and this time they were-
- Test Driven Development, lovingly known as TDD,
- Don't Repeat Yourself, the DRY principle and
- Pair programming.
The basic problem given to us was- Problem - Coordinates of two points are given, return length of line segment formed by the points.
Simple! Isn't it? Solution to above problem will be a Line class which have attributes start_point and
end_point and a method length which gives distance between these two points. We can implement above class either based on the assumption that coordinates of these two points are given to us in the form of two arrays, i.e. [x1,y1],[x2,y2] or that we are given coordinates as x1,y1,x2,y2.
Now, one could argue that Points are separate identities themselves and
the method Line#length does nothing but returns distance between two
instances of Point class. So our solution can be refactored to add Point
class with attributes x_coordinate, y_coordinate and a class method
distance_between point1, point2.
Writing Ruby code- The conventions!
One can make any number of classes in a single ruby file, write logic in
this file and get it executed. But such code is hard to understand and tough to debug.
Thus, we have conventions. When everybody follows some conventions, all our folder
structures are alike, which in turn makes collaborated works easy.
An easy to maintain, clear folder structure for Ruby projects is-
All our classes and modules that means functionality goes in lib folder.
That means if we want to make a class named Line for our given problem,
it goes in Line.rb file in lib folder. Class names in ruby are
conventionally written in CamelCase while method names are written in
snake_case. Conventionally one file has one class. So lib folder will
contain two files Line.rb and Point.rb as per the solution discussed above.
Now, while working on any project in any programming language, we should
always follow Test Driven Developement(TDD) approach. When our projects
grow bigger, our code base increases, the specs we had written for each
small unit of our code are our only friends in debugging. If you are new
to TDD and don't see any benefit for why you should follow TDD, visit my
friend Debashish's blog here.
So all our specs go in spec folder. We write one spec file for each ruby
class file as classname_spec.rb in spec folder.
There are many libraries available for testing in ruby. One of the ones
that has gained popularity and use is RSpec. To use RSpec, we write a
Gemfile for our project. Gemfile is the place where we write all our
dependencies for the project. A sample Gemfile, one for our current
project will be -
When we write
Bundler looks up to the source "https://rubygems.org" for the gems we declared. We can
mention multiple sources and bundler will look up in those sources in
order. Bundler installs specified versions of gems if mentioned and
latest stable realeases of gems if versions are not specified.
After running bundle install, a Gemfile.lock file is
created in current directory. This file is the place where Bundler
records the exact versions of gems that were installed. In this way, it
is ensured that when we install the dependencies on some other machine
for the same project, bundler will look into Gemfile.lock file for the
versions of gems to be installed rather than installing latest stable
releases of all the gems.
This way gemfile and bundler manage our dependencies. And folder
structure keeps our code clean and more readable. We will look into rake
tasks and an extended exercise on Object Oriented Design based on our
problem in next blog. Till then,