OO 之美:设计的分寸

本节将介绍以下内容:

  • 设计的由来
  • 浅谈重构

设计的分寸

引言

有了前面两章“OO 大智慧”和“OO 大原则”的铺垫,相信读者已经有了对面向对象的基本认知。而本章将继续深入关于面向对象和设计问题的讨论,挑起设计与架构的话题。在高级语言横行的今天,对于静态语言的设计都源于面向对象思想,重构与设计都基于这些简单的标准。

然而,对于设计,还有很多看似“惯常”的法则与经验广泛存在于软件系统中,例如除了经典的 23 种设计模式,还有很多模式之外的模式,按照粒度的大小、系统的特点、规模的大小,而形成的架构规则。

对设计来说,或许永远没有唯一的答案,你只能无限地接近最好。

设计,没有唯一的答案,但是把握分寸,却是软件设计中需要“用心良苦”的部分。

设计由何而来

设计,从何而来?是需求。是重构。

设计原则是系统设计的灵魂,而设计模式是系统开发的模板,灵活自如的应用才是设计以不变应万变的准则。例如,实现一个用户注册的方法,首先会想到:

// 初次设计
public void Register(string name, Int32 age)
{
}

在一定的需求条件下,这个方法已经能够经受系统的考验,安全而平稳地向数据库中不断插入新的用户信息。然而,当需求发生变化时,你可能不得不对此做出调整,而我们就将这种调整称为重构。但是重构远不是扩充,而是设计。例如,现在的注册项发生了变化,还需要同时注册性别、电话,没有设计的调整,就被实现为:

// 需求变更
 public void Register(string name, Int32 age, bool isMale, Int32 phone)
 {
 }

通过重载方式,一定程度上解决了这一问题,然而这种不能称为重构的调整,至少存在以下的弊端:

  • 有新增的注册信息时,还要通过不断地重载 Register 方法来实现更多信息的扩展。
  • 方法 Register 的参数列表实在太长了,这不是优雅的代码实现。
  • 需要修改系统中相关的方法调用来适应新的重载方法。

僵化的调整失去了设计的灵活性,没有思考的程序只能使程序的扩展和维护变得不可收拾,其实对于上述问题,只需要进行简单的重构,就可轻松避免上述3个弊端,实现更加柔性的系统。例如,简单重构如下:

public class UserInfo
{
    public string Name { get; set; }
    public Int32 Age { get; set; }
    public bool Gender { get; set; } 
}

通过将用户信息封装为一个类,实现更加简单的参数列表,同时其带来的好处还远不止避免了上述3个缺陷,而且能带来对用户信息的封装,实现更可靠的信息隐藏和暴露:可以通过字段和属性封装,实现对于成员的只读、可读可写权限的控制。.NET 3.0 的自动属性为属性封装实现了更为优雅的语法游戏,这些特性让 C# 成为更具有吸引力的高级语言(详见13.2节“赏析C# 3.0”):

// 定义可读可写属性
public string Mobile { get; set; }

// 定义只读属性
public string Password { get; private set; }

实现一定的逻辑封装,例如对于电子邮件,可以检查其合法性:

private string email;

public string Email
{
    get { return email; }

    set
    {
        string strReg = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
        
        if (Regex.IsMatch(value, strReg))
            email = value;
         else 
            throw new InvalidCastException("Invalid Email Address.");
    }
}

那么,设计是如何实现和建立的呢?答案就是面向对象。正如上述演化过程一样,其中应用了面向对象中的封装要素,完成了更加柔性的设计。在1.3节“封装的秘密”中,我们就对封装展开了详细的探讨,基于实例的应用和对 .NET 实现本质的分析,能够更加强化对于面向对象基本要素的理解。这些面向对象的思想和应用,来自于实践,完善于重构。

从此重构

设计是如此重要,那么开发者的基本设计能力与素质又从何下手来培养呢?最好的办法,就是请个老师。从框架中了解,从系统中实现,从书文中汲取。然而,设计能力的提升绝非一朝一夕之功,软件开发中的设计大师,往往必须具备多年的修行方可称之为“架构师”。

