OOAD 板


LINE

※ 引述《hsnucsc (hsnugo)》之铭言: : 我找了很多网站 : 都将解释SRP成: 每一个物件, 应该要只有单一的responsibility : 而将responsibility解释成: 只有一个理由去改变物件 : 但是我还是觉得responsibility这个词很模糊 : (如果直接翻译成中文, "责任", 仍然很难知道这个责任的大小) 这个责任是一个够大的责任。 因为你不是从标准路线走到这一步, 所以大概跟你说明一下好了。 传统 use-case driven 的开发, 会先从零散的问题里整理出比较明确的 problem statements, 接着从那里面区分出 functional/non-functional requirements 来。 use-case model 主要在模塑的是 functional requirements, 经过对前面得到的文字资料做名词和动词的分析後, 可以找到 actors 和 use cases。 在 use cases 被找到之後, 你的「需求分析工具」会要求你撰写 use case specifications, 格式大概是: Use Case Specification: <这里填 use case 的名字> 1. Use Case Name 1.1 Brief Description 2. Flow of Events 2.1 Basic Flow 2.2 Alternative Flows 3. Special Requirements ... 在 2. 的部分要求你描述的, 就是整个 use case 从开始到结束要做的事情。 所谓的 basic flow 是很顺利的一直线走到底的流程, 没有所谓的特例状况和分支, 特例状况和分支都被描述在 alternative flows 上。 一般来说使用 UML 开发的话, 这部份也时常搭配 activity diagrams 来进行。 前言就讲到这里, 有一点长; 主要目的只有告诉你什麽叫 flow of events, 还有它是怎麽来的。 flow of events 是所谓「需求规格」的一部份。 对 flow of events 做 textual analysis, 你将会得到一群名词和动词, 一个有效的名词一般来说就会成为一个 class。 我想到这边你还是很熟悉, 但是这背後还有其它的意义。 你在描述 flow of events 时, 也同时在描述每个名词对某些行为的责任。 SRP 并不是无限上纲到脱离 requirements 让你停不下来, 你的一切 analysis 和 design 都必须基於 requirements 进行。 就像做学术研究, 一个论文题目总是不会解决所有问题, 而是会设定一些限制条件後再对有限的问题进行拆解; 实务面的软体设计更是如此。 责任的大小, 完全视你的需求而定, 不然你所有的东西恐怕都要定义到原子或夸克去了。 进行 SRP 分析或填写 CRC 卡的时候, 请记得看着 flow of events 做, 如果你没有这种东西, 就看看 flow charts 或 activity diagrams。 这些东西里都没有描述到的更细部责任, 那就不需要考虑, 你不需要把责任 delegate 给一个无效甚至不存在的名词。 在设计阶段, SRP 常跟 OCP 搭配, 而 OCP 常跟 strategy pattern 搭配。 strategy pattern 负责将各种行为做分类, 因此改变行为常常是「新增」 concrete strategy, 以及对 factory method (或 creation method) 的修改。 除非你需要新增的是 strategy 的 family (即 abstract strategy 或 interface), 才有可能需要去动到 context class。 因为这三种东西通常都有连动关系, 所以当你的「行为」本身根据需求并不会有「一个家族」的行为集时, 你是不需要再另外把责任再往外 delegate 给其它 classes。 以上两段应该大概可以告诉你「什麽时候该停下来」了, 简单来说, 一切都环绕在需求规格上; 其实我也很想直接推一句「看需求决定」来回你就好了, 但是你可能会觉得很抽象, 然後将来可能又会有其他人跑来问一样的问题。 : 以书上的例子而言 : Automobile 车子有很多功能 : start() : stop() : changeTiles(Tile [*]) : drive() : wash() : checkOil() : getOil() : 应该要被分解成 : Automobile : start() : stop() : getOil() : Driver : drive(Automobile) : Carwash : wash() : Mechanic : changeTires(Automobile, Tire[*]) : checkOil(Automible) : 有一些method移交到其他物件处理 : 但是.... : 1. 假设Automible有 : body, front-left_tire, front_right_tire, back-left-tire, back_right_tire : changeTires()为了要change车子的轮胎 : 势必要改变其四个轮胎 : 我猜写法是 : changeTires(Automobile au, Tire[*] tires) : au.set_front_left_tire(tires[0]); : au.set_front_right_tire(tires[1]); : .... : 这样为什麽不直接把changeTires这件事直接委派给Automible去做 : 同样的道理, 如果其他drive, wash等method, 需要get or set : 来知道Automible的细节, 那何不直接把这样工作交给Automible做 你把这世界简单化了。 一方面也是因为你看的书不是从头到尾 run 一个 project 给你看, 确实很容易让你因为对「需求」的资讯不足, 使得你对例子的理解与作者假设的情境不同。 一个物件被委派责任的原因, 主要是因为它「了解如何完成这个任务」, 也就是说包括这项任务的细节在内, 并不是你想的单纯 set/get 就好了, Automible 本身可能提供非常多 method 让你 set/get 细部的参数 但是只有 Mechanic 知道要如何正确的 set 它们, 这中间可能还会有一些操作机械的流程, 可能还会有一些基本的安全检测等等; 当然这一些要看你的 flow of events 有没有描述到。 : 2. 这样好像又回到procedural programming : data跟function是分开的, data当作function的input後, 由function来处理data : 在这里, Automobile是要处理的data : 而Driver, Carwash, Mechanic则有点像是处理data的function : 再举个例子: : 今天我们需要一个铁路线路网, 上面有多条线路, 多个车站 : 且在给予起点和终点後, 可以找出一个起点到终点的path, 并印出来 : 如果是我来设计的话 : class会有Subway, Line, Station, Route : Subway.find(Sation s, Sation t)後, return 一个Route : Route.print()印出path : 但是书上的方法, : class会有Subway, Connection, Station, Printer : (Line, Connection的差异先不讨论) : 他用Printer来印一个List route(有Connection跟Station) : 於是, Printer在print的method里 : 必须要不停的用route.getXX(), station.getXX() ...... : 这感觉很像是Printer在处理一个Data : 为什麽不直接把print的工作给statoin, 给route呢 Printer 可以做相当简化的工作, 比方说它就是只提供 print(String), 也就是字串的列印; station 和 route 并不需要知道如何列印一个字串。 Route.print() 可能要做比你想像中还要多的事情, 比方说把内部的资料表示法转换成有意义、易读易懂且可列印的字串, 才把列印「字串」的责任交给 Printer。 : java Exception 不是也有 printStackTrace, 并没有说特别把print的工作交给别人啊? : 上面是增加新的物件来处理 : 我也有找到另一个方法, 是增加interface : http://www.codingefficiency.com/2009/07/18/ : solid-s-single-responsibility-principle/ : http://0rz.tw/QP6hs (缩过的网址) : 不过仍然让人很难分辨responsibility : 说严格一点, 好像每个method, 都有理由改变 : 但是又不可能把每个method都新增一个物件去处理这项功能 : 希望有人可以帮忙解答 : 谢谢 -- Ling-hua Tseng ([email protected]) Department of Computer Science, National Tsing-Hua University Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design Researching: Software pipelining for VLIW architectures Homepage: http://www.tinlans.org --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.160.104.199 ※ 编辑: tinlans 来自: 118.160.104.199 (01/21 15:40)
1F:推 lovemage :谢谢说明,刚好这个案子也在思考这些,有帮助^^ 01/21 18:53
2F:推 KanoLoa :Thanks 01/23 00:28







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BuyTogether站内搜寻

TOP