orm - How to Apply Feature Flags in Domain Entities Without Adding Dependencies? - Stack Overflow

We use domain objects to encapsulate business logic. Sometimes, we need to change the behavior of an en

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 badges
Add a comment  | 

2 Answers 2

Reset to default 0

You 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信