Consider I have a class which represents a tree element. An element can be changed, inspected children elements can be added to it (say trough the add()
method). But also I have a class which contains root of the tree (State
). And for convenience's sake I have added static overload of add()
method which adds elements to root. And as result element class needs to get current application state through a singleton (which existence is justified) and therefore element class is bound to State
class. Is it good? Is it justified? Because otherwise I have to add method add
to State
(but this seems like SRP violation though).
1 Answer
The SRP is not about doing one thing, but about reasons to change.
The case that you describe is on one side a Tree
class that manages elements, and on the other side a State
class that makes use of a specific tree.
At first sight, creating an overload to enrich Tree
with an add
at root level does not seem to break the SRP: this overload does not create a new reason for change. It's just a convenience.
Unfortunately, it's not fully clear how root
relates to a node of the Tree
:
- Is there only one single
root
for all theTree
elements? In this case, it's not about SRP but it's more about OCP and extendingTree
to allow reusability. - Are there several trees, each with it's own root? In this case, how do you find the right root? There are two variants:
- There's no direct relation: the using context has to know its root. In this case,
State
would have a root. But other classes could have a different root. Then youradd()
overload would belong toState
since it addresses an encapsulated element. But theadd()
signature would depend on theTree::add()
. In this case you would break SRP. - There is a relation. For example, each tree would point to a root node. Or each tree would point to a parent tree, allowing to go back to the root. Or the tree keeps trace of the root, and the tree elements are a nested class. Whatever the design, you could then have an
add()
for the root level without breaking any SOLID principles.
- There's no direct relation: the using context has to know its root. In this case,
add
adds to root?State.root.add
?