Open-Closed Principle

Your company sells temperature sensors and software for it for many years. For the last 5 years there we produced only indoor sensors.
Yesterday your boss came around and told you, that you’ll now sell also outdoor sensors.
There is a class that feeds the gui with the average temperature of multiple sensors. You’re assigned the extend the average temperature class, which look quite messy after your change:

Before your change it simply took a List<IndoorTemperatureSensor> and it had only one for loop. But look at this – feels like we’re missing something….. Continue reading “Open-Closed Principle”

Liskov Substitution Principle

The Liskov Substitution Principle (LSP) says: “Let  \phi(x) be a property provable about objects x of type T. Then  \phi(y) should be true for objects y of type S where S is a subtype of T.” (Wikipedia)

That means: A derived class should by able to be replaced by another object of it’s base class without errors or modified behavior of the base class. Continue reading “Liskov Substitution Principle”

Interface Segregation Principle

The ISP was “invented” by Robert C. Martin while consulting for Xerox: “The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.”*

I’ll explain this with an example, let’s assume we have an Interface SensorDevice that provides a lot of functions:

So what’s the problem with fat interfaces like in the example coding?

If clients use interface with methods they don’t need, they know details that they don’t care about.
In the sensor device example you will have code that controls maybe hundreds of different sensors and on the other hand there’ll be code that reads and handles the readings.
Device State, control and reading methods are tightly coupled togehter. If there’s a change in a method signature for example, all “clients” are eventually affected by the change – which is unnecessary.

Applying the interface segregation principle

To understand the ISP you must understand the difference between the (class-)interface and the object interface. Depending on the language a class can inherit from one or more classes and implement multiple interfaces

An object that implements multiple interfaces exposes all methods. But you also can access the object with the interface it implement, like IDisposable.
This allows a very specific access to a subset of the object interface, so that it can be treated in different ways without caring about its details.

Especially on higher levels of abstraction you will have objects with many methods, but you can group them using interfaces:

Class diagram - interface segregation principle

Now you can access the different methods by client-concern using the interfaces:

Console-Output
06.03.2016 07:17:37 ConsoleLogFakeSensor: enable()
06.03.2016 07:17:37 ConsoleLogFakeSensor: isEnabledSince()
06.03.2016 07:17:37 ConsoleLogFakeSensor: disable()
06.03.2016 07:17:37 ConsoleLogFakeSensor: powerOff()
Press any key to continue…

This will also be very handy if you want to disable dozens of different devices of different types using the generic interface “DeviceState” – without knowing which type of Device it is.

The example project is in this GitHub repository.

Conclusion

Splitting fat interfaces by client concerns is a powerful tool to build cohesive interfaces. Due to the reduced dependencies the scope of changes is minimised and the loose coupling will payoff in the long term when it comes to extending and maintaining the project. Smaller specific interfaces may also help to communication your intentions.

Sources

Dependency Inversion Principle

The dependency inversion principle states:

  • “High level modules should not depend upon low level modules. Both should depend upon abstractions.”
  • “Abstractions should not depend upon details. Details should depend upon abstractions.”

See Principles of Object Oriented Class Design by Robert C. Martin (2000) for further details.

An example Application
The application sends e-mail notifications to users. The message text is different for regular and premium users.
The “BL” sub-package contains the business logic, it knows how to generate the email (address, subject and message) and how to call the SMTP client. Continue reading “Dependency Inversion Principle”