Terminology

Abstraction definition: 'Modelling classes in such a manner as to be able to use the most appropriate level of inheritance for a given aspect of the problem.'

Decoupling definition: 'Separating object interactions from classes and inheritance into distinct layers of abstraction. '

Encapsulation definition: 'Concealing the fundamental details of an object from the other objects that communicate with it.'

Inheritance definition: 'Using one class as the basis for other classes.'

Polymorphism definition: 'Treating an object of a derived class as a member of an inherited class.'

Facts, Thoughts and Opinions

Inheriting a Class is a Bad Idea

Inheriting a non-abstract class is a bad idea because by overriding a method, we risk breaking the logic of the entire parent class. You probably have no or incomplete knowledge of how the rest of the class uses the method that you are overriding. To extend a final class, treat it like a black box and decorate it with your own implementation.

SOLID

Single responsibility principle An object should have only a single responsibility.
Open/closed principle Software entities should be open for extension, but closed for modification.
Liskov substitution principle Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
Interface segregation principle Many client specific interfaces are better than one general purpose interface.
Dependency inversion principle Depend upon abstractions, not concretions.

Static Methods are Bad

Static methods go against the object-oriented paradigm, because static methods turn object-oriented programming into "class-oriented" programming. The problem is that with class-oriented programming, decomposition doesn't work anymore. We can't break down a complex problem into parts, because only a single instance of a class exists in the entire program. When I instantiate an object inside a method, it is dedicated to my specific task. It is perfectly isolated from all other objects around the method. It is a local variable in the scope of the method. A class, with its static methods, is always a global variable no matter where we use it.

Public static methods also have a few practical drawbacks: It's impossible to mock them, or at best a very bad idea to try to mock them. Also, they are not thread-safe by definition, because they always work with static variables, which are accessible from all threads. You can make them thread-safe, but this will always require explicit synchronization.

Virtues of a Good Object

  • It represents something that exists in real-life.
  • It works by contracts (which are represented by the interfaces that it implements).
  • It is unique.
  • It is immutable.
  • Its class doesn't have anything static.
  • Its name tells us what it is, not what it does.
  • Its class is either final (can't be extended via inheritance) or abstract (incomplete and uninstantiatable).

Virtues of Immutable Objects

  • Immutable objects are simpler to construct, test, and use.
  • Truly immutable objects are always thread-safe.
  • Immutable objects help avoid temporal coupling.
  • The usage of immutable objects is free of side effects (no defensive copies).
  • Immutable objects always have failure atomicity.
  • Immutable objects are much easier to cache.
  • Immutable objects prevent NULL references.

Images

[[/div]]
  •   Subtopics

  •   Writings

  Sources & Bookmarks

Name/Link Date