To IOC,代码结构演变

代码结构演变

需求描述:

需求: 提供一个系统,可以在新春佳节之际以邮件的形式给员工发送新春祝福。

源自: 【调侃】IOC前世今生@家住腊树下

版本一

string message = "新年快乐!过节费5000.";
Console.Write("Frome email: " + message);

版本二

业务逻辑控制代码

string message = "新年快乐!过节费5000.";
EmailHelper emailHelper = new EmailHelper();
emailHelper.Send(message);

邮件发送

public class EmailHelper
{
     public void Send(string msg)
     {
         Console.Write("Frome email: " + msg);
     }
}

ps: 将邮件发送的业务代码封装掉(正常的邮件发送代码量还是有很多行的),使代码变得更清晰易改点。

需求变更

需求变更:要求增加发短信的方式,以便可以灵活选择。

祝福消息的发送方式不再是单一模式,要可以发邮件、也可以发短信、甚至后面随着时代的发展,还可能会逐步加入新的方式,如微信消息,微信公共号消息……

版本三

消息发送方式

public class EmailHelper
{
    public void Send(string msg)
    {
        Console.Write("Frome email: " + msg);
    }
}

public class SMSHelper
{
    public void Send(string msg)
    {
        Console.Write("Frome SMS: " + msg);
    }
}

消息发送服务类

public class GreetMessageService
{
    public enum SendType
    {
        Email,
        SMS,
    }
    public void Greet(string msg, SendType sendType)
    {
        switch (sendType)
        {
            case SendType.Email:
                EmailHelper emailHelper = new EmailHelper();
                emailHelper.Send(msg);
                break;
            case SendType.SMS:
                SMSHelper sMSHelper = new SMSHelper();
                sMSHelper.Send(msg);
                break;
        }
    }
}

业务逻辑控制代码

string message = "新年快乐!过节费5000.";
GreetMessageService service = new GreetMessageService();
service.Greet(message, GreetMessageService.SendType.Email);

PS:为了应该需求的变化,代码结构再次做了调整

当再次增加消息发送方式时,需要修改 GreetMessageService类 。

消息发送方式不用改动旧代码,仅扩展。

版本四

将消息发送方式,消息发送服务类这两个模块 各自建立独立的类库,分别开发,以组件的形式集成到项目中来。这样就可以交给张三、李四、王五各自独立去开发这三个模块。

其中:由张三负责业逻辑控制模块 LogicController的开发,此处简化为UT.LogicController.exe ;由李四负责祝福消息管理类(GreetMessageService),并集成到组件 UT.MessageService.dll中;由王五负责消息发送帮助类,并提供组件 UT.Email.dll。

消息发送模块

namespace UI.Sendable
{
    public class EmailHelper
    {
        public void Send(string msg)
        {
            Console.Write("Frome email: " + msg);
        }
    }

    public class SMSHelper
    {
        public void Send(string msg)
        {
            Console.Write("Frome SMS: " + msg);
        }
    }
}

消息发送服务模块

using UI.Sendable;

namespace UI.MessageService
{
    public class GreetMessageService
    {
        public enum SendType
        {
            Email,
            SMS,
        }
        public void Greet(string msg, SendType sendType)
        {
            switch (sendType)
            {
                case SendType.Email:
                    EmailHelper emailHelper = new EmailHelper();
                    emailHelper.Send(msg);
                    break;
                case SendType.SMS:
                    SMSHelper sMSHelper = new SMSHelper();
                    sMSHelper.Send(msg);
                    break;
            }
        }
    }
}

业务逻辑控制模块

string message = "新年快乐!过节费5000.";
GreetMessageService service = new GreetMessageService();
service.Greet(message, GreetMessageService.SendType.Email);

版本五

因为考虑到以后可能再添加新的祝福方式,这种未来的不确定性,一定会让李四现有的枚举SendType和 GreetMessageService中的构造函数不断的进行更改,这将会是一个没完没了工作。

再说了,既然张三要传SendToolType给我,也就是说在具体产品应用时,张三的模块肯定是知道要采用什么方式进行祝福,那么何不让他直接把祝福方式的实例而不是简单的方式类型给我呢?这样,我不就省事了吗,于是乎把设计进行了优化。

   ②、优化后设计方案:

消息发送模块

using System;

namespace UI.Sendable
{
    public interface ISendable
    {
        void Send(string message);
    }
    public class EmailHelper : ISendable
    {
        public void Send(string msg)
        {
            Console.Write("Frome email: " + msg);
        }
    }

    public class SMSHelper : ISendable
    {
        public void Send(string msg)
        {
            Console.Write("Frome SMS: " + msg);
        }
    }
}

消息发送服务模块

using UI.Sendable;

namespace UI.MessageService
{
    public class GreetMessageService
    {
        private ISendable sendHelper;
        public GreetMessageService(ISendable sendHelper)
        {
            this.sendHelper = sendHelper;
        }

        public void Greet(string msg)
        {
            sendHelper.Send(msg);
        }
    }
}

业务逻辑控制模块

string message = "新年快乐!过节费5000.";
ISendable greetTool = new EmailHelper();
GreetMessageService service = new GreetMessageService(greetTool);
service.Greet(message);

PS:

李四此处成功的利用“接口分离”、并结合“依赖倒置”的方式,使得自己负责的模块初步具备了应对新增祝福方式的扩展要求。同时由于其采用的“依赖注入”方式要求李四的业务逻辑控制模块对其所需的 “ISendable”实例进行注入,理论上已经初步具体了“IOC反转控制”的雏形。

    对“IOC反转控制”此时带来的优势就是:确保了“红色框”内的模块是具有应对变化的能力,在后继新增新祝福方式时,UT.MessageService.dll组件可以完全不做任何修改。

