1

Problem: I have a complex system with many layers of abstractions. I need a different behaviour low in the abstractions, but to be configured high in the abstraction.

Solution 1: Having a parameter to define the chosen behaviour and pass this parameter down in the abstraction until the method that uses it.

Solution 2: Have a configuration module set high in the abstraction and the module low in the abstraction have access the configuration module.

Solution 3: Strategy Design Pattern?

According to the Clean Code book the solution 1 is bad because a function shouldn't have control flags as parameters, the different path should become a new function. Doing so in this case would duplicate what else is called in this function and in the underlying ones.

The problem with the solution 2 is the scope of the configuration, if it's too high it becomes hard to test the code as I have a dependency that I can not inject, if I inject I'm kind of in the solution 1. Also following an Hexagonal Architecture I could be forcing my Application layer to depend on external modules, for example if the user access the different code paths depending from which page he accessed the functionality.

A friend recommended me to take a look in the Strategy pattern, but for what I remember it needs to pass a reference to the implementation that's going to be used and in the end is similar to injecting the dependency.

My conclusion

I feel that the solution 2 is better as I can define in which level of the abstraction I will have this configuration module, but I would like to know if the problem is solved for a better design pattern or refactoring strategy.

  • 2
    sometimes with these problems when look at the specific case there is a solution which cant be seen from the generic case – Ewan Sep 14 '18 at 16:58
  • 2
    the very nature of an abstraction is supposed to hide these low level behaviours, if you need to change them you might be doing something wrong – Ewan Sep 14 '18 at 17:00
  • I understand the point and I agree, but the problem is in a context that I don't have all the information since the begin. It's a mix of architecture and refactoring question I think. – Jp_ Sep 14 '18 at 17:03
  • 3
    I think you need to add some context. atm you question is "consider this contradiction. whats the solution" – Ewan Sep 14 '18 at 17:07
  • 2
    Your question heavily begs for a concrete example. – Doc Brown Sep 14 '18 at 19:30
1

Passing configuration parameters from "higher" layers to "lower" layers (instead of letting lower layers access directly configuration data) is fine. But this is about layers, not about functions.

What you found in Uncle Bob's Clean Code book about control flags is purely meant for functions - each function is part of a class, a module, a component or a layer, and when the class, module, component or layer is constructed or initialized, then it is perfectly ok to pass configuration parameters from a higher level unit to this lower level unit, as part of of the construction or initialization process. For example, if the unit is one class, one can pass a configuration flag through the constructor and store its value inside a member variable. AFAIK there is no recommendation in the Clean Code book against this kind of design.

Functions inside such a layer can then access this layer-specific configuration directly, without getting the value passed as a parameter. Or the initialization code of the layer/class/module/component takes the configuration and uses it to build a certain strategy object. That is what the strategy pattern is for - it is a clean way of implementing configuration-dependent behaviour inside a layer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.