if (m_doc->isModified() == true) { for (int i = 0; i < 100; i++) { save(); //Save the document for 100 times to ensure it has been saved successfully. } }
不知道谁写的,总之我都看哭了
以前所在公司做激光雕刻软件,客户对雕刻速度有要求,于是乎大神把显示在客户端的所需时间乘上4/5。后来软件交给我维护,重写了界面,新版本到了客户手里雕刻速度变慢了,无论怎么优化雕刻算法,都不能达到原来的雕刻速度。
后来忘记是怎么看到那个* 4/5了,真是买了表的
举三个我前东家的故事:
1. 写 Facebook Android的代码时候看到
public void testSetCurrentMessageCount() { setupGlobalTestEnvironment(); currentThread.setValue(10); assertEquals(10, currentThread.getValue()); } public void testGetCurrentMessageCount() { testSetCurrentMessageCount(); // Couldn't figure out a better way... }
对,好像是没有更好的办法来测试getter。。。
2. Facebook的Android和iOS的代码里都大量使用 Dependency Injection,主要好处是 便于测试 和 每个类实例的生命周期便于维护。只是开始的时候为了图方便,用的是类的静态方法来拿到 全局的 providerMap。后来Tech Lead规范编程风格之后,禁止大家直接调用静态的globalProvider方法,从ctor里注入。但是FB里的人图方便,还是在继续使用。最后没办法,函数名被Tech Lead改成这样:(由于保密协议,我删除了实现逻辑的代码)
+ (FBProviderMap *)globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED { // .... FBAssertNotNil(globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED, @"Call +[FBGlobalProviderMap setGlobalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED:] before invoking this method."); return globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED; } } + (FBProviderMapData *)globalProviderMapDataDO_NOT_USE_OR_YOU_WILL_BE_FIRED { return [[self globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED] providerData]; }
2. 来自FB神童 Evan Priestley 的 Hackathon 代码 (这哥么高中毕业后开始以写程序为生,主导FB很多的大项目。离开FB之后创立:
Phabricator)。代码本身并不是有缺陷,只是它产生了一个有趣的段子:
Tech Crunch 一直以来以爆FB的八卦为荣,但是很多时候八卦内容完全不准确,甚至是非颠倒,让高层很不爽。Evan Priestely 在一次Hackathon的时候在Facebook Photo里加了一个小按钮 “Fax Photo”,支持把当前照片传真出去,并且收费1美元(背后直接调用第三方传真公司的API)。功能本身在2009年的美国当然没鸟用,当时email,facebook和iPhone都已经高度普及,直接发照片的链接或者邮件即可,没人还想去传真一下。不过 Facebook 已具备极其强大的灰度发布功能,Evan把这个按钮发布出来,只允许 TechCrunch 公司的IP可见(除了TechCrunch,其他用户都看不到),并且在twitter上“透露”了一下Facebook Photo有新功能。
第二天,TechCrunch开始骚动了,一编辑火速发文(伴以截图)来说明Facebook Photo中“fax this”按钮的功能:TechCrunch 原文:
Facebook Now Lets You Fax Your Photos. I Have No Idea Why Anyone Would Want To Do This。在产品流程上,还专门花了一刀成功把图片传真到了公司的传真机上。接下来,开始详细“剖析”此功能开发的初衷和适用场景,最后开始吐槽在这个互联网高度发达的时代开发这么一个古代功能并没有什么卵用。。。
过了两天,TechCrunch终于在众多网友的热心评价下,意识到自己被耍了。于是又发文补充:
Yeah Ok, So Facebook Punk'd UsEvan Priestely 一直是Facebook很多员工心目中的天才,对,极其有争议的天才。
我写的。
用的是某统计软件,建模的关键一步,写了个魔法数字,大概是5.28这样的。
我还贴心地注释了,这个魔法数字来自另一个同事的高端代码,请不要质疑。
正常来说要得到这个数字需要迭代优化,可能代码又要几个屏幕,加上机器跑几个小时,还不一定是最优的。
我问了另一个同事这个数字是怎么来的,他说他凭借个人经验定了一个范围,比如3-6,然后在这个范围内每隔0.01跑一一次模拟。在我码其它代码的几个小时内,他把这些模拟跑完了,发现这个数最好。
那时是半夜三点,跑完这一步后还有很多步,第二天上线。我骂了一句国骂就把这个数字写到代码里了。
第二天上线很顺利,后来做检查的时候我好心把上面那个注释加上了。加上这个注释有两个原因,一是想说有些领导根本不考虑实际情况,硬要上线。二是想说无论是多么傻逼的想法,硬要上也能有办法。
我本准备在后人问起时把这个道理告诉他们,哪知道几个月后我和那位写高端代码的同事都离职了。后来有原公司的人告诉我,直到那个项目下线,这段代码都没人碰过...有些故事,注定淹没在历史的长河里。
我软有不少代码看上去挺好的但是会被标识成操蛋,这都归功于各种静态检查工具。
在我软代码里面起个变量名叫WhiteList都会被自动发bug,因为用White来表示允许就属于种族歧视,一定要改成AllowList。我会告诉你我们因此还真的改了服务接口而且还要做向下兼容吗?
还有变量名叫country也会被查,因为正确的说法是country and region。
我不是说public的类成员哦,private的都不行。
另外kill,dead之类的字眼都是有问题的。
当然你真的一定要用这些词你就得说明理由,然后加supression。
要像 @vczh 那样变量起名bitch什么的那是要死一百遍啊。
所以你现在知道写点代码有多难了吧。
运输管理公司,公司手底下多家分公司,各个分公司都有自己描述线路状态的代码,而总公司有另外一套。所以在总公司的屏幕上,需要用一套“字典”,把各个分公司的描述“翻译”成总公司的语言。
简单吧?
稍微做过leetcode的都知道hashmap搞个单次翻译O(1)时间复杂度简直基本操作。
实际业务中不一定有hashmap这么简单,弄个array挨个找,也至少是单次O(n)复杂度对吧?
很简单吧?how wrong could that be?
就有contractor给我写了个时间/空间复杂度双O(n2)的代码出来。
人家翻译之前,先把字典重新整理一遍,挨个来,整理的过程是先把每个词提取出来,在处理每个词的过程中,都要遍历一遍整个字典,行了妥妥时间复杂度O(n2)。然后还没完,最终导出的字典每个词后边都缀了相当于原来整本字典的数据(非shallow copy),得,空间也O(n2)了。
你以为就完了?没,人家每翻译一个词都要重新干一遍上边的事。
我说大哥你真行,你这相当于拿着汉英双译词典看英文小说,每查一个词之前,都要把汉英双译词典里边每个词都抄一份出来抄成英汉双译词典,别人印书洛阳纸贵,你看书就够了,你这辈子能看完半本就算我输。
说完了上边的再说接下来这个,公司的所谓Typescript项目。一天debug,发现一段代码如下:
const user = new User();
哦原来是新建一个用户,不过奇怪了,为什么要在后端程序里新建一个用户?用户不应该是从jwt token,DB或者相应服务里拉取的吗?接着看看怎么用的:
const email = user.getEmail(req.user);
慢着慢着,这个req.user又和这个user有什么关系?还有为什么这个user获得Email居然要另外一个user的信息?难道这个user是被另外一个user管理的吗?我还是看看这User的class definition吧:
import User from '../user-helper';
啥玩意?这个是个helper?我进文件看看:
export default class UserHelper { getEmail(user) { return user.email; } }
和大多数回答会简化code不同,我这个就是源代码,一刀未剪,我看到后一度半分钟没说出话来,槽太多不知道怎么吐:
看完这个我就叫我经理过来,说:
I'm not sure if someone gets paid by the number of lines committed. If yes, I want his contract as well.
“你把距离显示优化一下,超过1000米就显示公里,精确到小数点后2位。”
“好的!”
然后,在Code Review的时候,我看到了如下的代码片段:
NSString *strLog = [[NSString alloc]init]; NSString *distance = [strLog stringByAppendingFormat:@"%d",(int)dis]; if (distance.length >=4) { int q = 2; for (int i=0; i<distance.length; i++) { if (i >4) { q+=1; } } NSMutableString *str = [NSMutableString stringWithString:[distance substringToIndex:q]]; [str insertString:@"." atIndex:1]; if (str.length >4) { NSString *string = [str substringToIndex:4]; return [NSString stringWithFormat:@"%@公里",string]; } return [NSString stringWithFormat:@"%@公里",str]; }else{ return [NSString stringWithFormat:@"%@米",distance]; }
最后,我饱含热泪,心怀不忍地将他辛勤不易的工作成果改成了如下:
if (dis<1000) { return [NSString stringWithFormat:@"%.0f米",dis]; } return [NSString stringWithFormat:@"%.2f公里",dis/1000.0];
(a != b) ? b : a
以前在人人上贴了这段代码来吐槽前公司的代码质量,被转发后火了,因为神最右的注解:
和老婆意见不一致的时候听她的;意见一致的时候听我的
========================
关于评论中提到的运算符重载等问题,这里统一回答一下:
我摘的这段代码被我省略了上下文。实际情况是,变量是基本类型,也没有重载运算符等其他让这段代码有意义的原因。我刚看到它的时候也绞尽脑汁去想有没有别的可能,试图理解这么写的用意,最后发现只是代码写得烂而已。
enum FiveLine { Gold, Wood, Water, Fire, Earth, };
看枚举名字不知道五行(hang)是什么鬼,看了枚举内容恍然大雾,原来是五行(xing)……
哎。。。跟你们说个奇葩的事情吧。。。
背景:做手持设备的公司,你们可以理解成手机一样的东西。
第一家公司有个大神。写驱动的。
不知道怎么写并发的代码。。。
如果出现问题,就直接sleep。并且创造了自己的一套调试理论。
于是在代码里面就会看到各种莫名其妙的sleep(xxx)。
而且很多都还是神奇数字。不按那个休眠,并发就会出问题...
由于大神杰出的工作,让代码出问题的概率降到了8小时一次。
又特么由于猪队友的硬件设计,我们那里的机器电池在连续使用6小时之后就没电了,于是客户相当于每6小时就要重启一次机器...
嗯...于是,相安无事。
==============================
没想到几句吐槽这么多赞。
看到评论区里面真的有人这么写代码,又想写两句。
借用
@vczh说的一句话(原话记不太清)
现在硬件性能逐步提升,写出能跑的程序太简单,而写出真正好的程序太难。
希望大家在写程序上多追求极致和规范。
如果碰到看起来很傻的问题,先多看看别人怎么解决的。
别什么事情都想当然。
上面的话说给大家,也更多的说给我自己。