别的团队交接过来一个十几万行的 Python 项目,要重构成 Java ,我真的吐了,一点文档也没有。
Python 里面大量的访问各种 RPC 接口,关键是特别喜欢自己转换 rpc 返回的结构,还非要用字典去自定义结构!
现在好了,到处都是字典 + 字符串取值,这个字符串 key 还是尼玛自己定义的,和 idl 都对不上,得自己去代码里面到处翻找,看看到底是哪个接口返回的。
最离谱的是命名还会骗人,弱类型就算了,好歹命名漂亮点吧。"xxx_list"
是个字符串我真的服了,甚至就连 "user"
也能是个字符串……
现在国内的现状就是领导疯狂催,程序员疲于奔命,谁天天给你写文档,代码迭代几次连自己都不认得了,还搞弱类型,万一熟悉项目的人走了后面的人根本没办法看,都都读不懂。再加上英语水平有限,命名真的是一塌糊涂,更加重了理解问题。
1 hhacker 2024-07-13 11:07:01 +08:00 不讨厌的只是屎山,不是弱类型 |
![]() | 2 estk 2024-07-13 11:08:29 +08:00 via iPhone ![]() 中国人老板:My grandma run faster than your code! |
![]() | 3 qcbf111 2024-07-13 11:08:46 +08:00 ts 火不是没有道理得,当初我们用 lua 也强制必须要规范书写 type annotation. |
4 Makabaka01 OP ![]() @hhacker 国内环境下,弱类型 == 不可阅读的屎山……强类型还属于可阅读的屎山,能接受一点 |
5 lithiumii 2024-07-13 11:10:47 +08:00 via Android ![]() 可能别的团队一个月整出了能挣钱的活,现在用户多到需要重构了。但凡一开始就用 java 写,现在还没上线呢(我瞎说的 |
6 Makabaka01 OP @lithiumii 哎,现在大厂确实都这样,代码随便搞,能跑就行,吹一波后面反正晋升走人了,维护代码又不是自己,然后后面来的人继续这么想,继续屎山上拉屎。 |
![]() | 7 walkeronway 2024-07-13 11:17:29 +08:00 我写 python 就特喜欢写类型注解,看着特舒服,写了之后 pycharm 的语法提示也好用 |
![]() | 8 75S3CWXNN0VQ84mg 2024-07-13 11:18:18 +08:00 ![]() 上线收益拿到手拍拍屁股挖新的坑,留下的老坑里面都是屎,接盘的有福了 |
![]() | 9 sagaxu 2024-07-13 11:19:22 +08:00 ![]() php 代码里面经常有 $item['aa']['bb']['cc']['dd'] 甚至 5 级以上的数组,运行时产生一大堆 undefined index xxx ,但产品行为却符合预期,就算是原作者维护,可能过几个月就搞不清有哪些字段了 |
10 kenvix 2024-07-13 11:21:12 +08:00 ![]() 你要不先区分一下弱类型和动态类型... |
11 ciderzero 2024-07-13 11:21:36 +08:00 ![]() Python 是强类型动态语言吧,虽然我觉得写着也不舒服。 |
![]() | 12 akira 2024-07-13 11:22:01 +08:00 ![]() 都一样, 赶工期出来的东西,用啥写 都是屎山。。。 |
13 Pzqqt 2024-07-13 11:22:40 +08:00 以下内容摘自《流畅的 Python 》第 11 章“接口:从协议到抽象基类”的延伸阅读 Python 是弱类型语言吗 由于缺少统一的术语,讨论语言类型方面的话题时有时会让人不明其意。有些人(例如扩展阅读中提到的 Bill Venners 对 Guido 的访谈)说 Python 是弱类型语言,把 Python 与 Javascript 和 PHP 归为一类。讨论类型时,最好考虑两条不同的坐标线。 强类型和弱类型 如果一门语言很少隐式转换类型,说明它是强类型语言;如果经常这么做,说明它是弱类型语言。Java 、C++ 和 Python 是强类型语言。PHP 、Javascript 和 Perl 是弱类型语言。 静态类型和动态类型 在编译时检查类型的语言是静态类型语言,在运行时检查类型的语言是动态类型语言。静态类型需要声明类型(有些现代语言使用类型推导避免部分类型声明)。Fortran 和 Lisp 是最早的两门语言,现在仍在使用,它们分别是静态类型语言和动态类型语言。 强类型能及早发现缺陷。 下面几例体现了弱类型的不足: ```Javascript // 这些是 Javascript 代码(在 Node.js v0.10.33 中做了测试) '' == '0' // false 0 == '' // true 0 == '0' // true '' < 0 // false '' < '0' // true ``` 因为 Python 不会自动在字符串和数字之间强制转换,所以在 Python3 中,上述 == 表达式的结果都是 False (保留了 == 的意思),而< 比较会抛出 TypeError 。静态类型使得一些工具(编译器和 IDE )便于分析代码、找出错误和提供其他服务(优化、重构,等等)。动态类型便于代码重用,代码行数更少,而且能让接口自然成为协议而不提早实行。 综上,Python 是动态强类型语言。“PEP 484TypeHints”( https://www.python.org/dev/peps/pep-0484/)无法改变这一点,但是 API 作者能够添加可选的类型注解,执行某种静态类型检查。 |
![]() | 14 cmdOptionKana 2024-07-13 11:33:29 +08:00 ![]() 古语有云:动态一时爽,重构火葬场。 |
15 unbridle 2024-07-13 11:34:10 +08:00 via iPhone ![]() 只是不方便 javaboy 转 java 而已 |
16 vitality 2024-07-13 11:37:52 +08:00 是的,没有 Type Annotation 的代码不是好代码,阅读、维护起来真的是灾难。 |
17 Makabaka01 OP @Pzqqt “很少隐式转换”这个概念很模糊啊,比如 JS 现在也不会有人写 == 了,都是 ===,然后 Python 里面也会经常在 if 里面直接放一个字典或者数组,`if dict` `if arr` 这样,这不算隐式转换吗 |
![]() | 18 AV1 2024-07-13 11:46:47 +08:00 via Android ![]() 我写 Python 都会写 type hints ,写 JS 都会写 jsdoc 。 有的人嫌弃写 type 浪费时间,我觉得不然。写 type 能让编辑器自动提示对象里的成员,反而更能节约调试时间。 以前写 JS 的时候,最烦的事情,比如对象成员的字段名拼写错误,或者调用 async 函数忘记 await ,写一段代码,还要花同等的时间来调试。后来坚持写 TS/JSDOC ,代码跑起来经常都是一次通过,效率高多了。 |
19 Makabaka01 OP @akira 万恶之源还是魔法字符串 |
![]() | 20 yolee599 2024-07-13 11:49:12 +08:00 via Android ![]() 所以我很反感用 var ,auto 来定义变量,该 string 就 string ,该 int 就 int ,别搞一个通用类型 |
![]() | 21 awalkingman 2024-07-13 11:49:36 +08:00 |
22 hez2010 2024-07-13 11:56:10 +08:00 via Android @yolee599 var 也不是通用类型。var 的类型是静态推导的,跟你直接写 int 和 string 没区别,编译的时候会被编译器自动替换成实际类型。 |
23 davehandong 2024-07-13 12:01:49 +08:00 Java 不是也支持了 var 声明变量么,C/C++里现在也有 auto ,我是一直挺反感这个的. 一方面像 js 这种往 typescript 这方向走,另一方面本来是强类型的又非要引入弱类型的风格。 |
![]() | 25 AV1 2024-07-13 12:04:24 +08:00 via Android @yolee599 如果你说的 Java 的 var 和 C++的 auto ,它们都不是“通用类型”。 那只代表类型自动推导,开启 inlay hints ,或者把鼠标 hover 上去,就能看到真实的类型。 |
26 Biggoldfish 2024-07-13 12:07:35 +08:00 加上 type annotation 并且 enable type checker 不就完了 |
27 deplives 2024-07-13 12:10:13 +08:00 via iPhone 连动态类型和弱类型都分不清? python 早就有了 hint 建议了解一下 [Python 里面也会经常在 if 里面直接放一个字典或者数组,`if dict` `if arr` 这样,这不算隐式转换吗] 你真的 了解一下啥叫 magic method ? |
![]() | 28 wangritian 2024-07-13 12:11:45 +08:00 语言的约束作用始终有限,主要看开发人员水平,写 java 用 Map 一把梭不也受不了 |
![]() | 29 mikewang 2024-07-13 12:19:37 +08:00 |
![]() | 30 villivateur 2024-07-13 12:28:43 +08:00 有一说一,Python 是强类型语言,建议你自己点个“下沉”,不然太尴尬了,会被人笑的 |
![]() | 31 yolee599 2024-07-13 12:40:32 +08:00 via Android @DOLLOR #25 但是这个功能需要编辑器支持才行,在网页上看到一段全是 var ,auto 的代码就要在脑子里推断很久,当然也可以拷贝下来粘贴到编辑器里,但麻烦就是了 |
32 vituralfuture 2024-07-13 13:04:59 +08:00 via Android python 是强类型,动态类型的语言 |
![]() | 33 jlkm2010 2024-07-13 13:08:43 +08:00 动态一时爽,重构火葬场 |
![]() | 34 yb2313 2024-07-13 13:36:32 +08:00 喜欢我**args 吗, 然后再通过各种不可名状的 magic 方法获取到一个值 |
![]() | 35 kmyzzy 2024-07-13 13:55:33 +08:00 你说的是静态类型 vs 动态类型,不是强类型 vs 弱类型。 |
36 CodeCodeStudy 2024-07-13 14:08:30 +08:00 js 的坑更多,就算用 ts 也没办法完全规避,比如: 一个 number ,有可能是 NaN ,需要用 Number.isNaN 来判断 一个 Date 对象,比如变量名叫 d ,有可能是无效的,通过 d.toString() === 'Invalid Date' 或者 Number.isNaN(d.getTime()) 这两个坑无法使用 ts 检测出来,因为 NaN 的数据类型也是一个 number ,Invalid Date 的数据类型也是 Date |
![]() | 37 whenov 2024-07-13 14:19:48 +08:00 via Android 你转到 Java 时也转成字典不就好了 |
38 yanqiyu 2024-07-13 14:27:14 +08:00 道理我都懂,但是 python 是典型的强类型语言。C++反倒是弱类型语言。你指的是动态类型和静态类型的区别 |
![]() | 39 duluosheng 2024-07-13 14:33:04 +08:00 js 就不如 ts 好阅读,强类型真是更适合大工程 |
![]() | 40 Rehtt 2024-07-13 14:34:44 +08:00 via Android 前段时间重构 php 也是同感 |
![]() | 41 bronyakaka 2024-07-13 14:35:18 +08:00 Python 是强类型!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
![]() | 42 AV1 2024-07-13 14:43:09 +08:00 @CodeCodeStudy 你说说哪些编程语言是能够通过 type 来区分 NaN 的? 反正 java 和 python 都不行,都需要专门的 isNaN 来判断。 // java double x = Double.NaN; System.out.println(x == Double.NaN); // false System.out.println(Double.isNaN(x)); // true # python import math x: float = float('nan') y: float = float('nan') print(x == y) # False print(math.isnan(x)) # True 你也认为这是 java 和 python 的“坑”吗? |
43 CLMan 2024-07-13 14:48:45 +08:00 @CodeCodeStudy NaN 是计算机为了满足数学需求搞出来的,在浮点数的标准 IEEE754 里面有规定,现代编程语言差不多都支持这个概念(因为都依赖于底层实现),这怎么能怪到 JS 去。 https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Errors/Invalid_date Invalid Date 有点类似 null ,算个小坑,要在源头( new Date())进行检测(这意味着与其它编程语言并没有太大区别),后续代码并不需要防御性编程。 个人认为比较坑的,是 Array.isArray()这种需要额外记忆成本(因为浏览器跨框架的原因)的东西。 |
![]() | 44 matrix1010 2024-07-13 14:51:28 +08:00 跟风 diss 一下 Python: "First Python version I used was 2.2. I am using Python since 2003. I cannot figure out my wife’s Python packaging issues. Skill issue." - Armin Ronacher (Creator of the Flask framework. Engineering at @getsentry) |
![]() | 45 shijingshijing 2024-07-13 14:58:19 +08:00 跟语言种类没啥关系,主要还是文档和流程的问题,你还没有碰到复杂逻辑的代码。 |
![]() | 46 RoninLee 2024-07-13 15:01:05 +08:00 昨天还是组内建议了不要用 var ,又不写注释,很难读。 然后下周即将迎来一场 battle ,为啥不用 var 。 --来自 Java 码农 |
![]() | 47 FYFX 2024-07-13 15:15:04 +08:00 |
48 jianchang512 2024-07-13 15:20:21 +08:00 100 个项目里需要重构的能超过 5 个吗,小概率事件谁在乎,快速齐活就完事了 |
49 james122333 2024-07-13 15:34:27 +08:00 via Android 相信我 就算用的是静态语言 迭代几次也差不多认不得 因为习惯太差 习惯太差或者纯搞事的你是拦不住的 现在最讨厌的就是静态语言 开发太慢了 字典倒是无所谓 反正 vim 类似编辑器可以补全字串 |
50 CodeCodeStudy 2024-07-13 15:36:16 +08:00 @DOLLOR #42 然而实践当中,java 很少遇到 double 是 NaN 的情况,如果需要表示没有值的话,用 Double x = null; 来表示即可。 只有 Math 跟数学计算有关的,才会得到 NaN 吧,如果是其他的,如果是参数不正确,通常会抛出异常,而不是返回 NaN 。 |
![]() | 51 laduary 2024-07-13 15:38:43 +08:00 ![]() |
52 CodeCodeStudy 2024-07-13 15:38:44 +08:00 @CLMan #43 Invalid Date 算是一个设计失误了,如果 new Date()的参数不正确,应该是抛出异常或者返回 null 的,而不是一个 Date 对象,调用方还要判断 Date 对象的有效性。 |
53 动态语言深入的是语言细节 然而整齐方便程度还得看封装 |
54 LuckyLauncher 2024-07-13 16:00:25 +08:00 “现在国内的现状就是领导疯狂催,程序员疲于奔命,谁天天给你定义类型,认真命名” 你用 java 通篇给你 abcd 命名你就好维护了 |
![]() | 55 AV1 2024-07-13 16:05:36 +08:00 ![]() @CodeCodeStudy Double x = null 恰好体现了 java 一个天坑,没有 null safety 。 null 居然可以赋值给任意类型,方法的参数总要不厌其烦地判断 if (obj != null)。 特别的是那个 Boolean 类型,相当于有了 null/true/false 三个值,也得先判断是否为 null 才能在判断 true/false 值。这在别的编程语言看来,都是很荒唐的现象。 |
56 whileFalse 2024-07-13 16:07:34 +08:00 via Android 什么适合职场环境,是发钱的人说了算的,不爽可以辞职 |
57 shmilypeter 2024-07-13 16:07:56 +08:00 现在还给你写文档?能跑起来就不错了。以前虽然也流动性强但还是以年为单位的流动,现在以月为单位流动,迭代几次真的是连自己都不认得了。 |
58 mekingname 2024-07-13 16:10:19 +08:00 先搞清楚什么是强类型语言什么是弱类型语言再来吐槽吧。Python 是强类型语言,Javascript 这种才是弱类型语言。区分强弱类型,就看 1 + '1' 的结果。报错就是强类型,等于'11'就是弱类型。 你吐槽的其实是动态语言和静态语言的区别。 |
![]() | 59 tsohgdivil 2024-07-13 16:32:19 +08:00 Python 是强类型,动态类型 |
![]() | 60 pengdachxx 2024-07-13 16:34:22 +08:00 @davehandong 你是没有用现代的 ide |
62 chainal7777 2024-07-13 16:55:10 +08:00 看到楼上一堆人说 python 说是强类型我就想笑,一个解释型语言说自己是强类型,配吗 |
63 Azure99 2024-07-13 16:56:04 +08:00 如果我掏出 Map<String, Map<String, Object>>,阁下又该如何应对? |
![]() | 64 yohole 2024-07-13 17:00:04 +08:00 所以我经常说,从 java 转 python 最难适应的就是这个类型,方法源码和调用链,可以说谁用谁知道 |
![]() | 65 onion83 2024-07-13 17:08:06 +08:00 “看不懂就厌恶,看不爽就是屎山”,将个人“代码洁癖”带入职场的人,一肚子怨气,注定 996 35 岁后失业。 |
66 jackmod 2024-07-13 18:15:51 +08:00 为了消除 pylance 插件的 warning ,以及自动补完,我加了一堆 assert(isinstance(var, class)) 。 现代语言是需要现代工具辅助的,尤其是 py 这类特别灵活的玩意。 |
67 crackidz 2024-07-13 18:29:54 +08:00 点进来之前以为吐槽 Javascript |
68 nowheremanx 2024-07-13 18:36:35 +08:00 ![]() @onion83 我反思一下,看别人写的垃圾代码确实会引起反感,尤其是要加代码到我的项目里。 :D |
![]() | 69 sunpwork 2024-07-13 18:41:27 +08:00 重点不在语言,而是人。我们公司用 Java ,结构全部是 JsonObject ,各种魔法字符串取值,还沾沾自喜觉得灵活。重构直接火葬场,完全找不到结构 |
70 james122333 2024-07-13 18:55:02 +08:00 via Android |
71 james122333 2024-07-13 18:59:25 +08:00 via Android |
72 fzls 2024-07-13 19:11:18 +08:00 我现在写 python 和 lua 的时候都习惯加上类型注释,ide 也能解析,维护起来方便很多-。- |
![]() | 73 kandaakihito 2024-07-13 19:11:31 +08:00 @sunpwork 这也太恶心了吧,写这种代码的人过个周末就大概率不知道自己上周写了啥 |
75 longlonglanguage 2024-07-13 19:15:09 +08:00 现在有 ai 了会不会好一点,可以让 ai 读一遍,让 ai 给一个文档说明 |
![]() | 77 javak 2024-07-13 19:29:46 +08:00 via iPhone 一开始就用 Java ,现在现在就没你啥事,你就失业了。所以你看,增加就业拉动经济,多好 |
![]() | 78 Felldeadbird 2024-07-13 19:50:02 +08:00 ![]() 不是哥们,你公司因为发展好,所以你才有机会换语言重构。 这怎么又成批判语言的罪行呢? 要知道公司成立之初啥都没有,技术选型最快实现业务才是关键。一上来就给搞 java 一套,业务还没开展,开发团队就要几十万,承担不起啊。 |
79 kenvix 2024-07-13 20:04:30 +08:00 ![]() @chainal7777 #62 你更是重量级,强弱类型怎么还和解释型联系起来了? |
![]() | 81 lambdaq 2024-07-13 20:12:17 +08:00 你要的不是强类型,是 IDE 里能猜出来自动提示。这一点其实主要是接口不规范。 |
82 jjx 2024-07-13 20:58:50 +08:00 我即世界 |
84 happy32199 2024-07-13 21:08:20 +08:00 via Android 各有优点吧,强类型报个错模棱两可,找半天不知道哪里问题…… 弱类型直接把行数告诉你…… |
86 sir283 2024-07-13 21:18:53 +08:00 python 只适合调库写点简单的东西,写 web 还是用 Java 、Go 、C++,写 web 用 python 除了抖 M ,我找不到第二种选择它的理由 |
![]() | 87 w3cll 2024-07-13 21:19:19 +08:00 @DOLLOR 确实,每次还得先判断下是否是 null ,就很烦多此一举的感觉,除非把 null 转成 bool ,然后类型一致后再判断 |
88 butterls 2024-07-13 21:37:41 +08:00 via Android 这是什么防御型编程 |
89 bzj 2024-07-13 22:00:41 +08:00 @sagaxu 业务复杂的时候,其他语言也一样,这是写代码的人逻辑不严谨,唯一的区别是当遇到对象不存在,其他语言会报致命错误,强制要求重新写,反而其他语言更容易写出屎山代码,而 php 只是报 notice 级别的错误,缺点是容易出 bug |
![]() | 90 wonderfulcxm 2024-07-13 22:13:24 +08:00 via iPhone 归因错误 |
![]() | 91 mightybruce 2024-07-13 22:31:15 +08:00 人的问题非要归于语言,不知道豆瓣、谷歌、instagram 大量代码还是 python 吗 |
92 thorneLiu 2024-07-13 23:30:06 +08:00 via Android Cpp 我看代码我能知道代码在做啥 python 我只能跑起来加打印才知道:( |
![]() | 93 daysv 2024-07-13 23:45:38 +08:00 弱类型动态语言爽飞, 能根据我的思绪飞翔 |
![]() | 94 eachann 2024-07-14 00:03:27 +08:00 笑,什么语言根本不重要,出活快才重要。 特别是小公司,慢点公司都倒了 |
95 oyps 2024-07-14 00:13:26 +08:00 @ciderzero 运行时 Python 是强类型语言,代码外观上是弱类型,很多类型会藏起来或者误导你,不运行都不知道。Java 和 TypeScript 这种把类型写在明面上的,方便查看分析。 |
96 oyps 2024-07-14 00:17:14 +08:00 @ciderzero 虽然现在有很多工具和方法去辅助,使得编码时也能方便查看类型,但是以前的屎山不一定会遵循这些约束,本质还是语言的缺陷导致代码编写时不优雅,我个人的观点 |
![]() | 97 supersu 2024-07-14 00:42:17 +08:00 via Android Python 确实是强类型,但是 if "",if []返回 false 又有点不完完全全绝对强类型,这种不知道算不算语法糖,用起来很爽,但是又落下一个不是绝对完全强类型的把柄,哎,两难~ |
![]() | 98 nuk 2024-07-14 02:13:26 +08:00 动态类型 map 一把梭这不是很正常的嘛,真要到处继承 class 你又要跳脚了。 |
![]() | 99 woniuppp 2024-07-14 02:16:51 +08:00 还好中国职场你说了不算 |
![]() | 100 EndlessMemory 2024-07-14 09:10:36 +08:00 关键还是在于赶项目进度,代码质量常常不被重视 |