简述为什么要重视.NET代码设计

开发 后端
这里将简单谈谈为什么要重视.NET代码设计,这样的原理也有助于大家更好的规范代码结构,希望本文能对大家有所帮助。

.NET代码设计的重点在于重视程度,也就是开发人员需要集中思想,提前做好准备工作。如果不重视,很可能出现太多的public会让使用这些class的二次开发的人员无所适从的局面。

为什么要重视.NET代码设计?

在绝大多数项目中,尤其是在大型、资源缺少(这是软件项目的典型现象)的项目中,正规的架构可能只是解决系统级的事项,而特意把大部分的设计工作留待代码构建阶段去做。这可能会引发两个问题:

<!--[if !supportLists]-->1)       <!--[endif]-->代码构建阶段的设计分散保存在开发人员的头脑中,得不到有效的验证

<!--[if !supportLists]-->2)       <!--[endif]-->由于开发人员各有所长,也各有所短,往往在进行了部分或完成代码构建后,问题才能被明确。最终,不合理的设计导致大量的重构工作,延误项目工期。

设计工作千头万绪,然而软件设计的首要使命是“管理复杂度”;重点和难点是“管理变化”。虽然“管理变化”是“管理复杂度”的内容之一,但由于“管理变化”具有突出的重要性,因此单独进行介绍。在代码构建整个过程中,所有设计工作必须充分考虑这两个方面,从而实现高质量代码。

<!--[if !supportLists]-->1.  <!--[endif]-->管理复杂度
复杂度来源:

<!--[if !supportLists]-->1)       <!--[endif]-->用复杂的方法解决简单的问题

这个现象通常出现在过度设计上:首先是简单的问题复杂化,然后对复杂化的问题使用复杂的方法。

如在10个有序数字中检索某个数字。按照目前的CPU运算速度,直接采用顺序检索简单有效。如果盲目考虑CPU运算的因素,采用二分法检索,反而导致逻辑冗余。但是,如果对位数过万的数组进行检索,则应采用二分法或其它更有效的算法。

<!--[if !supportLists]-->2)       <!--[endif]-->用简单但错误的方法解决复杂的问题

由于设计是一个由浅入深,不断尝试,不断失败,最终得到正确结果的过程,因此,在代码构建之初,当设计者未能正确考虑复杂问题的各个方面,将复杂问题简单化后,将会导致“用简单但错误的方法解决复杂的问题”。

对此,我说一下自己的一个切身体会,在SharePoint开发中,我们一个常见的问题是“内容数据库非关系型数据库”,虽然Moss提供了Lookup类型的字段来建立这种关系,但是存在两个问题,首先是不能跨站点,更不能查询多个列表的内容,也不能综合显示多个字段的内容。这些缺陷对于很多应用来说,似乎是致命的。为此,我曾经设计出同时支持跨网站、跨列表、多字段的自定义Field。但是设计中欠缺考虑,以致完成该Field的开发后,一个显著的缺陷让我头疼不已:将关联关系存储与字段值中,虽然在显示、编辑和存储上简化了编码工作,但是却未能解决关联关系本质上的问题,从而导致了一系列更为复杂的问题的出现,如反向关联查询,关联同步,以致于花费了大量的精力来维护这种关系。

在该字段新版本的设计中,我将关联关系单独存储在一个列表中,同时扩展基内容类型的New & Edit Form。嵌入维护不同列表间项与项关系的可视化展示与编辑部件(基于Silverlight实现)。顺便提一下,使用了多年的Flex,发现Silverlight除了在基础组件库上略逊色外,性能方面还是很不错的,尤其是继承自NET的垃圾回收机制。

但是无论是Flex和Silverlight,都要注意它在图形绘制方面的局限性,当需要绘制的组件和图表过多时,尽量只绘制ViewPort中的部分,否则性能问题将导致整个程序的崩溃。


总结一下,如果使用简单但错误的方法解决复杂问题,那么代价会在后面成几何级数回馈给你。

套用一句话:代码无小事!

<!--[if !supportLists]-->3)       <!--[endif]-->用不恰当的复杂方法解决复杂问题

在旧有经验的指导下,某些复杂问题的表象会误导设计者,将之当作另外一个曾经发生过的复杂问题,而问题本身的复杂程度也令人望而却步,不愿做进一步的分析,直接套用已有的解决方法虽然省事,却有可能“用不恰当的复杂方法解决复杂问题”。

管理复杂度的方法:

<!--[if !supportLists]-->1)       <!--[endif]-->任何人在同一时间只处理必不可少的复杂度

<!--[if !supportLists]-->a)         <!--[endif]-->分类汇总

