欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

软件构造 课堂笔记4

程序员文章站 2022-03-10 14:16:19
...

这篇文章会较多的搬运PPT上面内容,因为我认为确实比较重要,也会在里面加上一些我个人的理解

类接口设计建议

一:好的抽象

类的接口应能提供一组 明显相关 的子程序

类的接口应该尽量展现一致的抽象层次

class EmployeeCensus: public ListContainer {
  public:
    void AddEmployee(Employee employee);
    void RemoveEmployee(Employee employee);

    Employee NexItemInList();
    Employee FirstItem();
    Employee LastItem();
  private:
};

在这里面,前两个方法是EmployeeCensus类的ADT功能,而后三个是ListContainer接口里的方法。也许可能有人认为前面两个接口也都是ListContainer里面的,但是从命名来看,确实前两个方法更贴近于Employee的层次。也就是这里表现出了两种抽象,最主要的原因是EmployeeCensus这个类继承了ListContainer类,但是这里不符合”is a”原则,因此不应该使用继承,而应该使用组合。

class EmployeeCensus {
public:
  void AddEmployee(Employee employee);
  void RemoveEmployee(Employee employee);
  Employee NexItemInList();
  Employee FirstItem();
  Employee LastItem();
 private:
  ListContainer m_EmployeeList;
};

这种写法与上一种写法相比,要稍微好一些。上一种对于各个方法的实现需要自己直接管理数据,也要处理逻辑。下一种写法的话,对于数据的管理交给了m_EmployeeList,自己来处理逻辑。

  • 谨防在修改时破坏接口抽象

这是因为,在很多赶工期的时候,人们会不自觉地将需要的接口随便先找个地方放进去,而不考虑抽象的事情。

二:好的封装

不要暴露自身数据和实现细节

  • 封装比抽象更严格,二者相辅相成

    • 抽象:提供可以忽略实现细节的模型来管理复杂度
    • 封装:阻止你看到细节
  • 尽可能限制类和成员的可访问性

    • 采用最严格且可行的访问级别

    即所有类成员的访问限定符都是private,然后根据访问器来访问。

  • 不要公开暴露成员数据

错误的做法:

public:
    float x;
    float y;
    float z;

正确的做法:

public:
    float getX();
    float getY();
    float getZ();
    void setX(float x);
    void setY(float y);
    void setZ(float z);

我们这么做,是可以不暴露x,y,z的属性的,因为假设我们将x设置为string类型,这么做可能是为了前端显示起来比较方便,那么这时候get和set方法就隐藏了x的变量类型。

  • 避免把私有的实现细节放到类的接口中

由于我们平时都是写Java,所以不管怎么样都是可以看到实现细节的,所以这里不列出PPT上的内容了,其实也是《代码大全》上的内容。

  • 不要对类的使用者做任何假设

    很多东西不应该写在注释里,而应该写在代码里。比如我们不希望使用者将x初始化为0,我们可以用assert而不是使用注释。

  • 避免使用友元类

  • 不要因为一个子程序里仅使用公用子程序,就把它归入公开接口

  • 让阅读代码比编写代码更方便

  • 要格外警惕从语义上破坏封装性

如果必须要看到底层实现才能理解发生的事情,那还算不上抽象。——P.J Plauger

表现为:调用方代码不是依赖于类的公开接口,而是依赖于类的私用实现。

解决方案是针对接口编程。

不知道如何使用类的接口时,联系类的作者,作者应该修改类的接口文档。

二者相关,或者两者都有,或者两者皆失

设计实现

包含

  • 面向对象编程中的主力技术
  • 警惕超过7个数据成员的类

继承

  • 使用时应该谨慎
  • 遵循里氏替换原则
    • 基类中定义的所有子程序,在它的任何一个派生类中含义应该是相同的。典型的例子是借款、存款Account里面的InterestRate,一个是借钱,一个是还钱,需要程序员记得其中的差异才行,所以不能继承同一个类。
  • 在多处使用switch-case时,很可能应该使用多态

Demeter原则

假设有一个类O,O里面有一个方法M

public class O{
  private int x;
  public void A() {

  }
  public void M(O1 o1) {
    O2 o2 = new O2();
  }
}

这时候M只可以调用一下几种对象的方法:

  1. O里面的方法
  2. O的直接组件对象 // 不应该出现多层.调用的情况
  3. M的参数
  4. 在M中创建的对象

构造函数

  • 尽可能在所有构造函数中初始化所有数据成员

先给一个全部参数的构造函数,然后在别的构造函数里面调用全部参数的构造函数

相关标签: 软件 设计