C# - 代码重构
隐藏更多
只暴露集合中供人使用的单一功能,将关于集合的更多功能隐藏掉。
旧版本
{
private List<string> LanguageList = new List<string>
{
"#$%^",
"@*&#",
"中文",
"英文"
};
public IList<string> GetLanguageList( )
{
return LanguageList;
}
}
public class Programe
{
static void Main( string[] args )
{
Animal a = new Animal( );
var language = a.GetLanguageList( );
language[0]=
}
}
IList<T>具有索引器,可以通过数组检索的方式设置元素的值,而我们只想让用户调用枚举器对集合进行简单的迭代或查询,但并不需要他们插手对集合元素的值的更改。所以此时就要考虑让GetLanguageList方法返回一个IEnumerable<T>,由于IEnumerable<T>只有一个GetEnumerator的方法,它没有索引器,所以它只能提供一个枚举器供用户调用,从而防止了集合元素被修改的可能。
新版本
{
return LanguageList; //方法返回的LanguageList隐式转换为了IEnumerable<string>
}
提升成员
将完全重名的字段、属性、方法提升到基类,供每个子类调用。
聚合模拟多继承
为了使没有逻辑上的继承关系的两个类强行发生关系,可以将其中一个类作为另一个类的成员来存取。
抽象解耦
如果其它类需要与某个类(x)发生关系,则可以将x类抽象成一个接口,将其成员抽象到接口中,其它类只需要和接口发生关系,而不需要直接与x发生关系,好处在于如果今后删除了x,我们还可以创建y类来实现接口,这样就不会影响与接口发生关系的那些类。接口就像角色那样,x具有这个角色所要求的的功能,所以x=此角色,y具有这个角色所要求的的功能,那么y也=此角色,对于其它想要与x发生 关系的那些类来说,它们完全可以只需要与角色发生关系,而不用在乎这个角色是由谁来扮演,所以如果x后来死掉了,它们是不用感到惊慌失措的,因为它们只关心和其发生关系的角色。
用属性替代字段
关键思路:多使用属性,少用字段。因为字段过于粗略,而属性由于多了两个方法块,就可以提供更精细的操作逻辑,在设置或获取数据之前你就可以编码出更多的细节控制。
常量封装
如果一些频繁使用的常量总是存在于方法的代码块中,假如有100个方法都在使用这些常量,而今后需求变更,需要更改这个常量值,你就需要把存在于100个方法中的这个常量值给修改掉,工作量巨大而且毫无乐趣,简单的办法就是,将这种普遍存在于各个方法中的常量封装成一个方法的返回值抑或封装到枚举中以应对将来可能发生的需求变更,需求变更时,只需要在封装的方法里或枚举中修改这个常量值即可。
方法分割
如果一个方法中的逻辑代码过于臃肿,就很难让人去尝试阅读,也不方便调试,更不利于需求变更时的代码修改,方法应该作为一个单一的功能供其它方法调用,所以,将一个有N个操作逻辑的方法分割成多个方法,每个方法只提供一个单一的功能,这样就更便于阅读、理解和修改。
封装条件
如果一个条件判断中有多个条件,这会使代码难以阅读,将条件的逻辑判断封装成望文即可生义的属性或方法后,只需要使用属性或方法做判断即可。如果条件需要用某个参数做判断则把判断的逻辑定义成方法,否则定义成属性即可。
旧版
{
public void Show( string arg )
{
if (arg.Trim( new char[] { 'u', 'p' } ).Length > 10 && arg.Contains( "s" ) && arg.LastIndexOf( "a" ) != -1) { }
if (DateTime.Now.Hour == 12 && DateTime.Now.DayOfWeek == DayOfWeek.Monday && DateTime.Now.DayOfYear == 1984) { }
}
}
新版
{
public bool IsArgPass( string arg ) { return arg.Trim( new char[] { 'u', 'p' } ).Length > 10 && arg.Contains( "s" ) && arg.LastIndexOf( "a" ) != -1; }
public bool IsNowTimePass { get { return DateTime.Now.Hour == 12 && DateTime.Now.DayOfWeek == DayOfWeek.Monday && DateTime.Now.DayOfYear == 1984; } }
public void Show( string arg )
{
//望文生义,IsArgPass表示参数是否通过测试
if (IsArgPass( arg )) { }
//望文生义,IsDatimePass表示当前时间是否正确
if (IsNowTimePass) { }
}
}
移除条件
如果一个类需要根据条件调用不同的方法,假如有100个条件就需要判断100次。这样就降低了代码的复用性和灵活性。为此,可以使用一个简单的策略,将条件作为哈希字典的key,将对应的方法作为哈希字典的Value,当用户传递一个条件到类中,类只需要从哈希字典去取出Key所对应方法即可。
旧版本
public enum Country { UnitedKingdom = 1 << 1, Japan = 1 << 2, China = 1 << 3 }
//语言
public class Language
{
public void UnitedKingdomLanguage() { Console.WriteLine( "hello" ); }
public void JapanLanguage( ) { Console.WriteLine( "ハロー" ); }
public void ChinaLanguage( ) { Console.WriteLine( "你好" ); }
}
//服务
public class Service
{
private Language Language = new Language( );
//根据国籍提供不同版本的语言对话
public void ShowLanguage( Country country )
{
switch (country)
{
case Country.Japan:
Language.JapanLanguage( );
break;
case Country.China:
Language.ChinaLanguage( );
break;
case Country.UnitedKingdom:
Language.UnitedKingdomLanguage( );
break;
}
}
}
service.ShowLanguage( Country.Japan );
新版本
public enum Country { UnitedKingdom = 1 << 1, Japan = 1 << 2, China = 1 << 3 }
//语言接口
public interface ILanguage
{
void UnitedKingdomLanguage( );
void JapanLanguage( );
void ChinaLanguage( );
}
//语言
public class Language:ILanguage
{
public void UnitedKingdomLanguage() { Console.WriteLine( "hello" ); }
public void JapanLanguage( ) { Console.WriteLine( "ハロー" ); }
public void ChinaLanguage( ) { Console.WriteLine( "你好" ); }
}
//服务
public class Service
{
private ILanguage Language;
private Dictionary<Country,Action> LanguageMethodDictionary { get; set; }
public Service( ILanguage language )
{
this.Language = language;
LanguageMethodDictionary = new Dictionary<Country, Action>
{
{ Country.China, Language.ChinaLanguage },
{ Country.Japan, Language.JapanLanguage },
{ Country.UnitedKingdom, Language.UnitedKingdomLanguage },
};
}
//根据国籍提供不同版本的语言对话
public void ShowLanguage( Country country )
{
LanguageMethodDictionary[country]( );
}
}
service.ShowLanguage( Country.Japan );
尽早返回
如果一个方法中有大量的条件分支语句,这会使得整个逻辑走向变得不清晰,最佳做法是尽早return,把不满足条件的情况尽早返回,这样可以使代码更容易理解和阅读。
C# - 代码重构的更多相关文章
- 让代码重构渐行渐远系列(3)——string.Equals取代直接比较与非比较
重构背景及原因 最近由于项目组的人员在不断扩充,导致项目中代码风格各异,大有百花齐放甚至怒放之势.考虑到团队的生存与发展,经过众人多次舌战之后,最终决定项目组根据业务分成几个小分队,以加强团队管理与提 ...
- C++代码重构——从C global到C++ template
在学数据结构的时候,我常有这样目标--写出能够最大程度复用的代码(算法正确,封装优秀).我常想--如何能在短时间内达成"算法正确,封装优秀"这样的目标.经过一段时间的摸索,我的结论 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换
前言 上一篇中,我们用了反射工厂来解除BLL和UI层耦合的问题.当然那是最简单的解决方法,再复杂一点的程序可能思路相同,但是在编程细节中需要考虑的就更多了,比如今天我在重构过程中遇到的问题.也是接下来 ...
- CSS代码重构与优化之路
作者:@狼狼的蓝胖子 网址:http://www.cnblogs.com/lrzw32/p/5100745.html 写CSS的同学们往往会体会到,随着项目规模的增加,项目中的CSS代码也会越来越多, ...
- NET代码重构
记一次.NET代码重构 好久没写代码了,终于好不容易接到了开发任务,一看时间还挺充足的,我就慢慢整吧,若是遇上赶进度,基本上直接是功能优先,完全不考虑设计.你可以认为我完全没有追求,当身后有鞭子使 ...
- 代码重构 & 常用设计模式
代码重构 重构目的 相同的代码最好只出现一次 主次方法 主方法 只包含实现完整逻辑的子方法 思维清楚,便于阅读 次方法 实现具体逻辑功能 测试通过后,后续几乎不用维护 重构的步骤 1 新建一个方法 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十一) 代码重构使用反射工厂解耦
前言 自从此博客发表以及代码开源以来,得到了许多人的关注.也没许多吧,反正在我意料之外的.包括几位大牛帮我做订阅号推广,真的很感谢他们.另外,还有几个高手给我提了一些架构上的问题.其实本身这个项目是没 ...
- CSS代码重构
CSS代码重构的目的 我们写CSS代码时,不仅仅只是完成页面设计的效果,还应该让CSS代码易于管理,维护.我们对CSS代码重构主要有两个目的:1.提高代码性能2.提高代码的可维护性 提高代码性能 提高 ...
- 多线程的练习----妖,等待唤醒,代码重构,lock到condition
× 目录 [1]需求 [2]妖的出现和解决 [3]等待唤醒 [4]代码重构 [5]改成Lock Condition ------------------------------------- 1,需求 ...
- 推荐五款优秀的PHP代码重构工具
在软件工程学里,重构代码一词通常是指在不改变代码的外部行为情况下而修改源代码.软件重构需要借助工具完成,而重构工具能够修改代码同时修改所有引用该代码的地方.本文收集了五款出色的PHP代码重构工具,以帮 ...
随机推荐
- bat——批量删除文件文件夹
bat批处理,在工作中会带来很多便利. 例如:想删除多个文件夹内的文件夹“Quality”及其子文件 同时删除所有Cyc*文件夹内的所有R00*.tif文件 则可如下操作 先建立父bat文件run_d ...
- Spring Boot:The field file exceeds its maximum permitted size of 1048576 bytes
错误信息:The field file exceeds its maximum permitted size of 1048576 bytes原因是因为SpringBoot内嵌tomcat默认所能上传 ...
- UI Automator 常用 API 整理
主要类: import android.support.test.uiautomator.UiDevice; 作用:设备封装类,测试过程中获取设备信息和设备交互. import android.sup ...
- 在 .NET Core 中结合 HttpClientFactory 使用 Polly(上篇)
译者:王亮作者:Polly 团队原文:http://t.cn/EhZ90oq 译者序一:前两天写了一篇文章 .NET Core 开源项目 Polly 介绍,在写这篇文章查看 Polly 资料时,看到了 ...
- alert执行时机和js线性模型 事件循环
<div class="test">测试内容</div> <script> $('.test').text('内容改变') alert($('. ...
- 云计算openstack共享组件(3)——消息队列rabbitmq
队列(MQ)概念: MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链 ...
- Google Translation Via Python
没什么好说的,直接送包 https://github.com/mouuff/mtranslate
- ORM基础之字段及其参数介绍
一.外键ForeignKey 1.字段参数 1.to 设置要关联的表 2.to_field 设置要关联的表的字段(一般不设置,默认使用主键id关联) 3.related_name 反向操作时,使用的字 ...
- Hive 口袋手册
2019-04-01 关键字:Hive 学习总结.Hive 基础 . Hive 进阶 .Hive 调优 . Hive 入门手册.Hive PDF 下载 本篇文章系本人就目前所掌握的知识对 Apache ...
- MT【315】勾股数
(高考压轴题)证明以下命题:(1)对任意正整数$a$都存在正整数$b,c(b<c)$,使得$a^2,b^2,c^2$成等差数列.(2)存在无穷多个互不相似的三角形$\Delta_n$,其边长$a ...