zoukankan      html  css  js  c++  java
  • 代码重构——移除领域模型的属性“set”块

    设计领域模型的时候,属性的set块会带来一些问题,例如下面的一个类。

        public class SearcherBase
        {
            public IApplication Application { get; set; }
    
            public virtual IIndexManager IndexManager { get; set; }
    
            public virtual async Task<SearchResult> SearchAsync(Query query)
            { //some code }
        }
    

    当客户端调用该类时,看到ApplicationIndexManager两个属性,会不知所措: 该不该给他们赋值呢?这两个玩意是干吗的呢?
    事实上,这两个属性的set块,在 SearcherBase类型初始化的时候才会被用到。

        public class SearcherBuilder
        {
            private IocResolver _iocResolver;
    
            public SearcherBase Build(IApplication app, IIndexManager manager)
            {
                SearcherBase searcher = _iocResolver.Resolve(app.SearcherType) as SearcherBase;
                searcher.Application = app,
                searcher.IndexManager = manager;
                return searcher;
            }
        }
    

    将领域模型的属性set块暴露出来,会造成属性的语义不明,没有表达出业务逻辑(初始化),不符合DDD有关领域模型设计的要求。因此,可以根据情况对SearcherBase做如下两种方式的重构:

    1. 尽可能多的在构造函数中初始化内部成员
        public class SearcherBase
        {
            public SearcherBase(IApplication app, IIndexManager manager)
            {
                Application = app,
                IndexManager = manager;
            }
            public IApplication Application { get; }
    
            public virtual IIndexManager IndexManager { get; }
    
            public virtual async Task<SearchResult> SearchAsync(Query query)
            { //some code }
    
        }
    
    1. 对于该例,由于关系到通过容器初始化实例,可以创建SearcherBase的初始化方法
        public class SearcherBase
        {
            public void Initialize(IApplication app, IIndexManager manager)
            {
                Application = app;
                IndexManager = manager;
            }
            public IApplication Application { get; private set;}
    
            public virtual IIndexManager IndexManager { get; set;}
    
            public virtual async Task<SearchResult> SearchAsync(Query query)
            { //some code }
        }
    
        public class SearcherBuilder
        {
            private IocResolver _iocResolver;
            public SearcherBase Build(IApplication app, IIndexManager manager)
            {
                SearcherBase searcher = _iocResolver.Resolve(app.SearcherType) as SearcherBase;
                searcher.Initialize(app, manager);
                return searcher;
            }
        }
    

    经过上述重构,当客户端在看到 SearcherBase 的时候,会发现 ApplicationIndexManager 两个属性并没有Set块,并根据第二种重构方式的Initialize方法推断出,类型初始化的时候,两个属性被赋值。
    这样,就增强了SearcherBase的可读性。

    何时进行类似重构?

    《实现领域驱动设计》这本书中提到,DDD关注的是 核心复杂领域模块 的设计。整个项目中的各个模块有轻重主次之分,只有那些多次被引用、关系核心业务环节的模块才应该做精心的设计,否则会造成过度设计。

  • 相关阅读:
    <JZOJ5912>VanUSee
    <JZOJ5910>duliu
    <JZOJ5913>林下风气
    pytest学习笔记(二)
    试用saucelabs进行浏览器兼容性测试
    pytest学习笔记(一)
    SSM框架搭建,以及mybatis学习
    游戏2048的python实现
    使用svn在github上下载文件夹
    jenkins集成python的单元测试
  • 原文地址:https://www.cnblogs.com/crayfish/p/5902146.html
Copyright © 2011-2022 走看看