zoukankan      html  css  js  c++  java
  • 关于领域对象业务逻辑中条件判断的最佳实践

    这篇文章其实是大健康行业直销系统的番外篇,主要给大家讲讲如何在领域逻辑中,有效的处理业务逻辑条件判断的最佳实践问题。

    大家都知道,聚合根、实体和值对象这些领域对象都自身处理自己的业务逻辑。在业务处理过程中,通常会有一些条件判断,当满足这些条件时,会进行不同的后续处理。在传统的实现中,可以通过If Else条件语句进行判断,但If Else语句在复杂领域中来检查是否满足一些业务条件存在以下的问题:

    1.      无法很好的显示表达业务条件本身。

    2.      无法对多个条件在不同需要的地方进行灵活的组合。

     

    为了更好的组织业务逻辑中关于业务条件的判断,最佳实践方式是将业务条件拆分得足够细,并用语义化的方式表示。这样,在当前上下文中的领域对象就可以使用一个或多个业务条件的组合。

     

    举个例子:酒店业务中,房间领域对象会处理预定房间的领域逻辑和退房的领域逻辑,在预定房间时,我们需要保证房间没有被其他人预定并且房间没有正在维护这两个业务条件同时满足;在退房时,我们需要保证房间里没有物品损坏或已经进行了损坏赔偿这两个业务条件中的任意一个。

    要实现上述的需求,我们可以分别作出4个业务条件规则,然后在界限上下文任意要使用的地方进行灵活的组合。

    1.      为了达到上述目的,我们首先要开发出业务条件的接口与条件的组合方式定义。

    public interface ISpecification<T>
        {
            bool IsSatisfied(T entity);
        }

    该规约接口就定义了一个方法,传入某个领域对象,判断是否满足条件。

    public class AndSpecification<T> : ISpecification<T>
        {
            private ISpecification<T> left;
            private ISpecification<T> right;
            public AndSpecification(ISpecification<T> left,ISpecification<T> right)
            {
                this.left = left;
                this.right = right;
            }
            public bool IsSatisfied(T entity)
            {
                return this.left.IsSatisfied(entity) 
                    && this.right.IsSatisfied(entity);
            }
    }

    该类实现了两个业务条件的与关系。

    public class OrSpecification<T> : ISpecification<T>
        {
            private ISpecification<T> left;
            private ISpecification<T> right;
            public OrSpecification(ISpecification<T> left, ISpecification<T> right)
            {
                this.left = left;
                this.right = right;
            }
            public bool IsSatisfied(T entity)
            {
                return this.left.IsSatisfied(entity)
                    || this.right.IsSatisfied(entity);
            }
    }

    该类实现了两个业务条件的或关系。

    2.      在房间业务界限上下文中,分别实现4个业务条件规则。

    //房间没有被其他人预定业务条件判断
        public class RoomIsNotConfirmedByOtherSpecification : ISpecification<Room>
        {
            public bool IsSatisfied(Room entity)
            {
                return !entity.OtherConfirmed;
            }
        }
        //房间没有被正在维护业务条件判断
        public class RoomIsNotMaintenanceSpecification : ISpecification<Room>
        {
            public bool IsSatisfied(Room entity)
            {
                return !entity.Maintenancing;
            }
        }
        //房间没有物品损坏条件判断
        public class RoomIsNotAnythingBrokenSpecification : ISpecification<Room>
        {
            public bool IsSatisfied(Room entity)
            {
                return !entity.AnythingBroken;
            }
        }
        //房间没有物品损坏条件判断
        public class RoomHasBeenBrokenCompensateSpecification : ISpecification<Room>
        {
            public bool IsSatisfied(Room entity)
            {
                return entity.HasBeenCompensated;
            }
        }

    3.      在房间领域对象的预定房间与退房的领域逻辑中,组合使用上述4个条件规则

    //预定房间
        public Room Reservation()
        {
            var roomisnotconfirmedspec = new RoomIsNotConfirmedByOtherSpecification();
            var roomisnotmaintenancespec = new RoomIsNotMaintenanceSpecification();
            var researvationrulespec = new AndSpecification<Room>(roomisnotconfirmedspec, roomisnotconfirmedspec);
            if (researvationrulespec)
            {
                //进行后续业务处理
            }
            return this;
        }
    
        //退房
        public Room CheckOut()
        {
            var roomisnotanythingbrokenspec = new RoomIsNotAnythingBrokenSpecification();
            var roomhasbeenbrokenspec = new RoomHasBeenBrokenCompensateSpecification();
            var checkrulespec = new OrSpecification<Room>(roomisnotanythingbrokenspec, roomhasbeenbrokenspec);
            if (checkrulespec)
            {
                //进行后续业务处理
            }
            return this;
    }

    当然如果要任意组合多个与、或业务条件,需要在规约上实现Or、And方法来形成链式调用,具体怎么实现?有了上面的思路,自己写代码试试吧。

    QQ讨论群:309287205

    DDD实战进阶视频请关注微信公众号:

  • 相关阅读:
    数据库unsigned char*类型图片存进
    int main(int argc, char *argv[])中的argc和argv
    数据库任务进度记录
    数据库存入数据后id保持不变,或者直接报错
    数据库图片存入并显示成功,但查询时不能全显示
    数据库存入图片成功但显示不出来
    JWT(Json web token)认证详解
    重启eclips后启动项目出现监听文件找不到
    解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server
    Linux系统常用命令
  • 原文地址:https://www.cnblogs.com/malaoko/p/8961348.html
Copyright © 2011-2022 走看看