Reply to Lattice Inheritance

This publication is a response to the text “Lattice inheritance” published by the potan user , with a suggestion of an alternative, in the subjective opinion of the author, closer to OOP with classes (for the case with a limited set of classes).

“The goal of inheritance is to bind code (a set of methods) to the minimum set of entity properties (usually an object) that it provides and that it needs.”

Is that so? Also, what is the reason for the binding? On what grounds do we conclude that these methods should be connected with this object, but some other methods should be made part of other objects that will take the missing properties / parameters through public interfaces?

I adhere to SOLID and the idea of ​​sole responsibility for the object. Consequently, the hierarchy of inheritance in this case is a clarification of responsibility to the specific circumstances in which it needs to be executed.

However, objects of the real world (or domain) can carry several different functions / responsibilities, therefore, direct mapping of them into the class system may fail. I see such an object in the application class system as a collection / container of responsibilities supported by the domain object. The task of this class is to coordinate responsibilities among themselves. Reconcile partly through specific descendants of the responsibilities, partly inside the class container.

I will try to give an example close to the example of the article.

Abilities
  • ability to shoot
  • ability to shoot MANPADS
  • swimming ability
  • walking ability


Skill - provides general information, for example, a link to the skill tree and a slot for skill items.

Ability to shoot - provides an opportunity to aim, in the slot of skills there should be a shooting weapon.

The ability to shoot from MANPADS - specifies the implementation of the function to aim, for example, the MANPADS screen draws.

Ability to swim - allows you to immerse yourself in water (for example, without dying at the same time) and shows the time scale, the character somehow flies in the water.

By the way, here I missed the abstraction - the ability to move, from which you can inherit the ability to swim and walk.

Then specific characters will contain skill sets.

The character:
  • current ability to move;
  • list of skills: [].


Footman (Character):
  • current ability to shoot;
  • list of skills: [swim, walk, shoot from MANPADS].


Duck (Character):
  • list of skills: [swim].


The responsibility of the character is to coordinate his skills with each other and switch them. For example, when a character enters the water. If you have the ability to swim - activate it, otherwise - draw a picture character drowns.

Question: what will happen if this set grows?
And how can it grow?
  • add new skill;
  • add a new character;
  • add to the existing character a skill that was previously not characteristic of him (teach the duck to shoot from MANPADS).


New skill:.
If these are quantitative things, for example, MANPADS fired with a probability of hitting 0.6, and now 0.8 - these are just different records in a database of the same class.

.If something new, for example, a sword, then in any case you need a mountain of code, which at the beginning will describe the possession of the sword abstractly, and then each character will add its own details. Although not necessarily a complex modification (if the abstractions of the Character and his heirs are good).

A new class of characters - here you need to describe the combination of skills, how to coordinate them with each other. Code as a character’s subclass, it is possible to select separate subclasses of skills adapted for a new character.

It’s more difficult to add something else to the existing one, because it is necessary to sort the internal code of the existing one again. And perhaps it will be easier to inherit a descendant.

For example, Duck suits us all, only it doesn’t know how to shoot. This means that this functionality needs to be applied, it may be more convenient to add 2 classes at once: Simple Duck and Duck that can shoot. And in the Duck class, to leave common responsibilities for daughter ducks - the ability to swim - adapted to the duck: in the form of keeping on the water and diving.

Another side of the difficulty is adding a new responsibility (class). There is a need to relate it to all existing ones. Potentially, this process can go to infinity, and the more classes that already exist, the longer it takes. The help in this is top-down design: there is a world, it creates characters and allows them to interact by means of skills. Skill characters can gain / lose.

From this perspective, mixin seems to be an underdeveloped class. It was left underestimated because of the desire to make it faster and not to rebuild the existing class hierarchies and their compositions.

Also popular now: