Search code examples
oopdesign-patternsumlclass-diagramclass-design

Extending object with properties in class diagram (Composition or inheritance)


enter image description here

So, I'm in the process of designing a small system for which I'm starting out with making a class diagram. (Before however I proceed, I guess it is fair to say, that the properties visualized here have different naming in the real system)

The small snippet displays the following:

  • Engine can generate either a DefaultAlgorithm or a DecoratedAlgorithm
  • Engine, DecoratedAlgorithm and DefaultAlgorithm have Algorithm as an associated property
  • Engine needs the properties from Algorithm in order to generate either DefaultAlgorithm or DecoratedAlgorithm
  • DefaultAlgorithm and DecoratedAlgorithm both need the properties from Algorithm because those properties are metadata that tells how the algorithms were generated.
  • DefaultAlgorithm and DecoratedAlgorithm will besides being consumed by other classes (that reads algo and corresponding properties) also be persisted in a database where nested properties might not be desirable.

When I look at above diagram, I dont feel that things look quite right, for example will the properties of Algorithm be deeply nested, making me have to write awkward code to access the properties.

To me, possible alternative options could be:

  • Extend DefaultAlgorithm, Engine and DecoratedAlgorithm with Algorithm, not caring about "Composition over inheritance"
  • Carelessly repeat myself and add the properties to respectively DefaultAlgorithm, Engine and DecoratedAlgorithm

I know this might be a broad question, but what I hope with this question is to get some feedback on my thought process (Since I fear that I might be overthinking this)


Solution

  • If you want to use the DefaultAlgorithm or the DecoratedAlgorithm in place of Algorithm, they should either all implement a common interface, or the more specialised algorithms should inherit from the general Algorithm.

    Repeating doesn’t seem to be a wise approach, because if Algorithm would evolve and change some properties, you’d need to change all the others as well. This is not compliant with the open/closed principle.

    If you go for the extensiin approach, you could make your properties protected. Nevertheless, this is not a good idea in view of the history rule of Liskov’s Substitution Principle: protected members are a leakage of internal details that proved to cause very nasty bugs.

    In this regard, the problem is elsewhere. Rather than querying the algorithm to get the properties, you should tell the algorithm to to something (up to the algorithm to see which property is relevant). Tell, don’t ask. This would lead to more OO, in the spirit of the principle of the least knowledge.

    If you implement this principle, “deeply nested properties”, i.e. properties that are themselves objects of a complex class, should no longer be a problem. By the way, nested properties in UML are equivalent to associations (the property being an owned association end). Persisting such classes is supported by well known techniques (serialising, transformstion to a flat rdbms model, etc…)