Wednesday, 28 December 2016

Open/Closed Principle

The situation in which you have to modify a lot of files to add a new feature is a classic violation of the Open/Closed Principle:
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
source: https://dzone.com/articles/the-power-of-openclosed-principle?edition=155254&utm_source=Weekly%20Digest&utm_medium=email&utm_campaign=wd%202016-12-28

If we were to adhere to this rule, there would be no files to modify in order to add a new feature or those files would be limited to some configuration/factory methods.  

Applying OCP

To apply the principle, you need four keywords: abstract, extends, interface, and implements. You find the places that require a change:
class Report {
    enum Type {
        ORDERS_PER_DAY, CONVERSION_RATES
    }
    Type type;
    String generate() {
        ...
        switch (type) {
            case ORDERS_PER_DAY:
                // do stuff
                break;
            case CONVERSION_RATES:
                // do stuff
                break;
        }
        ...
    }
}

Then you extract proper abstractions:
interface Report {
    String generate();
}

Then implement each of your features using these abstractions in separate source files:

class OrdersPerDayReport implements Report {
    public String generate() {
        // do stuff
    }
}
class ConversionRatesReport implements Report {
    public String generate() {
        // do stuff
    }
}

The interfaces or base classes are the ones being both open and closed
 – they’re open to be derived from and closed for modifying their content.

The real challenge in implementing the Open/Closed Principle lies in choosing the places to close (as in “closed for modification”). 
What are the heuristics?

  • Product backlog: if the new feature is already present in the backlog, there’s a huge chance it will be implemented one day. Therefore, if we’re working with the potentially affected code, we might prepare it for the upcoming feature.
  • Previous features: I’d call this “closing by refactoring”. While implementing new features, whenever you notice that a place is vulnerable to modifications, you close it, so that the problem doesn’t occur ever again.

Monday, 26 December 2016

Gennady Golovkin's Jab

https://www.youtube.com/watch?v=xTO6DmknBz8

MVC vs OOP

Source: https://dzone.com/articles/mvc-vs-oop?edition=154268&utm_source=Weekly%20Digest&utm_medium=email&utm_campaign=wd%202016-12-21

In an MVC design, the controller is in charge, taking care of the data received from  the Model and injecting it into View — and this is exactly the problem. The data escapes the Model and becomes "naked", which is a big problem, as we agreed earlier. OOP is all about encapsulation — data hiding.


MVC architecture does exactly the opposite by exposing the data and hiding behavior. The controller deals with the data directly, making decisions about its purpose and properties, while the objects, which are supposed to know everything about the data and hide it, remain anemic. That is exactly the principle any procedural architecture is built upon: the code is in charge of the data. Take this C++ code, for example:

void print_speed() { // controller
  int s = load_from_engine(); // model
  printf("The speed is %d mph", s); // view
}

The function print_speed() is the controller. It gets the data s from the model load_from_engine() and renders it via the view printf(). Only the controller knows that the data is in miles per hour. The engine returns int without any properties. The controller simply assumed that that data is in mph. If we want to create a similar controller somewhere else, we will have to make a similar assumption again and again. That's what the "naked data" problem is about, and it leads to serious maintainability issues.
This is an object-oriented alternative to the code above (pseudo-C++):
printf(
  new PrintedSpeed( // view
    new FormattedSpeed( // controller
      new SpeedFromEngine() // model
    )
  )
);

Here, SpeedFromEngine.speed() returns speed in mph, as an integer; FormattedSpeed.speed() returns "%d mph"; and finally, PrintedSpeed.to_str()returns the full text of the message. We can call them "model, view, and controller", but in reality they are just objects decorating each other. It's still the same entity — the speed. But it gets more complex and intelligent by being decorated.
We don't tear the concept of speed apart. The speed is the speed, no matter who works with it and where it is presented. It just gets new behavior from decorators. It grows, but never falls apart.
To summarize, Controller is a pure procedural component in the MVC trio, which turns Model into a passive data holder and View into a passive data renderer.