Soft_Job 板


LINE

感谢大家热烈讨论,看到不少网友对 interface 的话题有兴趣, 另外开一篇,欢迎大家一起来讨论 : -- :



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 73.70.25.48 (美国)
: ※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1747295625.A.D41.html : 推 ikachann: 很多都这样 一开始能动最重要,真的有闲稳定下来後才是 05/15 22:20 : → ikachann: 重构的部分 05/15 22:20 专案开发节奏跟着商业需求走的,需要速度的时候先能动,但方向确立後,就真的需要 排时间做 refactor,清理成好维护的 code, 不然容易快速 launch,然後就快速坠落 refactor 的时候往往遇到一些 code 无法写 UT,这时候就是该导入 abstraction layer 的时候了。 : 推 ikachann: interface真的是说到点了,可能补习班教吧 一堆人都照着 05/15 22:22 : → ikachann: 一个service都做一个interface然後就只有自己实作 05/15 22:22 : → neo5277: interface 还是看语言跟框架用啊 05/15 22:42 : 推 stepnight: interface 跟 DDD 就是互相成就 05/15 23:5 : 推 shibin: 推,好奇问,那如果是为了 UT 而弄的 interface 呢? 05/16 14:3 : 推 attacksoil: 有时候写interface是怕把依赖方向搞烂 有建议吗 05/17 22:2 : 推 tsaigi: 但c#要mock的话不是一定要interface吗? 不测试的话的确 05/21 11:0 : → tsaigi: 是不用interface啦 聊到这个,除了 interface 还有 oop 继承的问题,早年学 OOP 都是狂用继承 但帮 parent class 改变行为,所有 children 就强迫一起自动获得这个改变, 如果有部分 children 不需要这个行为,事情就会变得非常棘手。 这就是为什麽会有 SOLID principle 的 O, open-close principle parent class 要设计成好开放扩充 (open) 但 parent class 本身不能随便改(close) 但这实务上不好做到,所以现在越来越常见提倡少用继承,尤其不要为了 reuse 某个 class 的功能而继承他。如果 class A 需要 reuse class B 的功能,可以在 class A 的 data member 建立一个 B 物件,然後呼叫他就好,不需要继承整个 B 的全部行为跟 介面,就可以有效避免这问题。 这个就是 compoisition over inheritence, 透过组合多个物件来 reuse 他们的功能,而不是继承他们的 classes 来取得这些功能。 当这样做的时候,每个物件就可以只负责一件事情 (single responsibility), 他们就会很单纯很好测试,然後组合这堆物件来合作完成一个大功能。 每个物件就可以有很简单的介面,这就是 SOLID 的 S, single responsibility 这样对 testability 也有帮助,但这样衍生的问题,就是物件会拆得很多很散, 把这些东西正确兜再一起很复杂,於是就需要写 factory 来建造这些物件, 或是借助 dependency injection 工具,使得 dependency 的管理变复杂。 物件之间要正确的互动也复杂,这个的经典案例就是 Windows 输入法框架 tsf 每个 interface 都只有一个功能,大多只有一个 method,结果就是写个输入法 API 文件一打开散成上百个 interfaces,没有足够的范例谁知道要从何看起? 这种时候就需要,提供一个简单易用的 wrapper,来把这堆复杂互动包起来, 提供简单 API 让常用场景方便使用,这就是 facade pattern。 解决一个问题,往往会制造另外一个问题,所以最後你逐渐就上了软体工程全餐 : 推 stepnight: interface 跟 DDD 就是互相成就 05/15 23:56 : 推 shibin: 推,好奇问,那如果是为了 UT 而弄的 interface 呢? 05/16 14:39 如果是为了让某些 dependency 在测试期间能替换,这是合理的做法。 最常见的场景之一,就是把 clock API 包进 abstract interface 里面,然後 code 需要时间就 call abstract interface,而不是直接呼叫 system call 这样在 UT 里面就可以替换成假的,inject 写好的固定时间进去,不然每次跑都不一样 另外一个例子就是你的程式呼叫某个系统 API,但 UT 的环境不允许呼叫,或是每次结果 是随机的,那我们就会用 interface 把它包起来,让 UT 时可以替换成不同实作 这确实是很合理而且常见的作法。但除了这些特殊状况,其他多半不是必要的 测试的时候还是 Prefer real object,使用真实物件如果适合,尽量用真的 使用 fake or stub 每次你改变行为,这些 fake/stub/mock 也要跟着连动,如果没有 一起改到,UT 就可能会坏掉或是得出错误的结果,使用过度会非常难维护 test double 使用的目的,主要是为了观察内部互动 (mock),提供假的固定数值 (stub) 或是避免外部依赖,例如避免连真实 server,或是加速,例如避免大量 disk I/O, 换成用 in-memory cache 的实作来加速 UT,除了这些状况,大多都可用 real object : 推 attacksoil: 有时候写interface是怕把依赖方向搞烂 有建议吗 05/17 22:28 我想你在讲的是 inversion of control or dependency inversion,也就是 SOLID 的 D 他要解决的问题是物件间高度耦合,所以让大家都依赖高阶抽象 interface,不直接 呼叫低阶的实作细节,低阶的实作要呼叫其他物件,也透过高阶介面,所以称"反转" 大家都只依赖介面而非特定实作,就达成低度耦合。 (注: Inversion of control (dependency injection) 和 dependency inversion 是不 同的东西,但实际上几乎会一起用,因为所有呼叫都是 abstract interface 的话, 那使用的 code 大多不会负责建造这些物件,所以几乎必然会从外面 inject 进来) 这要解决的问题是耦合,但耦合不等於不好。当两个物件就只有一种实作,然後他们就 真的只能搭配一起用无法抽换,那耦合其实也没有问题,没必要硬要解耦。 等你需要抽换不同实作的时候,再来抽 interface 其实常常也没关系。 会有问题的是 share library,事後补抽 interface 会变动 ABI,造成 binary 版本 不相容,需要重新编译。这种情境 interface 一开始订好不要动就会比较好。 然後 interface 越小越好,每个都只做最少的事情,就不会动一个东西就要到处改 这样对测试维护都比较好,也就是 SOLID 的 I, interface segregation : 推 tsaigi: 但c#要mock的话不是一定要interface吗? 不测试的话的确 05/21 11:00 : → tsaigi: 是不用interface啦 05/21 11:00 上面讨论过 UT 了 : 推 jennya: 热爱尝试当下流行的新工具新理论的工程师,常常也是团队主 05/22 01:58 : → jennya: 力,很难找到理由阻止他们尝试新事物 05/22 01:58 确实,就只能定期 review,定期 refactor 了。 对导入新事物保持开放心态,同时也对万一发现不合适随时 rollback 保持开放 勇於尝试,但也勇於承认错误,就会是个比较健康的文化。 讲半天架构,耦合,好玩的是,实务上最後决定系统架构的,往往是 Conway's law 你的组织架构长怎样,系统架构最後就会长成那样.... XDDDD 虽然现在 AI 当红,还是很高兴有人一起来讨论这些日薄西山的传统软体工程啦! (泪) -- Sent from PCMan on PCMan's PC --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 73.70.25.48 (美国)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1747904496.A.E67.html
1F:推 neo5277: C#来说虚拟类别出来然後可以有不同实作又可以再挂介面 05/22 18:30
2F:→ neo5277: 目前我是觉得我的场景还算满够用 05/22 18:31
3F:→ BoXeX: 有时候觉得OO搞那麽复杂 不如C语言 05/22 18:35
4F:→ BoXeX: 至少所见即所得 05/22 18:35
5F:→ BoXeX: 新人也能trace code 05/22 18:35
6F:推 shibin: 推 为了隔离第三方呼叫而弄的 interface 是可接受的 05/22 19:05
7F:→ shibin: 其余等不同实作开始浮现再来抽 05/22 19:06
8F:→ shibin: 是说 C 也是会使用 function pointer 解耦 05/22 19:07
9F:推 aleelyle: 後来发现OO写到後面太复杂了就往functional靠了 05/22 22:13
10F:推 brianwu1201: 推这篇 05/22 22:43
11F:推 fantasychese: 推推 不过SOLID的DIP跟IoC的DI应该是不同的东西? 05/22 22:48
12F:推 viper9709: 推分享~好专业 05/23 00:32
13F:推 WTS2accuracy: 在这个AI产UT的时代 更不该随意抽象 05/23 01:20
14F:→ WTS2accuracy: 发现有模组能共用再抽象出来就好了 05/23 01:20
15F:→ HZYSoft: 楼上说的没错,dependency inversion & injection 不同 05/23 01:24
16F:→ HZYSoft: 但两者实务上常并用,我写清楚好了,感谢纠正 05/23 01:25
※ 编辑: HZYSoft (104.135.204.212 美国), 05/23/2025 01:28:17
17F:→ HZYSoft: 搞清楚每个东西是解决什麽问题,就可以知道什麽时候要用 05/23 01:28
18F:→ HZYSoft: 但用了一个往往就制造另一个问题,最後就整个套餐集满了 05/23 01:29
19F:→ HZYSoft: 最後就分开看都是 best practice,但全部组起来却看不懂 05/23 01:31
20F:→ HZYSoft: 在大型专案有些复杂度有必要之恶,了解脉落有助於理解 05/23 01:31
21F:推 oopFoo: Accidental Complexity,不意外。 05/23 07:02
22F:推 oopFoo: Uncle Bob的SOLID都是一看合理但实际行不通的观念。当作 05/23 07:10
23F:→ oopFoo: 理想可以,但实务是折磨自己。 05/23 07:11
24F:推 v86861062: 推推 05/23 07:37
25F:推 APTON: 组合起来就看不懂,有机会是boundary切太大,有多个职责在 05/23 09:45
26F:→ APTON: 里面。工程师要直接面对程式码,视角上难免见树不见林 05/23 09:48
27F:→ APTON: 常常遇到SA/PM开需求都不加思索,画面上有甚麽就开甚麽需求 05/23 09:50
28F:→ APTON: 任何复杂的商业逻辑,都被他们开得好像只要CRUD就能完成 XD 05/23 09:50
29F:推 SirDoggo: 谢谢大大分享,我经验不是很多,主要是写独立游戏,现在 05/23 09:58
30F:→ SirDoggo: 用的很接近你的软体工程全餐,但是我使用起来感觉很条理 05/23 09:59
31F:→ SirDoggo: system+factory+facade组一个系统,写完了丢namespace 05/23 09:59
32F:→ SirDoggo: 对项目整体复杂度下降真的很有帮助。没用设计模式之前 05/23 10:00
33F:→ SirDoggo: 写出来的东西对心智负担很大 05/23 10:00
34F:→ SirDoggo: 用设计模式不算坏事吧? 05/23 10:01
35F:推 Segundus: 现在我几乎不写单元测试而是直接写整合测试把自己当使 05/23 11:36
36F:→ Segundus: 用者去测完整行为了,本地端直接docker compose启Post 05/23 11:36
37F:→ Segundus: gres Redis等实在很方便,早期docker还没那麽成熟时只 05/23 11:36
38F:→ Segundus: 能靠h2假装一下… 05/23 11:36
39F:→ HZYSoft: 说这麽多,其实我只是想提倡彻底理解各种practice的优缺 05/23 13:13
40F:→ HZYSoft: 比起把书上的东西当成教条奉行,更重要的是理解其内涵 05/23 13:14
41F:→ HZYSoft: 了解他们解决的问题和局限,使用上就会更弹性和得心应手 05/23 13:14
42F:→ HZYSoft: 就能吃软工自助餐,想要什麽就夹什麽,知道自己在做什麽 05/23 13:14
43F:→ Lordaeron: 不就是为了一定要用某个概念,有没有多伟大不知道。 05/23 20:51
44F:→ Lordaeron: 但这个概念产後的副作用另一个概念/方法来补救。 05/23 21:09
45F:推 wulouise: 到最後c++我还是用free function > class xd 05/23 23:28
46F:推 viper9709: 推彻底理解各种practice的优缺 05/24 00:49
47F:推 sugaryeh000: 有时候人在江湖 身不由己。 每次上面老板急着要东西 05/24 08:08
48F:→ sugaryeh000: 要你最快速赶出来。什麽clean code,design的东西全 05/24 08:08
49F:→ sugaryeh000: 丢在旁边,老板看到能跑就爽了 05/24 08:08
50F:推 sugaryeh000: 之後想要跟上面要时间去整理一下code, 好以後扩张, 05/24 08:10
51F:→ sugaryeh000: 上面就会一副不耐烦的表情说不用动 05/24 08:10
52F:→ sugaryeh000: 之後需要扩张时上面的又会嫌说当初怎麽写的那麽乱很 05/24 08:10
53F:→ sugaryeh000: 难扩张 05/24 08:10
54F:推 attacksoil: 了解了 推推 05/24 11:47
55F:推 shortoneal: 然後技术债就是大家比偷渡,用三寸不烂之舌把一些有隐 05/24 18:47
56F:→ shortoneal: 忧的部分想尽办法偷渡进下一个专案的排程 05/24 18:47
57F:推 prag222: 我个人看不顺眼的code重构也是包在自己的时间内 05/24 19:02
58F:→ prag222: 重构也不是整个重写,评估处理个大概能用 05/24 19:03
59F:→ prag222: 就好 05/24 19:04
60F:→ wulouise: project重构本来就应该包,只是很多人不接受 05/25 11:09
61F:→ superpandal: 就是过於复杂了 语言特性决定一切 只有麻烦的语言才 05/26 16:11
62F:→ superpandal: 讲究这些东西 然後还有些人当成宝 包含框架都是 我很 05/26 16:13
63F:→ superpandal: 久以前就看破这情况 简单并不等於实现复杂功能麻烦 05/26 16:14
64F:→ superpandal: 然後有些软体整策略整半天 最後有差吗? 真的快笑死 05/26 16:18
65F:→ superpandal: 软工要学的是本质而不是整天搞渐近式优化 05/26 16:20
66F:→ superpandal: 然後过於注重小细节 一个小写法就搞定的东西 05/26 16:24
67F:→ superpandal: 这个工作一两年应该就知道了 很可惜这一堆人乐此不疲 05/26 16:31
68F:→ superpandal: 资安也是 引入那麽多东西不怕这些东西有问题... 只有 05/26 16:35
69F:→ superpandal: 能掌控的才能够全方位覆盖全部 05/26 16:36
70F:→ superpandal: 说真的还不用ai 只要多点这种人 可惜现实不可能 为了 05/26 16:41
71F:→ superpandal: 利益是人的本性 05/26 16:41
72F:→ Firstshadow: 超熊猫大大...好厉害... 05/27 18:43
73F:→ superpandal: 还可以 05/27 22:56
74F:推 danielho1671: 推一个 05/28 05:19
75F:→ BoXeX: 像c++就用他的lib就好 没事别在那边定义class 05/28 11:18
76F:→ shooter555: 那就是C的写法 05/30 00:13







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灯, 水草

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

TOP