如果语言能够提供足够的表达性,是否可以不需要反射和 AOP 的概念?

查看 57|回复 1
作者:netabare   
在用 Kotlin 写 API 的时候突然想到的。
一般来说,像是 @before 和 @after 这种,用扩展函数就可以很方便的实现了。更复杂一点的概念,如果把 Kotlin 里面的 receiver 、scope 函数、 @this 之类的雕花技弄熟练然后配合良好的 OOP 设计感觉其实也可以实现差不多的效果吧。(草,不加代码块直接变成 at 人了(捂脸
我不熟悉 Scala ,不过如果本着「 Kotlin 能做到的 Scala 都能做到」的原则,那应该 Scala 也不是问题(雾
感觉这样写起来也许比起 AOP 的写法会啰嗦一点,但是代码层面上是很透明的,类型安全也可以得到保证,可读性和可维护性应该都是优于反射和 AOP 满天飞的 Java 代码吧。
并不是很喜欢 lombok 那套,感觉预处理的写法让代码变得不透明了。AOP 里面拿字符串写跳转更是让人头皮发麻。
感觉这也是不喜欢 Java 的一个很重要的因素……很多本来可以让语言来提供的功能都一概欠缺,然后实际工程里发现写不下去就不得不上一些非常 dirty hack 的写法,如果团队的水平不高直接变成灯谜大会。

aop, Scala, kotlin, 写法

h0099   
1. `@before` 和 `@after` 是指 JUnit 中的一个 attribute? https://stackoverflow.com/questions/20295578/difference-between-before-beforeclass-beforeeach-and-beforeall 结合阁下最近的回复 /t/910378#reply8 ,我暂且蒙古
> Kotlin 能做到的 Scala 都能做到
2. 经典类型系统的表达力决定了整个语言能做到什么
> lombok 那套,感觉预处理的写法让代码变得不透明了
3. 不用 lombok 难道您很喜欢手动复制粘贴满屏幕的 g/setter 方法和字段访问吗(而很明显 java 没有 c#的 auto prop 语法糖)?要是复制粘贴过程中扣错字段名了呢?
4. 如果阁下不喜欢静态语言中用于实现 ruby 那样的元编程的 source generator 轮子那我建议您也少碰 c/cpp 的宏和`php: hypertext preprocessor`和 css 预处理器( sass scss less ),因为他们的目的都是像 c#人滥用语法糖那样让代码变得不透明(然而语法糖远没有元编程自由,所以不透明的程度不如后者)
5. 与此同时截止 2023 年 1 月,奥利金德数理理论学家 dc 神的旗舰开源项目免 fq 上 p 站的 pixeval 第三方 c#客户端中仍在使用 source generator 来自动复制粘贴 i18n 文本: https://github.com/Pixeval/Pixeval/commit/ee13443205f8ed68dcc6dce87687f4cb341dde27 https://github.com/Pixeval/Pixeval/pull/278 在我看来这同样的`灯谜大会`
6. 但我在 https://github.com/n0099/TiebaMonitor/commit/8874e423b5345e66f81fc59e1ffe83f64a7d6d89 之后也希望能用 source generator 来自动生成我来回复制粘贴了十分钟的这些类型不安全(如果符号名不同也没有错误,也就是 3.中的`复制粘贴过程中扣错字段名`)的狗屎样板
7. 请问如何在这 https://github.com/n0099/TiebaMonitor/commit/4f098c8ef7f2fdd089a43ca99746a666c4bd10fc 之中避免使用 attribute 同时又不需要在每次使用 jsonserializer.serialize 时手动判断参数类型并决定是否传入这个 converter? https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to
8. 阁下不应该只将 attribute 视作运行时反射的唯一用途,尽管这是其常见用途,对于刚从动态语言转静态语言的人(如我)而言滥用反射主要是为了实现动态语言中常用的表达(所以我以前说动态语言天天反射)
9. 而在 https://github.com/n0099/TiebaMonitor/commit/34f9c32dd346a22878ea8dcf2ac82fe46169c8bc 中我将类型确定的反射都改成了朴素的所谓`member selector`(也就是通过函数参数将 project 出某个类成员的任务委托给 caller 而不是硬编码在内部)
10. 但在 https://github.com/n0099/TiebaMonitor/blob/c414ca3429ceb1cd4a7607c10fb79cb608b7cd2d/crawler/src/Tieba/Crawl/Saver/CommonInSavers.cs#L79 中我并没有将这的反射给彻底削除,因为 https://github.com/n0099/TiebaMonitor/blob/c414ca3429ceb1cd4a7607c10fb79cb608b7cd2d/crawler/src/Tieba/Crawl/Saver/StaticCommonInSavers.cs#L5 的目的只是把类 https://github.com/n0099/TiebaMonitor/blob/v2/crawler/src/Db/Post/ThreadPost.cs 和类 https://github.com/n0099/TiebaMonitor/blob/v2/crawler/src/Db/Revision/ThreadRevision.cs 之间名字相同的字段给合并赋值一遍(也就是 js 人最爱的`Object.assign({}, {})`),我当然可以用同样的手法来把这个反射 setvalue 给换成调用 revivison 类中的某种 merge 方法并在其中逐一复制所有已知的硬编码的类实例中同名的 prop 值,就像是阁下最痛恨的对`两个结构相似的类`却要写高度相似的重复代码来处理不同的类型: https://github.com/n0099/TiebaMonitor/blob/c414ca3429ceb1cd4a7607c10fb79cb608b7cd2d/crawler/src/Tieba/Crawl/Parser/ThreadParser.cs#L17 ,也就是我此前于 https://sora.ink/archives/1574?replytocom=800#respond 中所说的:
> @dylech30th ts 那种 ducktype 也算传统 oo 的严格 subtype?
> 就像四叶 CS 硕士 PLT 中级高手 irol 阁下此前锐评 java 魔怔人为了让两个结构十分相似的类能够兼容而写出一个逐类 prop 去复制粘贴的 converter (常见于 bean 中,而我也被迫在 c#中写出了这样的恶俗玩意: https://github.com/n0099/TiebaMonitor/blob/e84a230fa0eb1c1095f6b6aa74b34a29f1f6a69d/crawler/src/Tieba/Crawl/Parser/ThreadParser.cs#L45 )的刷代码函数和运行时开销的罪恶行径,而在 ducktyping 中只要结构相似那他们就是互相兼容同一个类型(如果不考虑逆变协变不变)
11. 然而我也只多举了一个反射的常见用例,事实上由于 8.中的`动态语言天天反射`使得您总能找到新的奇妙深刻反射(远比您所见的基于字符串的 DI/IoCcontainer/AOP 谔谔)
12. 如果阁下想完全不用反射建议去写 AOT 编译的 c/cpp/rust ,并且也别使用 RAII 在编译时给类结构附赠的元数据
您需要登录后才可以回帖 登录 | 立即注册

返回顶部