🧩 第八章 UML:查看无形软件的工具
📄 一句话概括

同一批消息两种排法:实测4 条消息、3 条连线(其中 1 条是自消息)——时序图看先后,通信图看耦合。

📝 本节和前面几节的关系

8.5 把结构画完了,这一节画动起来的那一半。两个图画的是同一批消息,只是排法不同。

一、时序图:纵轴是时间

每个参与者头顶一个框,生命线往下垂,消息画成箭头,从上到下就是时间顺序。 箭头一画,谁在等谁就露出来了——被调用的那条线要等返回才能往下走。 编号可以省:位置本身就是顺序。

二、通信图:横轴是连接

对象画成框,线表示它们之间有通路,消息标在线的旁边并带编号。 看的不是先后,是【谁跟谁有直接联系】——线越多,耦合越重。 自消息画成指向自己的圈(一个对象内部的调用)。

三、实测:4 条消息、3 条连线

一次借书:Reader → Loan(borrow)、Loan → Loan(make,自消息)、Loan → Book(lend、ok)。 消息 4 条,连线 3 条——同一条线可以走多次,这就是两个数的差。 自消息也占一条线(一个从自己指向自己的圈),容易被漏掉。

四、两者可以互推

因为画的是同一批消息,UML 里说它们可以互相推导(信息等价,只是排法不同)。 做法上的分工:调试时用时序图(追顺序),评审时用通信图(数耦合)。 别两张都画——除了浪费,还容易画得不一致。

五、动手 Demo:使用时序图和通信图表示动作

在方法里记一笔调用,跑一次借书。 先按时间排成时序图,再按【谁连谁】压成通信图。

LOG = []

class Book:
    def lend(self):
        LOG.append(("Loan", "Book", "lend"))
        return True

class Loan:
    def make(self):
        LOG.append(("Loan", "Loan", "make"))      # 自消息
        ok = Book().lend()
        LOG.append(("Loan", "Book", "ok"))
        return ok

class Reader:
    def borrow(self):
        LOG.append(("Reader", "Loan", "borrow"))
        return Loan().make()

Reader().borrow()
pairs = len(set((a, b) for a, b, m in LOG))
print(len(LOG), pairs)   # 4 3

实跑输出:

--------------------------------------------------------------------
使用时序图和通信图表示动作
--------------------------------------------------------------------

  同一个借书动作,**记录一次就够,两种图画法**:先按时间排,再按连线排。

  时序图(按发生顺序编号):

  序号     从         到       消息
  ------------------------------------
  1        Reader     Loan     borrow
  2        Loan       Loan     make
  3        Loan       Book     lend
  4        Loan       Book     ok

  通信图(按【谁连谁】重排,线旁标序号):

  连线              标号
  -----------------------
  Reader → Loan     1
  Loan → Loan       2
  Loan → Book       3/4

      消息条数                    4 条
      连线数                      3 条

  **第 2 条是自消息**(Loan 自己走了一步),**画成从自己指向自己的圈。**
  **消息比连线多**(4 对 3)——同一条线可以走多次,**这就是两种图的分工。**
  **时序图看【先后】**:找得到谁在等谁。**通信图看【结构】**:一眼看出耦合圈。
  **两张图画的是同一批消息**,所以 UML 里说它们可以互相推导。

实测:4 条消息、3 条连线,其中 1 条是自消息(Loan 自己指向自己)。 消息比连线多——同一条线可以走多次,这就是两个数的差。 时序图看先后,通信图看耦合;两张画的是同一批消息,可以互推。

30 秒实验

  1. 给你的一个方法加上调用日志,跑一遍,把日志排成时序图。
  2. 数一数你的通信图上有几条线,线最多的那个对象就是耦合中心。

常见误区

  1. 以为时序图和通信图是两种信息。同一批消息,两种排法。
  2. 漏掉自消息。对象调自己的方法也是一条消息。
自测三问(点开对答案) 1. 两张图最大的区别? —— 时序图按时间排,看先后与等待;通信图按连接排,看耦合与通路。 2. 实测为什么消息比连线多? —— 同一条连线可以走多次;实测 4 条消息落在 3 条连线上。 3. 自消息怎么画? —— 画成从对象指向自己的圈,也表示在通信图的连线上。

相关笔记