• 重构!重构!重构!


    站在用户的角度而不是程序员的角度来思考问题,才能设计出好的软件!

    从要实现的所有系统功能清单(用例)中选取最重要的,优先编程实现。

    根据能投入开发的人力和物力资源设计切实可行的开发计划。

    当你发现在程序中有多个地方都需要实现同一功能时,请将此功能代码抽取为独立的可重用的组件,不要到处Copy & Paste。You Ain’t Gonna Need It(绝不“画蛇添足”YAGNI原则)

    用最简单的方法,仅仅只实现你所需要的功能。
    在确实需要时,才进行抽象和封装
    不要“想象”用户会需要什么,自作主张地在系统中添加新功能。

    不要过度设计,在满足需求的前提下,采用的软件设计方案越简单越好。
    KISS原则的另两种表达:Keep It Short & Simple(追求短小精悍);Keep It Simple & Straightforward(追求简洁明了)

    Don’t Do It Yourself(不要一切自己动手)不走极端,要走“中庸”之道

    针对一些简单的问题,使用各种“框架”,确实显得“用牛刀杀鸡”,并非最佳方案。
    全部自己动手,则开发效率较低,隐藏BUG较多,系统不易稳定,亦非最佳选择
    多数场景下,尽可能地复用,但不排除在特定场景下“自己动手”,“重新发明轮子”或“造新轮子”。

    文档和UML图本身不是设计,最后产生的程序和代码才是设计

    僵化的设计:设计无法响应需求和外部环境的变化,一有改变,必须推翻重来。 

    在代码中“写死”要读取的文件路径
    UI控件直接设定底层数据源的字段名
    数据库表要加一个新的字段,结果导致N处地方需要更改

    脆弱的设计

    “不敢”对软件进行改动,进行一个小的改动,其他地方就出错,甚至整个系统崩溃……

    无法重用的设计

    系统中包容了对其他系统有用的部分,但是要把这些部分从系统中分离出来,却非常困难:

    过于复杂的设计

    完成一件事情有N种方式,选择复杂的那种。

    明明可以用Python写个小程序就能解决的问题,用C++来写……
    我需要保存一些数据到数据库的一个表中,使用Entity Framework这种重量级的框架……

    想得过多,过度设计。

    为了未来“可能发生”的变化,我先写一些可以应付这些变化的代码……
    唔,我要实现这个功能,有一个“XXX模式”正好用上,就用它吧……

    区分命令与查询

    对象的状态

    在某个一时刻,对象所有字段/属性值的集合构成对象的“状态”。
    Tell, Don’t Ask(告诉,而不询问):你应该告诉对象你需要他们干哪些事,而不要去查询他们的状态,再依据这些状态来决定你该采取什么行动。这些工作,应该封装到类的内部,由类自己完成。
    应用这条原则有助于避免类之间的紧耦合。

    命令 vs 查询

    类所定义的所有方法,可以分为两类:
    直接修改对象的字段值,导致其状态改变(或者对外部环境有直接影响)的,称为“命令(Command)”
    仅提取信息,并不改变对象自身及外部环境状态的,称为“查询(Command)”

    命令方法的执行会改变对象的状态,因此它是有“副作用( side effects )”的,而查询方法则不会。
    命令方法内部可以调用查询方法,但查询方法一定不能调用命令方法。
    命令方法通常没有返回值,而查询方法肯定有返回值。
    查询能够被安全地调用多次。

    类方法设计的准则

    你向对象发出的要不是Command,要不是Query,而不能同时是Command和Query。
    如果一个方法既是命令又是查询,那么不看代码,你是不知道它能做什么事的。

    区分命令和查询,有助于提升代码的可读性。

     

     

     

     

    不要生搬硬套,应该在理解的基础上活用这些知识。
    • 在实际开发中,不要强求一开始就能把类设计得很好,而应该用好“重构”这一利器:先把东西做出来,然后再不断地重构……

    什么是类的职责?

    类的“职责(Responsibility)”,指的是类实现的功能和承担的数据处理任务。
    + OOD设计原则:
    • 每个类的职责必须明确;
    • 每个类只承担一项职责。

    避免过大的类

    God object:指的是能“干一切事”的类,它就象上帝一样,负责”创造一切“,有它,其它的类都要靠边站。
    C#中的Socket类,定义有27个属性,近100个方法
    类承担的职责越多,它就越容易受到外界的影响,因为各种原因必须修改它的可能性就越大。

    General Responsibility Assignment Software Pattern(通用职责分派软件模式GRASP原则)

    •Creater
    •Controller
    •Pure Fabrication
    •Information Expert
    •High Cohesion
    •Indirection
    •Low Copupling
    •Polymorphism
    •Protected Variations
    应用这些原则有助于在设计确定一个类的职责。

    Expert/Information Expert原则

    Assign the responsibility to the class that has the information needed to fulfill it.某项功能需要某些必要的信息,这些信息在哪个类中,就让这个类承担这项职责。

    比如,“消费者(Customer)”想知道他己经订购了哪些“商品(Item)”,这个功能可以由“购物车(ShoppingCart)”所实现:

     Creator原则

    这一原则要求设计者想清楚一件事:谁负责创建对象?

    +比如,请看以下类:

     这两个类有着密切的关联,现在的问题时,创建Page对象的功能到底由谁负责?是外部代码还是归属于Document?

    在《设计模式》一书中,列举了多种与对象创建相关的设计模式:Factory Method、Builder、Prototype、Singleton……
    Controller原则
    +考虑:谁负责显示数据?谁负责响应事件?谁负责处理数据?……

    经典设计模式:MVC
    在MVC设计模式中,由Controller(控制者)负责协调一切。

    不要在实现业务逻辑的代码中访问UI控件
    不要在UI代码中直接嵌入实现业务逻辑的代码。

     High Cohesion / Low Coupling

    Coupling(耦合性): 用于衡量对象之间依赖性的强弱
    + Cohesion(内聚性): 用于衡量某个类所提供的外部功能及内部代码之间关联的紧密程度
    在设计类时,追求“低耦合,高内聚”

    实现 “低耦合,高内聚”的有效方法:组合优先于继承

     这么做的理由:继承在父类与子类之间建立了很强的耦合性,对父类成员的修改,有可能会影响到它所有的子类。

    Indirection(间接性)原则

    对象之间相互关联,形成了复杂的交互网络

    为减少耦合,创建一个中间对象,将多对多关联拆散为一对多关联

     Pure Fabrization原则

    当某些功能不适合于归属到特定的业务逻辑相关
    的类时,创建一个新的类,这种类被称为“Pure Fabrication”,就是“生造出来的类”。

     这种类往往起“XXXService”这样的名字:
    public class SystemService{
      public void SaveSystemArgument(){}
      public vlid Exit();
      public void BackupSystem();
    }
    使用这一思路,有助于实现“低耦合,高内聚”

    Protected Variations 原则

    这一原则可译为“隔离变化”原则,
    + 简单地说:在设计类时,应该尽量让其少受外界的影响。
    “隔离变化”,是OOD的最终目的之一,有许多手段可以采用。
    Polymorphism(多态性)原则

    利用多态特性,把变化封装到子类中

    from 面向对象软件开发实践之基本技能训练第5单元_第五单元:山重水复疑无路,柳暗花明又一村第2章_5.2 万丈高台,起于垒土——类设计指南

  • 相关阅读:
    C语言数组和字符串函数
    C语言控制语句
    C语言输入输出函数
    C语言运算符
    C语言数据类型
    嵌入式开发基础知识
    VI编辑器的使用
    Linux文件系统和目录相关命令
    前段之必学(转载)
    26个高效工作的小技巧(转载)
  • 原文地址:https://www.cnblogs.com/Chary/p/14120811.html
Copyright © 2020-2023  润新知