惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
S
Secure Thoughts
C
Check Point Blog
D
DataBreaches.Net
V
V2EX
The GitHub Blog
The GitHub Blog
博客园 - Franky
博客园_首页
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Y
Y Combinator Blog
Last Week in AI
Last Week in AI
H
Help Net Security
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
A
About on SuperTechFans
月光博客
月光博客
Google DeepMind News
Google DeepMind News
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
F
Fortinet All Blogs
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
N
Netflix TechBlog - Medium
GbyAI
GbyAI
G
Google Developers Blog
P
Proofpoint News Feed
Recorded Future
Recorded Future
C
CXSECURITY Database RSS Feed - CXSecurity.com
MyScale Blog
MyScale Blog
T
Threatpost
V
Vulnerabilities – Threatpost
AI
AI
Cyberwarzone
Cyberwarzone
B
Blog RSS Feed
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 最新话题
L
LangChain Blog
Webroot Blog
Webroot Blog
AWS News Blog
AWS News Blog
云风的 BLOG
云风的 BLOG
W
WeLiveSecurity
Latest news
Latest news
U
Unit 42
C
CERT Recently Published Vulnerability Notes
Cisco Talos Blog
Cisco Talos Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Security @ Cisco Blogs
Forbes - Security
Forbes - Security

博客园 - aimin

SharePoint Foundation中文档与文件、单据类型定制办法 SharePoint2010的牛刀:一、新的服务应用程序架构 Silverlight甘特图:五、Gantt图控件[已开源发布Codeplex] Silverlight甘特图:四、树形DataGrid开发原理 Silverlight甘特图:三、甘特图面板开发原理 Silverlight甘特图:二、时间线开发原理 Silverlight甘特图:一、甘特图介绍及开发者之系统准备 SharePoint Silverlight Workspacer 1.0 Silverlight Gantt Chart 改进计划 为业务建模——MOSS的优势与劣势 招SharePoint人才必须看ASP.NET底子 杂谈项目中的那些事儿:计划与变化 杂谈项目中的那些事儿:人的力量 杂谈项目中的那些事儿:理想与现状 【转】7 Signs Your SharePoint Project Is in Trouble 【转】7 Keys to Microsoft SharePoint Success silverlight Gantt Chart Demo Show一下Silverlight写的GanttChart SharePoint特性一览
谈谈代码设计
aimin · 2009-09-05 · via 博客园 - aimin

为什么要重视代码设计?

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

1)       代码构建阶段的设计分散保存在开发人员的头脑中,得不到有效的验证

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

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

1.  管理复杂度

复杂度来源:

1)       用复杂的方法解决简单的问题

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

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

2)       用简单但错误的方法解决复杂的问题

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

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

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

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

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

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

3)       用不恰当的复杂方法解决复杂问题

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

         管理复杂度的方法:

1)       任何人在同一时间只处理必不可少的复杂度

a)         分类汇总

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

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

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

b)         一致的抽象

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

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

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

2)       不要让偶然性的复杂度无谓地快速增长

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

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

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

2.  管理变化

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

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

1)       封装

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

2)       模块化

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

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

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