好代码、坏代码共8页文档

上传人:d****1 文档编号:140969608 上传时间:2022-08-23 格式:DOCX 页数:8 大小:21.48KB
收藏 版权申诉 举报 下载
好代码、坏代码共8页文档_第1页
第1页 / 共8页
好代码、坏代码共8页文档_第2页
第2页 / 共8页
好代码、坏代码共8页文档_第3页
第3页 / 共8页
资源描述:

《好代码、坏代码共8页文档》由会员分享,可在线阅读,更多相关《好代码、坏代码共8页文档(8页珍藏版)》请在装配图网上搜索。

1、好代码、坏代码1 .命名很重要,让代码告诉你它自己命名到底有多重要呢?重要到这几乎是很多软件项目成功或者失败的“罪魁祸首”,究其原因,代码不光支撑 了 0和1在计算机系统中运行的业务逻辑,同时也是开发者进行交流与研究的标准语言。没 有意义或者有歧义的命名,就像两个等待交流的人,面对了一堆火星文无从下口,让交流变 成灾难,也就导致很多问题。同时,好的命名是自说明的,让代码告诉开发者“我是谁,我做什么,我怎么做”。当 然,除了静态式的必要的注释说明之外,动态式的代码也可以包含传递信息的作用,让代码 告诉你它自己,因为代码是“活的代码”。例如,以某个缓存容器为例,泛型参数明确了容器的Key和Valu

2、e的关系,其中的方法 也基本明确了作为缓存容器所具有的方法:Add、Set、Clear、Refresh和IsExist,而TryGet Value是Try-Parse模式的应用体现。其中的变量container表示了容器载体;expiration表示 了过期时间;config表示了容器的配置信息。public class AtCachepublic int Count public List Items public int Expiration public void Add(TKey key, TValue value) public void Set(TKey key, TValue v

3、alue, int expiry)public bool TryGetValue(TKey key, out TValue value)public void Clear() public bool IsExist(TKey key) protected void Refresh() private ReaderWriterLockSlim rwLocker = new ReaderWriterLockS lim();private DictionaryTKey, CacheItem containe r = new DictionaryTKey, CacheItem();private in

4、t expiration;private DateTime lastRefresh = DateTime.Now;private IAtCacheConfiguration config;private List items;总体来说,让代码告诉它自己,是好代码的体现,而一堆没有意义的代码堆积是让人无 法接受和容忍的坏代码。2. 遵守编码规范编码规范,就是编码最佳实践,是前辈在编码这件事上的积累和总结,是智慧的延续和 工业的实践。在软件产业日益蓬勃的今天,软件工业在于如何更有效率地进行生产这件事儿 上,有了巨大的进步和积累,编码规范正是如此。例如可以随意列出很多的规范:命名规范。避免行数过多的

5、方法。代码缩进。异常规范。设计规范。注释规范。文件的组织规范。配置规范。发布与部署规范。测试规范。SQL规范。在以上每个领域都有N条“法规”,以最佳实践的条款被总结出来,每个条款都渗透着 很多前人的智慧。同时,编码规范的应用是有选择和场合的,不同的软件公司和产品,对编 码规范都有一定的理解和取舍。但是,没有规范的编码,一定是有问题、潜伏着坏代码的幽灵。3. 遵守命名规则命名已经被反复强调了,遵守编码规范首当其冲就是对于命名规范的遵守,对于命名规 则,通常可选择的体系主要有:Pascal Casing,混合使用大小写字母,每个单词的首字母必须是大写,例如FirstNa me。Camel Casi

6、ng,混合使用大小写字母,第一个单词的首字母是小写,其他单词的首字 母是大写,例如firstName。匈牙利命名法,通过属性、类型和对象描述混合来表示,例如frmMainWindow,表 示一个窗体实例的命名。不过,对于不同的语言体系而言,一般有着不同的命名规范和体系,很多不同的语言对 于命名规范的选择也有差别。以C#语言为例,最基本的命名规则包括:以Pascal Casing风格定义命名空间、类及其成员、接口、方法、事件、枚举等。以Camel Casing规范定义参数、私有成员。避免使用匈牙利命名法。以Attribute作为特性的后缀。以Delegate作为委托的后缀。以Exception作

