Project Ramon

A learning journey from a Ruby noob perspective

Class Pass – Has access been granted?

I’ll start this post off with an excerpt from Satish Talim’s access control chapter at  Ruby Learning.

The only easy way to change an object’s state in Ruby is by calling one of its methods. Control access to the methods, and you have controlled access to the object.

A good rule of the thumb is never to expose methods that could leave an object in an invalid state.

The last sentence in the above quote can be achieved by properly defining an interface. When looking for a way to explain what this could look like in a ‘real-life’ scenario, I was only too happy to reach for my copy of Sandi Metz’s book Practical Object-Oriented Design in Ruby.

In chapter 4 she gives a detail filled, ‘real-life’ analogy about defining interfaces. Here’s a quick excerpt about a restaurant kitchen. You’ll have to buy your own copy of her book in order to receive her entire analogy, and the other gems of understanding she dispenses throughout its entirety.

The kitchen does many things but does not, thankfully, expose them all to it’s customers. It has a public interface that customers are expected to use; the menu. Within the kitchen many things happen, many other messages gets passed, but these messages are private, and thus invisible to customers.

The idea behind this is to base programming logic on the interfaces of the objects used, rather than on internal implementation details.

Wikipedia says the following about software interfaces in object-oriented languages.

In object-oriented languages, the term “interface” is often used to define an abstract type that contains no data, but exposes behaviors defined as methods.

Lets pull up our Automobile class that we’ve been slowly building over the past two posts.

I’ll start with a class definition, an initializer method, and two instance methods:

The two instance methods defined in our Automobile class are methods that perform work on how to start and stop our Automobile object. From my understanding of Satish Talim’s excerpt at the beginning of this post. I will be better served (I’ll describe what I’ve read about technical debt a little later on) by hiding any moving parts, or methods that perform calculations, in a public interface. In hopes of a slightly better demonstration, I’m going to add a few more methods to our Automobile class.

Now that I’ve added a few more methods to our Automobile class, hopefully its becoming evident that there are a couple bundles of functionality that exist. In Ruby there are three levels of protection in regards to method access control.

These three levels of access control are:

  • Public
  • Protected
  • Private

Public methods –  can be called by any object, as there is no enforced access control at this level.

Lets take a quick peak at an Automobile object calling any one of the methods, since as of now, they’re all listed with Ruby’s default access level, ‘public’.

I’ll use ‘start_engine’ to kick things off:

Ok, so Ruby defaults to ‘public’ access methods, how would we make some of our methods ‘protected’ or ‘private’?

Protected methods – Can only be invoked by an object’s class or subclass.

Private methods – Cannot be called with an explicit receiver (i.e. a variable containing an Automobile instance). With private methods the receiver is always self.

Turns out that there happens to be a couple of ways to label the access-level of our methods, here’s the first way:

Above I gave protected access to ‘start_engine’ and ‘stop_engine’. As shown above I passed symbols of both method names to the ‘protected’ keyword. I did the same with the methods that I gave ‘private’ access control over.

The second way to pull this off looks like so:

Here, I slightly re-arranged the order of my method definitions. I placed ‘drive’ just under my initializer so that the preceding keywords wouldn’t affect Ruby’s default public access that I want it to maintain. And then I placed the keyword just atop of the methods I wanted the keyword to cover, only adding another keyword to make the distinction that all following methods will be affected by it. That’s all there is to it!

The advantage of creating an interface is to decrease technical debt.  Creating an interface consists of public descriptive methods that house protected or private implementation methods but hide their details. This way any alterations to implementation can be isolated to the tucked away implementation methods, and the interface can stand as is, to be used throughout the program.

In a future post I will elaborate on how to put all of this to work.

Advertisements

Categories: AirPair, Newbie, Ruby, Ruby on rails

Tags: , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s