📜 ⬆️ ⬇️

Sandy Metz and Object-Oriented Design in Ruby

Hello, dear readers.

We would like to ask if everyone has already read the excellent Ruby book by the author Sandy Metz in the original, or its translation is still relevant and awaiting.


')
Under the cut, you will find a translation of a rather subjective, enthusiastic article written under the impression from the book in September 2015. At the time of publication of the original, the author has not read the book yet, but already enjoyed it completely. Perhaps we will try to do it - according to the results of a survey in which you participate.

Talk to the rubists - and most of them will speak very positively about the book "Practical object-oriented programming in Ruby." I have been programming for a long time, but I started with procedural languages, so when I ran into objects and classes, I immediately preferred to retire. Having completed the course at the Flatiron School, I learned a lot about the basics of the PLO, but I still wanted to get a better understanding of the nuances. So I decided to take a volume of Sandy and how to smoke it. Having finished only about a quarter of the booklet, I completely understood everything.

Very cool when an experienced developer like Sandy in such a beautiful language shares his experience gained in more than 30 years of professional career. In addition, it is very cool to see how it consistently demonstrates several stages of refactoring (and not just a good code), starting with the real anti-pattern. So, enough prefaces; Now I will talk about the most interesting details that I already learned from the first chapters of the book:

Classes and methods should work on the sole responsibility principle and perform the minimum possible task.

Many have heard about this before, but it is worth emphasizing once again: one of the main advantages of a correct object-oriented code is that it resembles a constructor of interchangeable components that other programmers will work with in the future. If you implement the OOP code well, then this usually means that you will be able to refine, add and delete without cascading throughout the entire code base, which can turn into a nightmare. The principle of DRY (“not to repeat”) is beautifully woven into such a paradigm, since it is during the drying of the code that the program has to be divided into small unique components.

It can be very difficult to determine how to divide the code into classes and areas of responsibility, but Sandy suggests a couple of good rules:

  1. Try to describe the purpose of a class in one statement, without AND or OR. If it does not work out - try to remake the class.
  2. As for the behaviors that are implemented in your class, try asking questions to his various methods and check how meaningful they sound. For example, "Appointment (meeting - approx. Lane.), What time you will be held?" - Normal. But “Meeting, what is your area in centimeters?” - it is already suspicious, probably, it is better to transfer it to another class.

Avoid addictions

This topic is too voluminous to be considered in this article, and this topic is one of the main topics in Sandy’s book. But, I suppose, the following metaphor fully conveys its essence:

Each addiction is like a drop of glue, which class sticks to everything that concerns. A few droplets are really needed, but if you pour glue on the class, the application will stick together in one big clod.


More precisely and aphoristic can not be said. The fewer the dependencies between the classes, the more likely it is that modifying one class will not result in a whole cascade of costly changes that will affect other classes. In particular, it was interesting for me to read about why it might be advisable to use a single hash argument when creating an object, rather than relying on objects with several arguments going in a certain order:

Class Person attr_accessor :name, :height, :hair_color def initialize(args) @name = args[:name] @height = args[:height] @hair_color = args[:hair_color] end end Person.new(name: “Travis”, hair_color: “brown”, height: 6.25) 

When using a hash, we get several advantages at once, in particular:

  1. Since the position and number of the initializing argument may change from time to time, in the future this approach will help not to damage the code when other classes instantiate a new object of this class.
  2. The names of the keys understand what they are for, and what their meanings are.
  3. Finally, because we get rid of unnecessary dependencies in the code!

Respect the Law of Demeter (LoD)

In a broad sense, the law of Demeter states that you should not send messages to remote objects, redirecting them through an intermediate object. In principle, it is possible to violate this law, but always be careful in such situations, especially if you change the attribute of a remote object, and not just refer to it. Following this recommendation, we get loosely coupled objects - and this is a sign of high-quality object-oriented code.

Suppose there is an Order class, there is a place_order method, and in this method a call is made to customer.cart.items.update_stock . Thus, we are likely to violate the law of Demeter, since we are accessing a custom object to obtain an order basket object, to obtain element objects, to implement the update_stock method and thereby change the quantitative attributes of each element. Wow, reprimanded! Sometimes this practice is compared with the avoidance of railway accidents, as the long method resembles a train chain. You must admit that such an association is remembered much better than the name of the ancient Greek goddess of the harvest.

Access to instance variables through methods

Yes, I sometimes sin by direct references to instance variables when I should use the read or write method. But I never fully understood why this should not be done. Sandy justifies the need to always use the reading method, because if you decide to do an intermediate recalculation of the variable value, when the entire code base is stuffed with these instances, then it will take a lot of time to make changes. If you work with a method, then you will need to change the code in just one place.

Actively classify methods as public and private

The way you classify methods inside a class says a lot about your code and helps other programmers understand how it works. Usually in the case of the public method, the following points are meant:

  1. Other objects are free to use it.
  2. This method is stable and probably will not change.
  3. The method reports responsibility and purpose of your class.
  4. Method needs to be tested

On the other hand, private methods assume that this code is not intended for use by other objects (in Ruby this cannot be done without a special trick), it can change and, in principle, is not included in the main application framework to be tested.

So these are just some of the things that I learned from Sandy’s book. I love reading further. The book is very fascinating, as it considers in detail the philosophy of programming and the PLO in particular. Thanks for attention!

Source: https://habr.com/ru/post/277107/


All Articles