7、为异常的后缀。当然,规范还有很多,而这种积累来自于平时对于代码的理解和运用。4. 多注释,少废话代码,一定是给人看的,而代码本身的逻辑又决定于方法、类型和依赖的关系之中,所 以,必要的注释,是必需且必要的。通过注释的进一步解释,来辅助性地告知代码的逻辑、 算法或者流程,不仅是好习惯,更是好代码。第2页另一方面,注释不是“无病呻吟”,没有必要表述那些显而易见的逻辑或者说明,同时 注意区分单行注释和多行注释的应用。在平台下,XML格式的注释还肩负了另一项重要的使命,那就是根据注释生成代码文 档。例如:/ /根据用户信息,构建标签信息/ / Id,根据用户 Id,获取的实例信息/ 签信息 / 标签信

8、息对象 public Tag BuildTag(int memberld, string tag)return new Tag();在 Visual Studio 中,可以通过选择Properties Build 来设置“XML documentation files” 选项输出生成XML信息,例如上面的注释信息被生成为:Anytao.Inside.Ch03.GoodCode根据用户信息,构建标签信息 Id,根据用户 Id,获取的 实例信息 签信息 签信息对象 通过SandCastle工具就可以基于上述信息生成标准统一的文档信息,基于此方式就可以 建立类似于MSDN文档的项目帮助文件,大大简化

9、了这项“复杂”的工作。5.用命名空间组织你的代码命名空间,是逻辑上的组织单元,通过命名空间建立对代码的有机组织,是现代语言的 一大“创举”,Java夜未眠作者蔡学镛说:一个语言是否适合大型开发,可以从它对模块、 命名空间(或类似概念)支持的良窳看出端倪。从这个意义上说,命名空间并不是大型开发 或者团队开发最重要的核心概念,但却是加分的必要因素。关于命名空间的详细内容,请参考7.3节“using的多重身份”。6 .切勿模式而模式设计模式是好的,而滥用模式是不好的。了解和熟悉设计模式,是需要实践和思考的过程,模式并不是一切问题的灵丹妙药,而 且大多时候的滥用反而造成更多的问题。滥用模式体现在两个方

10、面:不慎误用,在不合适的场合应用不合适的模式,例如不是所有的场合都需要引入工厂 解耦对象创建;对于依赖于执行状态的场合,并非只有状态模式一种选择,工作流或 许能带来更好的控制。过度应用,模式的引入都会或多或少地介入了中间层或者中间代码,过度的模式应用 将导致代码复杂度的直线上升,除了会带来性能上的问题还有逻辑上的混乱。举一个简单的例子,策略模式是将算法从宿主类中剥离出来,将易于变化的部分封装为 接口,例如:public interface ITaxdecimal Calculate(decimal value);public class FoodTax : ITaxpublic decimal

11、 Calculate(decimal value)return new decimal(1 + 0.15) * value;public class RetailTax : ITaxpublic decimal Calculate(decimal value)return new decimal(1 + 0.1) * value;对于算法分离而言,通过ITax策略可以很好地进行不同行业(例如饮食FoodTax或者 零售RetailTax)税率的计算,不同的行业提供不同的算法策略,然而对于变化的税率而言, 这种实现的方式略显过度,越来越多的算法策略将造成代码的过度膨胀。所以完全可以对策 略的方式

12、进行改良,利用委托将税率算法分离看起来更加简洁而优雅:public interface ITaxdecimal Calculate(Func rateProvider, decimal value); public class Tax : ITaxpublic decimal Calculate(Func rateProvider, decima l value)var rate = rateProvider.Invoke();return rate * value;一下子清爽了很多,避免了 “策略”带来过度膨胀,又很好地解决了税率算法的变化与 分离,对于客户端的消费并没有太大的差别。倚天屠龙

13、记中有一个重要的片段,张三丰指点张无忌修炼太极,有一段“此时无招胜有 招”的精彩论述,武术上真正的无敌不在乎一招一式的死记硬背,也不在于一刀一剑的激情 挥洒。同样的道理,似乎更适合用于软件设计与模式,很多时候,架构与设计的极致不在于 对模式的“应用”,而在于对模式的“活用”,在于灵魂附体,在于无招胜有招。7 .线程安全很重要线程安全是重要的,在数据共享或同步的场合应将线程安全作为必须考虑的因素,不安 全的代码将在多线程运行时造成严重的问题。例如,单例模式就是这样一个需要特别注意的 例子:public sealed class Singleton Singleton() public stati

