- 主题:面向对象的设计模式在rust里怎么搞?
这不仅是一种workaround,更是一种对三十年前流行的继承的全面反思。正是因为对继承的副作用认识越来越清楚,所以组合优于继承越来越深入人心,所以rust go等等较新的语言都主动放弃了继承,迫使用户使用组合的方式来复用逻辑。
组合优于继承,是和“高内聚低耦合”大致处于一个级别的“设计思想”。“设计思想”落地细化为“设计原则”,比如SOLID原则等等,然后“设计原则”再细化为具体的“设计模式”。这里面,“设计思想”是处于源头的地位。
【 在 RunningOn 的大作中提到: 】
: 这个听起来和“trait的函数里第一个参数是struct的引用”感觉上差不多,
: 也是一种workaround
--
FROM 123.120.189.*
我一直说,oo 就是工程师设计出来的东西。把一堆数据类型放在一起,组合成 struct,然后很自然的就想到,完全可以把一堆函数按照同样的方式放到一起。从复用数据类型的结构,再到复用同样接口的函数。
但其实,oo 复用代码的场景过于理想化,以至于在现实中,都是硬往上凑而且还带来了非常多的问题。
比如前端的控件,看起来似乎是一个很理想的 oo 的场景。实际中呢,react 最开始的确也是这么设计的,但跟它自身核心的 fp 格格不入,最后换成 hooks 了。vue 在做3的过程当中,也想过用 typescript + decorator + oo 的形式来实现,但其实2里的 mixin 的坑就已经很深了,所以最后抄 react 的作业改成了 composition api。
这个世纪的新语言里,除了像 kotlin、swift 这种不得不兼容老语言而引入了 oo 的概念外,几乎都更多从 fp 里学设计,而摒弃了 oo 的设计。各种 immutable 变量,接口设计也都是返回新的数据结构,而避免修改原始的数据。从测试角度看,immutable + fp 的设计写出来的东西更简单,更容易测试,更好复用。oo 设计的东西,调用 object method 的结果完全是不可预期的。本来设计的是一个 read-only 的 method,但完全没有任何机制保证哪个子类不会手欠把 field 给改掉。你给基类写好的测试,放到子类就跑不过了,而且子类也是实在的业务需求,不改数据完成不了功能
还有经典的 banana-monkey-jungle 问题,本来只想要一小块非常单独的功能,最后发现必须得上整个 framework。原本你只想要一根香蕉,但发现最后需要整个森林。
回到 oo 解决的问题,object method 其实就只有两个信息,一个是数据的结构,另外一个是函数的接口。说白了就是设计一个接口,接受两个参数,数据和 callback 函数的指针而已。放到 rust 里,这个数据最好 mutable,因为保不齐 callback 就想动动手脚。
【 在 RunningOn 的大作中提到: 】
: 其实并没有,functional 只是大家不陌生了而已,远不到趋势的程度。
: 大多数业务并不适合 functional。
: oop大家不强调了,但流行的语言几乎都支持class而且广泛大量地使用,所以oop已经不是什么有趣好玩的概念了。
: ...................
--
FROM 222.153.175.*
struct放参数可以搞。几天讨论下来只有这个方法靠谱了。
不过那个 banana-monkey-jungle 倒不是oop的问题,是framework的问题,大多数项目的设计中都没有考虑在不引入整个framework的情况下引入一个小部件。
【 在 eGust 的大作中提到: 】
: 我一直说,oo 就是工程师设计出来的东西。把一堆数据类型放在一起,组合成 struct,然后很自然的就想到,完全可以把一堆函数按照同样的方式放到一起。从复用数据类型的结构,再到复用同样接口的函数。
: 但其实,oo 复用代码的场景过于理想化,以至于在现实中,都是硬往上凑而且还带来了非常多的问题。
: 比如前端的控件,看起来似乎是一个很理想的 oo 的场景。实际中呢,react 最开始的确也是这么设计的,但跟它自身核心的 fp 格格不入,最后换成 hooks 了。vue 在做3的过程当中,也想过用 typescript + decorator + oo 的形式来实现,但其实2里的 mixin 的坑就已经很深了,所以
: ...................
--
FROM 58.33.81.*
oo 出来的东西,使用方法一般要先创建一个 object,然后再调用 method。但怎么初始化这个 object 却成了一个非常复杂的问题,往往是需要符合 framework 的规范。为了在某个 framework 里面,通过反射的形式来执行这个逻辑,就成了抓住香蕉的猴子。
香蕉往往非常简单,如果设计成一个纯函数的话,完全可以设计成相对独立的库。所以很多功能复杂的包,有依赖于许多功能相对独立的小包。这就不存在为了一根香蕉而搞进来整个森林这种问题了。
【 在 RunningOn 的大作中提到: 】
: struct放参数可以搞。几天讨论下来只有这个方法靠谱了。
: 不过那个 banana-monkey-jungle 倒不是oop的问题,是framework的问题,大多数项目的设计中都没有考虑在不引入整个framework的情况下引入一个小部件。
: 以
: ...................
--
FROM 222.153.175.*