一个在简历中轻描淡写的“10年软件设计经验”,并非是所有软件人都能修炼成的真功夫,这里没有任何虚情假意可言。在一个项目的实现过程中,逐渐了解什么是对象、什么是对抽象编程、设计模式是如何应用在实际的系统架构、设计原则到底是什么秘密武器,而重要的是完成一个软件项目,对于更多人来说是认识一种软件开发的科学流程。这种体验,才是难能可贵的经验。在设计的广义概念里,几个必需的概念是应该首先被了解和认知的,以排名不分先后的原则罗列,它们大概包括:

  • 面向对象(Object-Oriented)
    关于面向对象没有必要重复嚼舌了,本书的第1章“OO 大智慧”中对 .NET 的面向对象进行了有别于其他专著的介绍,除了以实例突出面向对象之思想大成,还以浓墨铺陈了 .NET 是如何在底层技术上来实现继承、多态和接口映射等机制,从而使读者可以更加有效和深刻地把握面向对象之精髓。
  • 面向服务(Service Oriented)
    SO至少是个时髦的话题,WCF 伴着.NET 3.5 的发布,一个一统江湖的面向服务的基础架构横空出世。可以想象的是,未来的分布式系统架构将变得更加柔性和统一,简单而有效。
  • 框架(Framework),所谓框架就是应用系统构建所需的基础设施。
    应用程序是变化万千的,而基础架构则是相对稳定的。这正如我们基于 .NET Framework 来实现数以万计的 .NET 应用:Windows Form Application、Web Form Application、XML Web Service 等,都体现了框架和应用的关系。.NET Framework 本身就是一个基础性架构,正如经典的MFC一样,提供了.NET应用赖以生存的基础性支持。对于框架的探索和实践,应该是每个有意提高设计能力的开发者的必经之路。选择一个或几个典型的框架进行梳理与实践,才能有效地了解软件世界的庞大体系是如何和谐统一地运作。从经典框架设计中,寻找灵感,锻炼体验,例如分享经典案例 Petshop 三层架构的实践体验,通过真正的需求、设计、开发和测试,而在这个旅程中我们就能完成从概念到实践、从表面到思想的体验。
  • 设计原则(Design Principles),是面向对象设计程序开发的思想大成,了解面向对象,深入设计模式,则有必要深入设计原则之精髓。可以不了解全部的设计模式,但必须深入每一个设计原则。一个是内功,一个是招式,设计的第一项修炼就从内功开始。本书第2章“OO大原则”对5大设计原则进行了一些以例说理式的实际探讨和分析,几个看似简单的设计原则:单一职责原则、开放封闭原则、依赖倒置原则、接口隔离原则、Liskov 替换原则,这 5 个原则贯彻了一个简单的思想——“面向抽象,松散耦合”。
  • 设计模式(Design Pattern)
    23个设计模式,23个经典智慧,了解和掌握几个重要的设计模式,是修炼面向对象招式的必经之路。无论如何,作为设计者你应该在自己心中知道什么是 Abstract Factory、Iterator、Singleton、Adapter、Decorator、Observer、Façade、Template、Command。
  • 模式之外,除了23个经典的设计模式,其实还存在很多模式之外的模式,按照粒度的不同而广泛应用在实际的项目系统中。
    例如,在 SOA 系统中的 Event driven Architecture、Message Bus 以及分布式 Broker 模式;数据持久层的 Repository、Active Record 还有 Identity Map模式;可伸缩系统下的 Map/Reduce、Load Balancer 以及 Result Cache 模式;更高架构层面的MVC、MVP 以及 Pipeline/Filter 模式。在某种意义上而言,模式是一种经验的积累和总结,对于系统设计与架构考量,架构师要完成的不仅仅是对功能性需求的把握,还包括非功能性需求、平台与框架的平衡、性能与安全的考量。

在本书第1部分,以“OO大智慧”和“OO大原则”两章的篇幅,分别讲述了关于面向对象的实现本质和思想理念,以面向对象技术在 .NET 中的应用为起点,熟悉和领略面向对象的智慧与原则,修炼深入 .NET 技术的基本功,为深入理解 .NET 的程序设计打好必备的基础。而本章将对以上设计问题继续探讨,从点点滴滴入手来关注设计环节的下一个据点。

所以,下面我们将对软件开发中的设计与架构进行更多的探讨,以期收获更多的共识与争论。

结论

周星驰在《食神》中历经磨难之后参加食神大赛,做了一顿令人抓狂的黯然销魂饭,并对对手说了句:其实每个人都是食神,引来对手不屑。同样,现实世界的历练也渗透着同样的感悟,每个人都是食神,或者说每个人都可以是食神。软件设计与架构同样如此,不经一番寒彻骨,哪得梅花扑鼻香。

其实每个人都是食神,其实开发者都是设计师。关键在于掌勺的你,是否能让做饭的家伙油光锃亮。

其实,在设计的领域,你大可不必为看似高深的框架吓倒,也不必为没有经验而怯场。在每个人的代码生涯中,你随时可以是食神,就像上例中通过简单 Extract Class 重构方法,你就可以体验一次化腐朽为神奇的力量。所以,设计无处不在,架构如影随形。而如何将三层架构、Abstract Factory、Extract Method、MVC、OCP 这一竿子打不着的概念有机地、科学地、合理地体现在活生生的软件系统中,是一种功力和经验的体现。

作为学习者,如果还不具备在宏观上把握如何将上述模糊的概念进行统筹和消化,那么作为预备设计师,首先要做好的工作就是先逐个认识 SOA、Mapper、Pipeline、DTO、Message Bus 这些概念,有了基本功之后再看着唱本骑驴走远。

基于STM32F407,使用DFS算法实现最短迷宫路径检索,分为三种模式:1.DEBUG模式,2. 训练模式,3. 主程序模式 ,DEBUG模式主要分析bug,测量必要数据,训练模式用于DFS算法训练最短路径,并将最短路径以链表形式存储Flash, 主程序模式从Flash中….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值