14、c Singleton Instance get if (instance = null)instance = new Singleton(); return instance;private static Singleton instance = null;因此,你可以考虑通过“双锁”机制来保证线程的安全,不过在平台还可以有更简单的 实现方式:public sealed class Singleton static Singleton() Singleton() public static Singleton Instanceget return instance;static readon

15、ly Singleton instance = new Singleton();利用静态构造函数只能被执行一次且在运行库加载类成员时的特点,保证了 instance的 线程安全,避免了不必要的锁检查开销。关于静态构造函数,详见8.8节“动静之间:静态 和非静态”。线程安全是个大课题,需要仔细咀嚼。8 .不断地重构和思考软件开发就像爬山,而有意思的事情在于,我们爬的并不是一座山,而是一座又一座的 山,似乎永无尽头。所以爬山的过程其实是这样,爬上了一座,又从这一座下来,然后接着 爬向下一座,并且继续如此反复,才能到最高的巅峰。所以,可以把软件开发中这种不断重构和完善的过程,叫作爬山模型。爬山模型的

16、重点 在于只有通过不断地重构和演进,才能不断地完善和进步,并最终达到软件产品的高峰。代码重构是个系统工程,有很多值得借鉴的方法,在很efactoring: Improving the Desi gn of Existing Code一书中有详细的讨论:以单元测试驱动。提取类、方法、接口或者子类等。重新组织数据。简化函数调用。借助重构工具。9.扩展无处不在扩展性是衡量一个软件产品的重要尺度之一。通过合适的设计为软件系统赋予一定程度 的扩展,是架构师着手设计的重要考虑因素,如图3-16所示。扩展是个大课题,涉及软件系统的方方面面,依赖于粒度不同的架构格局。举例来说, 数据库设计可以考虑在横向或纵向

17、的扩展、在多层架构中实现可适配的数据层、为业务层实 现注入逻辑设计、在UI层提供可配置的界面选择以及为物理架构提供横向扩展的部署设计。 实现基于服务的系统,就意味着在服务层支持扩展良好的高层架构;而一个面向接口的设计, 将是为扩展提供可能的选择之一;采用ASP MVC构建的Web系统,将在很多方面被赋予 扩展的标签,基于管线模型的设计将扩展深入到几乎所有的方面,例如ActionFilter、ViewE ngine、Route、HtmlHelper、ModelBinder以及Controller,开发者可以轻易地替换所有原有 支持元素,扩展出不同的“个性”功能;而MEF(Managed Exte

18、nsibility Framework)则实 现了更灵活的扩展设计,基于MEF可以发现并使用扩展,甚至在应用程序之间重用扩展。在语言层面,考量扩展性的指标遍布于语言特性的各个细节:基于类的继承、组合和多态。面向对象的基本特征就是扩展良好,而的面向对象特性,在本书第1章“OO大智慧”已经有了详细的讨论。面向接口和抽象类,接口和抽象类是语言层的抽象载体,而面向抽象编程的设计原则 在实际编码中的应用之一就是面向接口和抽象类,详见8.4节“面向抽象编程:接口 和抽象类”。基于委托和事件的回调。回调是一种扩展良好的实现机制,提供动态扩展性表现,使 得框架能够以委托来调用用户代码:private void

19、 btnLogin_Click(object sender, RoutedEventArgs e) MessageBox.Show(Hello, Windows Phone.”);就像给框架提供了一个“钩子”来动态地将用户代码扩展到框架的逻辑,在单击按钮的 时候,执行用户代码的流程逻辑,并将这个流程注入到框架行为中。在中,可以通过委托实 现线程的安全回调,而事件正是这种模式的最佳实践,详情参考9.7节“一脉相承:委托、 匿名方法和Lambda表达式”。应用扩展方法。扩展方法,本身就是为扩展而生的,详见13.2节“赏析C# 3.0”。以部分类延伸类的组织,在很多情况下,为了便于组织和物理上的方便

20、,将一个类分 布在多个独立的文件,是一种合适的处理方式;另一方面,对于越来越多的自动生成 代码情况,部分类提供了 “手动”扩展支持。例如,应用LINQ to SQL作为数据访 问层框架时,通常可以通过Visual Studio自动生成实体类:global:System.Data.Linq.Mapping.TableAttribute(Name=dbo.Users )public partial class User : INotifyPropertyChanging, INotifyProper tyChanged在这种情况下,就可以考虑通过部分类的方式,为实体类User增加新的成员、继承统