从问题的领域着手,而不是从底层实现细节入手去编写程序,在最抽象的层次上工作,也能减少人的脑力负担。

问题的领域在不同抽象程度上,可以划分为不同的级别:业务,子系统,功能模块,类、子程序。通常,从较高的领域分解下来,会有效的降低问题的复杂程度。如在子系统级别确定好每个功能模块接口,那么在进入功能模块领域后,你只需要关心少量的接口,而把更多的精力放在该功能的数据、逻辑和UI设计上。

C#等面向对象语言可以轻易实现这种抽象,通过定义基类或抽象类(如C#中的abstract 关键字)。

<!--[if !supportLists]-->b)         <!--[endif]-->一致的抽象

定义基类或抽象类时,必须保持同级别抽象的一致性,摒除不必要的细节。

如ASP.NET编程中的Page和Control就属于同一级别的抽象。 在Page类的实现中,它无需知道具体是什么类型的Control,是DataGrid还是TextBox,它根本不关心,它只关心Control类中的Render()可以提供什么样的Html。而这个Control是红的还是绿的,是方的还是圆的,根本不需要关心。如果编写Page类时调用了Control的一个子类,那抽象就不一致了,Page将自动降级,Page对于Control基类毫无意义。当然,这样的错误谁也不会去犯,仅仅用来说明这个道理而已。

在SharePoint中,通常我们也会实现一些基础类以提高团队的开发效率,如BaseAjaxWebPart、BaseAjaxField等等。这些Base类中一定不要使用某些实现了特定细节的类或组件。

<!--[if !supportLists]-->2)       <!--[endif]-->不要让偶然性的复杂度无谓地快速增长

偶然性的复杂度,即潜在的变化,包括:已知的未知、未知的未知。

对于未知的未知这种情况,我们可以不过多考虑,只需要根据经验在任务工期上预留一定资源:时间、人力等。

对于已知的不确定的变化,在下面《管理变化》中简要介绍。

<!--[if !supportLists]-->2.  <!--[endif]-->管理变化

没有变化的程序是不可能存在的。但不能让变化像病毒一样蔓延到整个程序。

管理变化的手段比较多,如24种设计模式,大部分都是解决这个问题的。但万变不离其宗,主要还是以下两个方面:

<!--[if !supportLists]-->1)       <!--[endif]-->封装

通过有效的继承和一致的抽象,可以确保发生变化时,最小的代码改动量。

<!--[if !supportLists]-->2)       <!--[endif]-->模块化

通过对系统模块化及划分界面,确定接口,可以有效地将变化控制在模块内部。

使用封装和模块化来管理变化时,必须注意隐藏信息:该使用private之处,绝不要使用protected。该使用protected之处,绝不要使用public。Internal也不要多用,它的作用域是程序集内部,在编写代码时,往往跟public一样混淆视听,降低了代码的可读性。

太多的public会让使用这些class的二次开发的人员无所适从。充斥着非必要public成员的class,不符合管理复杂度的原则。有可能是设计原因,也有可能是未按照设计严格编码。

.NET代码设计的要点就介绍到这里。

原文标题:谈谈代码设计

链接:http://www.cnblogs.com/ghner/archive/2009/09/05/1560998.html

【编辑推荐】

  1. 深入浅出.NET接口:阿猫阿狗和程序员
  2. 程序员如何选择入门编程语言?
  3. 程序员最常犯的五大非技术性错误
  4. Java程序员的知识架构浅析
  5. 专家级程序员的“饲养”心得
责任编辑:彭凡 来源: 博客园
相关推荐

2019-11-17 22:38:13

PAM特权访问管理CISO

2022-06-02 08:48:39

Go枚举器Iota

2015-11-16 14:52:24

CephOpenStack分布式存储

2020-06-16 08:17:11

代码空格开发

2010-10-09 09:20:08

.NET

2022-01-19 22:51:57

设计匿名用户

2022-03-31 11:38:09

经营分析传统企业运营商

2023-05-04 11:39:17

经营分析流量项目

2021-02-01 08:02:11

设计模式接口

2014-08-28 11:12:14

谷歌

2011-08-15 10:10:47

编程

2015-08-06 10:14:15

造轮子facebook

2022-08-15 08:27:02

基站网络

2013-03-12 14:30:09

Ubuntu操作系统

2021-11-19 09:49:00

CC++语法糖

2021-02-11 13:30:56

Nodejs源码c++

2017-09-08 08:35:16

Android代码API设计

2019-11-27 10:25:15

SaaS云端IT架构

2019-03-19 08:59:13

物联网IOT技术

2014-08-25 10:00:18

开源
点赞
收藏

51CTO技术栈公众号