We use domain objects to encapsulate business logic. Sometimes, we need to change the behavior of an entity due to new system requirements. A common approach is to modify the method or property by adding an if statement that checks a feature flag:
public class Entity : IEntity
{
public void SomeMethod()
{
if (Feature.NewRequirement())
{
DoTheNewStuff();
}
else
{
DoTheOldStuff();
}
}
}
The feature flag determines when the new behavior should be enabled and allows us to turn it off if necessary. Typically, after the feature has been running in production for a few weeks or months, we remove the flag and keep only the new implementation.
Problems With This Approach
- Feature Flag as a Static Dependency – The Feature class is static and depends on a cache holding the feature flag configuration. This makes unit testing difficult since shared state in tests can cause flakiness and prevent parallel execution.
- Injecting the Feature Flag? – We could pass the feature flag as a constructor argument to Entity or as a method parameter, but we prefer to keep domain objects as pure as possible, without dependencies on infrastructure. Most of the time, entities are either created by an aggregate or fetched from a database via an ORM.
How can we make our domain entities behave differently based on feature flags while minimizing dependencies and avoiding static calls inside the entity?
We use domain objects to encapsulate business logic. Sometimes, we need to change the behavior of an entity due to new system requirements. A common approach is to modify the method or property by adding an if statement that checks a feature flag:
public class Entity : IEntity
{
public void SomeMethod()
{
if (Feature.NewRequirement())
{
DoTheNewStuff();
}
else
{
DoTheOldStuff();
}
}
}
The feature flag determines when the new behavior should be enabled and allows us to turn it off if necessary. Typically, after the feature has been running in production for a few weeks or months, we remove the flag and keep only the new implementation.
Problems With This Approach
- Feature Flag as a Static Dependency – The Feature class is static and depends on a cache holding the feature flag configuration. This makes unit testing difficult since shared state in tests can cause flakiness and prevent parallel execution.
- Injecting the Feature Flag? – We could pass the feature flag as a constructor argument to Entity or as a method parameter, but we prefer to keep domain objects as pure as possible, without dependencies on infrastructure. Most of the time, entities are either created by an aggregate or fetched from a database via an ORM.
How can we make our domain entities behave differently based on feature flags while minimizing dependencies and avoiding static calls inside the entity?
Share Improve this question asked Mar 13 at 15:50 DaggenDaggen 611 silver badge5 bronze badges2 Answers
Reset to default 0You can use the strategy pattern to encapsulate different behaviors based on the feature flag.
Interface
public interface ISomeMethodStrategy { void Execute(); }
Implementations
public class OldSomeMethodStrategy : ISomeMethodStrategy { public void Execute() => DoTheOldStuff(); } public class NewSomeMethodStrategy : ISomeMethodStrategy { public void Execute() => DoTheNewStuff(); }
New domain entity with strategy
public class Entity : IEntity { private readonly ISomeMethodStrategy _strategy; public Entity(ISomeMethodStrategy strategy) { _strategy = strategy; } public void SomeMethod() => _strategy.Execute(); }
And then, before creating the entity, determine which strategy to use:
var strategy = featureService.IsNewRequirementEnabled()
? new NewSomeMethodStrategy()
: new OldSomeMethodStrategy();
var entity = new Entity(strategy);
If you want avoid the static in domain object or injection in domain object, you can just have 2 methods differents (follow the rule of extensibility) to implement new and old feature, like :
public class Bar
{
public void DoNewFeature()
{
// ...
}
public void DoOldFeature()
{
// ...
}
}
And after you use a feature service to choose which method to use in your use case, like :
public class BarService(IFeatureFlagService feature)
{
public void DoSomething(int idBar)
{
var myBar = this.GetById(idBar);
if (feature.Enabled("barNew")
{
myBar.DoNewFeature();
}
else
{
myBar.DoOldFeature();
}
}
}
The feature flipping isn't a domain object rule, so it's better to have this in service.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744692433a4588288.html
评论列表(0条)