21、一的基类:public partial class User : EntityBasepublic bool IsAdmin get; set; 通过反射注入。反射特性是平台非常有吸引力的语法游戏,通过反射可以实现动态注 入设计,在3.2节“依赖的哲学”中有详细的讨论。基于DLR实现动态扩展。在4.0中,巨大的变革即是动态编程,为静态语言插上动态的翅膀,让动态扩展无处不在,详见14.3节“动态变革:dynamic”。让扩展可配置。在ASP整体架构中,将Web请求的处理设计为管道模型,模型中的 重要元素包括HttpApplication、HttpModule和HttpHandler等,而对于这些

22、管道中的 过滤器(HttpModule)和处理器(HttpHandler)则通过配置实现可插拔的扩展性设计: 例如,上述配置可以将TimeLogModule注入到HTTP管道,从而将每个请求的处理时 间输出到日志。public class TimeLogModule : IHttpModulepublic void Dispose()public void Init(HttpApplication context) context.BeginRequest += (sender, e) = var sw = new Stopwatch(); HttpContext.Current.ItemsS

23、topWatch = sw; sw.Start();context.EndRequest += (sender, e) = var sw = (Stopwatch)HttpContext.Current.ItemsSt opWatch;sw.Stop();TimeSpan ts = sw.Elapsed;string result = string.Format(0ms”, ts.TotalMi lliseconds);Logger.Log(result);基于ConfigurationManager的配置扩展。一般来说,配置是为扩展而准备的,而扩展 可通过配置注入。在框架中提供非常优秀的配置

24、支持,开发者完全可以通过这套完美 的配置框架实现自定义的配置扩展。口硬编码总是不好的。任何时候都尽可能将变化的部分从代码中分离,以配置或者其他 方式加载,为扩展提供机会。扩展无处不在。软件设计师的职责,在于将这种无处不在深入到软件系统的各个环节, 为各种可能提供基础与准备。10.性能是一把尺子性能,永远是任何软件产品衡量的标准,就像一把标准的千分尺,可以精度准确地为产 品打上分数,在中性能的指标体现在语言的各个方面,在本书6.4节“性能优化的多方探讨” 中,对于性能的问题有详细讨论。11 .信赖的是测试,不是自己质量的保证,一直是复杂的软件开发的软肋,为了保证软件产品的完美,测试是整个开 发流

25、程中最重要的部分。现代软件开发也衍生出很科学的测试方法、方式和制度,不管是黑 盒的还是白盒的,只要逮住Bug,就是好测试。与传统测试方式比较,测试驱动开发(Test Driven Development,TDD)已经被证明是 非常靠谱和科学的开发方式。TDD至少在两个方面为软件开发注入活力:保证质量。足够的覆盖率将能保证软件质量和稳定性,系统的修改和变化将第一时间 反馈在测试代码上,结果驱动的方式将能最大限度地评估变化对原有系统造成的影响, 从而保证业务代码的正确性。驱动设计。另一方面,为了能够让业务代码具有可测试性,你应重新审视业务代码的 设计,就像Bob大叔的名言:编写单元测试更像一种设计

26、行为,文档行为而不是验证 行为。编写单元测试缩短了反馈周期读数,最小读数基于功能验证。因此,测试驱动是值得提倡和普及的,将由人的信任测试,转变为由代码的信任测试,信任的是测试,而不是开发者自己。12.是进度还是质量,平衡是关键开发者经常挂在嘴边的一句话是:给我足够的时间,我将实现得更好。然而,实际的情 况往往是,开发的周期和开发的进度总是存在着冲突,进而带来进度和质量之间的妥协,而 妥协的关键在于平衡。作为开发者而言,需要评估设计和实现所花费的时间,然后根据评估的结果对进度做以 平衡,很多时候,并没有一次就很完美的设计,只有当下适合的设计。平衡进度与质量的关 键,是建立起行之有效的开发流程和进度计划,将资源、进度和质量有机地整合在可控制的 框架管理中,并准备好三个要素之间的缓冲带,在适合的时候做好调整的准备。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!