新的问题

该程序被集成到了三款应用中,这些应用分别采用不同的消息发送方式,于是张三同时维护着三个系统,

其中各自核心代码基本如下:

UT公司(微信方式)

string message = "新年快乐! 过节费5000.";
ISendable greetTool = new WechatHelper();
GreetMessageService service = new GreetMessageService(greetTool);
service.Greet(message);

UT编辑部(短信方式)

string message = "新年快乐! 过节费5000.";
ISendable greetTool = new SMSHelper();
GreetMessageService service = new GreetMessageService(greetTool);
service.Greet(message);

UT房产(邮件方式)

string message = "新年快乐! 过节费5000.";
ISendable greetTool = new EmailHelper();
GreetMessageService service = new GreetMessageService(greetTool);
service.Greet(message);

本着对工作和客户的认真负责,张三长时间在这些“版本维护”、“产品兼容”等脏活累活中摸爬滚打,心力憔悴……

版本六

 

时间: 2024-08-05 20:47:05

To IOC,代码结构演变的相关文章

PHP扩展代码结构详解

PHP扩展代码结构详解: 这个是继:使用ext_skel和phpize构建php5扩展  内容 (拆分出来) Zend_API:深入_PHP_内核:http://cn2.php.net/manual/zh/internals2.ze1.php 我们使用ext_skel创建扩展 hello_module,该模块包含一个方法:hello_world. 使用ext_skel 生成的代码都是PHP_开头的宏, 而不是ZEND_开头. 实际上这两者是一样的. 在源代码src/main/PHP.h 中发现:

joomla代码结构原理,执行流程

joomla-安装 下载源码 解压到apache发布目录 访问http://xxx/installation/index.php 根据实际情况访问 按每步提示操作,mysql库要先建立,ftp可暂时不开 删除安装文件即可 joomla代码结构 Joomla 2.5主要目录结构 ├─administrator     # 后台程序部分 ├─cache             # 用于存放cache,需要保持可写 ├─components        # 组件,每个组件一个文件夹,通常是com_*

ReactNative入门(4)代码结构

一.了解index.ios.js 大家都清楚,React-Native就是在开发效率和用户体验间做的一种权衡.React-native是使用JS开发,开发效率高.发布能力强,不仅拥有hybrid的开发效率,同时拥有native app相媲美的用户体验.目前天猫也在这块开始试水. 用编辑器打开index.ios.js文件,分析代码结构: 1.第一句:var React = require('react-native');有Node.js开发经验的同学都清楚,require可以引入其他模块.如果没有

代码结构和标识符

对代码结构的标识注解: 添加 JAVA语言的语法基础之一: 标识符:最好不要用中文的标识符,虽然没有限制,但最好也不要用. 注意并标识符的规则和可以定义的名字. 课本33页有Java语言的关键字表格.

关于网页脚本代码结构的再思考

在很多说法中,总是建议将我们的javascript脚本加载在网页的最后,并用外部文件的形式,然而事实并不是这样,外挂的文件最好不要太多,脚本结构代码本身才是值得我们思考的问题.我们需要重新思考我们撰写的脚本的执行力,并把更优秀的javascript开发思路融入到我们的开发中. 我在读完了几篇关于javascript和jQuery的性能优化的文章之后,才恍然大悟,我以前所做的很多代码结构优化,最终只是让乌徒帮显得臃肿,于是重新设计脚本代码的结构,无论怎么样,乌徒帮现在的网页打开显得更加流畅了. 1

storm源码之storm代码结构【译】【转】

[原]storm源码之storm代码结构[译] 说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于Storm进行源码级学习和研究的朋友有所帮助. Storm的源码共分为三个不同的层次. 首先,Storm在设计之初就考虑到了兼容多语言开发.Nimbus是一个thrift服务,topologies被定义为Thrift结构体.Thrift的运用使得Storm可以被任意开发语言使用. 其次,Stor

RYU控制器代码结构的总结

1. RYU的基本框架及开发须知 从框架中我们可以看到,在RYU控制器架构中,包括:Non-OF protocols.OF protocols. 各种libraries以及内嵌的APP,同时,RYU控制器提供给用户统一的REST API,供用户基于RYU框架开发自己的APP,同时,开发者可以根据自己的需要.添加所需的组件和库文件.值得注意的是,RYU架构只是提供给开发者一个平台,相当于一个没有应用软件的操作系统,开发者想基于这个框架实现自己想要的功能,就必须通过RYU提供的API编写相应功能的A

Storm系统架构以及代码结构学习

转自:http://blog.csdn.net/androidlushangderen/article/details/45955833 storm学习系列:http://blog.csdn.net/Androidlushangderen/article/category/2647213 前言 什么是storm,storm是做什么的,一个简单的描述,你可以理解为是一个“准实时”的Hadoop,Hadoop是专门做的是离线数据处理,而storm则弥补了Hadoop在这方面的不足,他是一个实时数据处

JSqlParser系列之二代码结构(原)

JSqlParser系列之二代码结构(原) 博客园 百味木屋原创,转载请注明出处. 上一篇文章简单介绍如何建立JSqlParser工程,本章对JSqlParser工程的代码结构作大致地介绍. 一.目录结构 JSqlParser的目录结构比较简单,主要有表达式,解析器,语句处理几个目录.下面这张图给出了一个具体的SQL语句与表达式: 接下来,简要介绍一下在JSqlParser中几个抽象概念. 二.SQL语句(statement) JSqlPaser将所有的SQL语句抽象为Statement,Sta