当前位置:编程学习 > 网站相关 >>

改善代码设计 —— 组织好你的数据(Composing Data)

1. Self Encapsulate Field (自封装值域)
解释:
      大部分类 (class) 中都会有一些值域 (field), 随之还会有一些方法使用到了这些值域. "如果调用这些值域"这个问题分为两种观点: 1. 应该直接调用它们 2. 应该通过访问函数调用它们.

      我觉得大部分情况下直接调用比较方便, 过多的访问函数还会造成类中的函数过多, 当然将来如果我觉得直接调用带来了一些问题, 写一个一个的访问函数也并不是很困难.

      下面的例子主要说明如何给值域写一个访问函数, 并通过访问函数调用值域的值.

冲动前:
0 private string _userName, _password; 

1   

2 public bool IsValid() 

3 { 

4     bool isValid = !(String.IsNullOrEmpty(_userName) && 

5         String.IsNullOrEmpty(_password)); 

6     return isValid; 

7 }

冲动后:
00 private string _userName, _password; 

01   

02 public bool IsValid() 

03 { 

04     bool isValid = !(String.IsNullOrEmpty(GetUserName()) && 

05         String.IsNullOrEmpty(GetPassword())); 

06     return isValid; 

07 } 

08 private string GetUserName() 

09 { 

10     return _userName; 

11 } 

12 private string GetPassword() 

13 { 

14     return _password; 

15 }

2. Replace Data Value with Object (以物件取代数据值)
解释:
      如果你发现代码中有很多字段或者值域似乎都在描述某一样东西, 可以考虑将这些字段或者值域封装到一个类中, 用这个物件代替原先代码中繁杂的字段和值域.

冲动前:
0 class Order 

1 { 

2     public string CustomerName { get; set; } 

3     public string CustomerAddress { get; set; } 

4     public int CreditLevel { get; set; } 

5     public int CustomerTel { get; set; } 

6     //... 

7 }

冲动后:
00 class Order 

01 { 

02     public Customer Customer { get; set; } 

03 } 

04   

05 class Customer 

06 { 

07     public string CustomerName { get; set; } 

08     public string CustomerAddress { get; set; } 

09     public int CreditLevel { get; set; } 

10     public int CustomerTel { get; set; } 

11     //... 

12 }

3. Change Value to Reference (将值对象改为引用对象)
解释:
      一个类中有时包含值对象作为它的字段或者属性, 如订单 Order 类中包含了一个 客户 customerName 的字段. 如果同一个客户有好几份订单, 那么每一份订单就都会保存一次客户的姓名. 如果这个客户的姓名改变了, 那么就需要更改每份个订单中的 customerName.
      如果将 customerName 提取出去, 提炼一个 Customer 的类, 订单使用的是 Customer 实例的引用, 则只需更改实例中客户姓名的属性, 因为所有的订单都是引用的这个客户实例, 所以它们不需要作其它更改.

冲动前:
0 class Order 

1 { 

2     private string _customerName; 

3   

4     public Order(string customerName) 

5     { 

6         this._customerName = customerName; 

7     } 

8 }

冲动后:
00 class Order 

01 { 

02     private Customer _customer; 

03   

04     public Order(Customer customer) 

05     { 

06         this._customer = customer; 

07     } 

08 } 

09   

10 class Customer 

11 { 

12     public string CustomerName { get; set; } 

13 }

4. Change Reference to Value (将引用对象改为值对象)
解释:
      如果给一个类传递引用类型变得不是你想要的效果, 比如我曾经做过一个类似于 MSN 的软件, 其中将人的头像, 昵称, 个性签名显示在一个自定义控件中, 然后在使用了 ListBox.Add(myControl), 结果我惊奇的发现最后好友列表里居然都是同一个 (最后一个) 人. 原来 ListBox.Add() 传递进去的都是引用的同一个 myControl 实例, 尽管代码貌似在动态的生成每一个人, 但其实都只修改了一个 myControl, 而 ListBox 仅仅了引用这一个对象. 后来我在代码中动态的生成不同对象的实例才解决了这个问题.

      除了这样, 还可以在你的类中定义一个值对象, 每一次生成一个类的实例时, 类中值对象的控制权总是属于自己.

5. Replace Array with Object (用物件取代数组)
解释:
      一个类中可能会包含很多字段, 你不能因为这些字段都是 string 类型, 就通通把它们放到一个 string[] 里, 在类的方法体中通过数组索引来获取你需要的值, 这样很难让别人记得你 string[0] 表示的是姓名, string[1] 表示的是他的住址...

      下面的将展示前后代码可读性的差距.

冲动前:
0 string[] _person = new string[5]; 

1   

2 public string GetName() 

3 { 

4     return _person[0]; 

5 } 

6 public string GetAdd() 

7 { 

8     return _person[1]; 

9 }

冲动后:
0 private Person _person; 

1   

2 public string GetName() 

3 { 

4     return _person.Name; 

5 } 

6 public string GetAdd() 

7 { 

8     return _person.Address; 

9 }

6. Duplicate Observed Data (复制被监视数据)
解释:
      一个良好的系统应该事先业务逻辑 (Business Logic) 与用户界面 (User Interface) 分离, 如果没有这样做, 常见的比如在 Program.cs 堆叠了大量的代码, 业务逻辑与用户界面非常紧密的耦合在了一起. 实现业务逻辑与用户界面分离, 最重要的实现是数据的同步机制, Duplicate Observed Data 重构手段用来完成这项工作. 由于例子较长, 可以独立成篇, 在以后介绍观察者模式 (Observer Pattern) 的时候会搬出来讨论.

7. Change Unidirectional Association to Bidirectional (将单向关联改为双向)
解释:
      如果两个 Class 都需要使用对方的特性, 但两者之间只有一条单向关联 (如只有调用方才能调用被调用的特性), 如果你想让被调用的那一方知道有哪些物件调用了自身, 这时就需要使用 Change Unidirectional Association to Bidirectional.

      通常的做法是在被调用方的代码里定义一个被调用方类型的集合 (Collection), 如 ArrayList<T>, List<T>(推荐使用 List<T>), 在[调用方] 调用 [被调用方] 的时候, 在 [被调用方] 里的集合中也添加一下自己的引用.

8. Change Bidirectional Association to Unidirectional (将双向关联改为单向)
解释:
      使用了Change Unidirectional Association to Bidirectional 之后, 如果需求变了, 发现双向关联是没有必要的, 这时就需要将双向关联改为单向, 也就是 Change Bidirectional Association to Unidirectional, 步骤与 Change Unidirectional Association to Bidirectional 相反.

9. Replace Magic Number with Symbolic Constant (用符号常量取代魔法数)
解释:
   &n

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,