zoukankan      html  css  js  c++  java
  • 企业代码

    企业代码需要我们用以下方式重新看待代码

    一、模块性   

    代码单元通常表现为类或类型。它们是基于特定目标而设计的。各个代码单元间的交互方式既要能达到较大的期望目标,    又不能违背对它们进行划分的准则。模块化不仅是针对可重用性的代码分离,同时也要求很强的松散耦合度。

    二、松散耦合的类    

    如果代码单元需要使用来自系统其他部分的服务,那么这些服务应该抽象地由传递到该单元中。创建所需的依懒不应该是该单元的职责。  如果针对代码单元编写单元测试很方便,就证明其松散耦合度很低。

    看下面的示例:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.OleDb;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        public class Program
        {
            const double basePrice = 35.00;
            static void Main(string[] args) {
                DataSet ds = new DataSet();
                OleDbCommand cmd = new OleDbCommand();
                string sql = "Select c.LastName,c.FristName,c.MiddleName,c.CustmerRegion,e.EmailAddress from Customers c inner join Email e on c.ID = e.CustomerID Order by c.LastName ASC";
                string name = "";
                double price = 0.0;
                OleDbConnection conn = new OleDbConnection();
                OleDbDataAdapter adapter = new OleDbDataAdapter();
                cmd.Connection = conn;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = sql;
                adapter.SelectCommand = cmd;
    
                try
                {
                    adapter.Fill(ds);
                }
                catch (Exception e) {
                    Console.WriteLine(e.Message);
                }
    
                foreach (DataRow dr in ds.Tables[0].Rows) {
                    name = String.Format("{0},{1}{2}", dr["LastName"], dr["FirstName"], dr["MiddleName"]);
                    switch (dr["CustomerRegion"].ToString()) { 
                        case "1":
                            price = (0.9 * basePrice);
                            break;
                        case "2":
                            price = (0.85 * basePrice);
                            break;
                        case "3":
                            price = (0.8 * basePrice);
                            break;
                    }
    
                    Console.WriteLine(String.Format("Customer name:{0} Customer Email Address:{1} Customer's Price:{3}", name, dr["EmailAddress"].ToString(), price));
                }
            }
    
        }
    }

    Program中的代码可以正常工作,但不是良好设计的代码。它不仅严重违背了模块化规则,还违背了松散耦合的基本准则。  在本例中,我们无法编写单元测试。

     对于同一示例,一个好的多的版本可能要分解为不同的类型,每个类型能够符合模块化和松散耦合的规则。

    首先,我们创建一个简单的数据实用工具类型:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.OleDb;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        /// <summary>
        /// 一个简单的数据实用工具类型
        /// 执行简单的数据提取,并以ADO.NET数据行集的形式返回提取的数据
        /// </summary>
        public class DataUtility
        {
            private string _connectionString;
            private DataSet _ds;
            private OleDbCommand _cmd;
            private OleDbConnection _conn;
            private OleDbDataAdapter _adapter;
    
            public DataUtility(string connectionString) {
                _connectionString = connectionString;
            }
    
            public DataRowCollection GetData(string sql) {
                _ds = new DataSet();
                _conn = new OleDbConnection(_connectionString);
                _cmd = new OleDbCommand();
                _cmd.Connection = _conn;
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = sql;
                _adapter = new OleDbDataAdapter(_cmd);
    
                try
                {
                    _adapter.Fill(_ds);
                }
                catch 
                { 
                   //handle exception and log the event
                }
    
                return _ds.Tables[0].Rows;
            }
        }
    }
    View Code

    下一步,我们创建一个完成基于基本价格进行打折率计算。由于这些计算代表一组业务规则,因此,实际上不同的上下文下可能需要不同的计算类。因此真正要做的是定义一组规则,抽象地代表这些计算类。可以使用下面这样一个接口:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        /// <summary>
        /// 定义一组规则,抽象地代表所有计算类
        /// </summary>
        public interface iCalcList
        {
             double this[int region] { get; }
            double GetPrice(int region);
            double BasePrice { get; set; }
        }
    }
    View Code

    在建立企业系统时,该抽象接口是一个重要的设计要素。抽象接口是类型解除关联的流行方法。此时,我们需要创建一个打折列表类:

    using System;
    using System.Collections.Generic;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        public class DiscountList:iCalcList
        {
            private Dictionary<int, double> _rates;
            private double _basePrice;
    
            public double BasePrice {
                get { return this._basePrice; }
                set { this._basePrice = value; }
            }
    
            public DiscountList() {
                _rates = new Dictionary<int, double>();
                _rates.Add(1, 0.9);
                _rates.Add(2, 0.85);
                _rates.Add(3, 0.8);
            }
    
            public double this[int region] {
                get { return _rates[region]; }
            }
    
            public double GetPrice(int region) {
                return _rates[region] * BasePrice;
            }
        }
    }
    View Code

    我们需要建立的下一个类应该实现来自数据行的文本格式化。我们需要循环处理每个数据行,提取相关列值,根据客户所在的区域计算相应的价格,然后打印成一个文本行。这个类同样代表一个业务逻辑单元,因此,我们要先定义一个代表这个抽象类型的接口,然后实现文本格式化器。

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        /// <summary>
        /// 数据行的文本格式化抽象逻辑
        /// </summary>
        public interface iTextFormatter
        {
            string GetFormattedText();
        }
    }
    View Code

    下面我们建立文本格式化器本身的代码:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Text;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        /// <summary>
        /// 文本格式化器
        /// </summary>
        public class DataToTextFormatter:iTextFormatter
        {
            private DataRowCollection _rows;
            private iCalcList _rateCalculator;
    
            public DataToTextFormatter(DataRowCollection rows, iCalcList rateCalculator) {
                _rows = rows;
                _rateCalculator = rateCalculator;
            }
    
            private string FormatLineEntry(DataRow dr) {
                string name = String.Format("{0},{1}{2}", dr["LastName"], dr["FirstName"], dr["MiddleName"]);
    
                double price = _rateCalculator.GetPrice((int)(dr["CustomerRegion"]));
                string email = dr["EmailAddress"].ToString();
    
                return String.Format("Customer name:{0} Customer Email Address:{1} Customer's Price:{3}", name, email, price);
    
            }
    
            public string GetFormattedText() {
                StringBuilder sb = new StringBuilder();
                foreach (DataRow dr in _rows) {
                    sb.Append(FormatLineEntry(dr));
                }
                return sb.ToString();
            }
        }
    }
    View Code

    仔细观察示例会发现,构造函数需要一个iCalcList的一个实例,那么构造函数可以很容易的接受iCalcList的子类的一个实例。

    下面我们封装一个完成任务的所有单元,我们也可以在控制台应用程序的Main方法中调用它们:

    using System;
    using System.Collections.Generic;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02
    {
        /// <summary>
        /// 用于执行相关动作
        /// </summary>
        public class ListPresenter
        {
            private DataUtility _dUtil;
            private iCalcList _dList;
            private iTextFormatter _formatter;
    
            public ListPresenter(DataUtility dUtil,iCalcList dList,iTextFormatter formatter) {
                this._dList = dList;
                this._dUtil = dUtil;
                this._formatter = formatter;
            }
    
            public string GetList() {
                string sql = "Select c.LastName,c.FristName,c.MiddleName,c.CustmerRegion,e.EmailAddress from Customers c inner join Email e on c.ID = e.CustomerID Order by c.LastName ASC";
                _dUtil = new DataUtility("读取配置文件获取数据库连接字符串");
                _dList = new DiscountList();
                _dList.BasePrice = 35.0;
                _formatter = new DataToTextFormatter(_dUtil.GetData(sql),_dList);
    
                return _formatter.GetFormattedText();
    
            }
        }
    }
    View Code

    三、单元测试
      单元测试,引入测试框架来构建自动测试框架。

    四、控制反转(Inversion of Control,Ioc)容器,也称为依赖注入(Dependency Injection,DI)容器
         用于将对象的依赖实例传递给松散耦合类。有助于保持代码的模块性,同时自动省去需要我们手动编写的逻辑。

         让我们看一下两种不同的方法。

    using System;
    using System.Collections.Generic;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02.IoC
    {
        class ComplexObject
        {
            private ObjA _calssA;
            internal ObjA ClassA
            {
                get { return _calssA; }
                set { _calssA = value; }
            }
            private ObjB _calssB;
            internal ObjB ClassB
            {
                get { return _calssB; }
                set { _calssB = value; }
            }
            private ObjC _calssC;
            internal ObjC ClassC
            {
                get { return _calssC; }
                set { _calssC = value; }
            }
            public ComplexObject()
            {
                _calssA = new ObjA();
                _calssB = new ObjB();
                _calssC = new ObjC();
            }
    
        }
        class ObjA
        {
    
        }
        class ObjB
        {
    
        }
        class ObjC
        {
            private ObjD _calssD;
            internal ObjD ClassD
            {
                get { return _calssD; }
                set { _calssD = value; }
            }
            public ObjC()
            {
                _calssD = new ObjD();
            }
        }
        class ObjD
        {
            private int _count;
            public int Count
            {
                get { return _count; }
                set { _count = value; }
            }
        }
    }
    View Code

     最后的代码可能如下所示:
       ComplexObject obj = new ComplexObject();
       obj.ClassC.ClassD.Count=5;
       这段代码简单优美,但是违背了模块化和松散耦合的准则,使得我们不能对每个类进行测试。

     对于同样的代码,一个更清晰的版本可能如下:

    using System;
    using System.Collections.Generic;
    using System.Web;
    
    namespace ProfessionalEnterprise.Net.Chapter02.IoC
    {
        class ComplexObject
        {
            private ObjA _calssA;
            internal ObjA ClassA
            {
                get { return _calssA; }
                set { _calssA = value; }
            }
            private ObjB _calssB;
            internal ObjB ClassB
            {
                get { return _calssB; }
                set { _calssB = value; }
            }
            private ObjC _calssC;
            internal ObjC ClassC
            {
                get { return _calssC; }
                set { _calssC = value; }
            }
            public ComplexObject(ObjA a,ObjB b,ObjC c)
            {
                _calssA = a;
                _calssB = b;
                _calssC = c;
            }
    
        }
        class ObjA
        {
    
        }
        class ObjB
        {
    
        }
        class ObjC
        {
            private ObjD _calssD;
            internal ObjD ClassD
            {
                get { return _calssD; }
                set { _calssD = value; }
            }
            public ObjC(ObjD d)
            {
                _calssD = d;
            }
        }
        class ObjD
        {
            private int _count;
            public int Count
            {
                get { return _count; }
                set { _count = value; }
            }
        }
    }
    View Code

    使用时代码如下:

     ObjA A = new ObjA();  
    
     ObjB B = new ObjB();  
    
     ObjD D = new ObjD();    
    
    ObjC C = new ObjC(D);
    
    ComplexObject obj = new ComplexObject(A,B,C);
    

           在使用其他对象的类中,需要多的多的代码,而这些代码只是为了创建ComplexObject的一个实例。这正说明了松散耦合设计的好处和它的不足。松散耦合和快速开发之间的折中可以通过使用控制倒置容器来实现。Ioc容器为开发人员提供了一组在编译时对对象编译描述的全局定义。这种容器可以自动感知定义文件中的所有对象和对象依赖关系。当一个使用其他对象的方法或类需要创建复杂对象的时,这些方法和类只需要向IoC容器请求这些对象的实例,请求过程就是调用容器的get()方法,而不是常见的new操作符。下面是针对ComplexObject的IoC容器对象定义的一个示例,该示例来自于流行的Spring.NET IoC容器:

    <configuration>
      <configSections>
        <sectionGroup name="spring">
          <section name="context" type="Spring.Context.Support.ContextHandler,Spring.Core"/>
          <section name="objects" type="Spring.Context.Support.DefaultSectionHandler,Spring.Core"/>
        </sectionGroup>
      </configSections>
      <spring>
        <context>
          <resource uri="config://spring/objects"/>
        </context>
        <objects xmlns="http://www.springframework.net">
    
        </objects>
    
      </spring>
    </configuration>

    一旦在容器中定义了对象,就可以通过容器引用来对该对象进行初始化:

    IApplicationContext Context = ContextRegistry.GetContext();
    ComplexObject obj = (ComplexObject)Context.GetObject("etlPipelineEngine");
    

      IApplicationContext是ComplexObject对象使用上下文的一种Spring.NET定义。一旦拥有了一个IApplicationContext的句柄,就可以简单的使用IApplicationContext的各种静态Get()方法通过名称来调用对象。IoC容器的好处不仅仅是对象实例化简单,还有助于开发使用对象的代码,为对象模型创建清晰的路线图,甚至提供各种层面的面向对象编程。

  • 相关阅读:
    Interview with BOA
    Java Main Differences between HashMap HashTable and ConcurrentHashMap
    Java Main Differences between Java and C++
    LeetCode 33. Search in Rotated Sorted Array
    LeetCode 154. Find Minimum in Rotated Sorted Array II
    LeetCode 153. Find Minimum in Rotated Sorted Array
    LeetCode 75. Sort Colors
    LeetCode 31. Next Permutation
    LeetCode 60. Permutation Sequence
    LeetCode 216. Combination Sum III
  • 原文地址:https://www.cnblogs.com/baoconghui/p/3086367.html
Copyright © 2011-2022 走看看