入职后发现项目组代码异常混乱,是去是留?

注:本文来自知乎,阅读原文请点击左下角的原文链接按钮。

在展开讨论之前,先抛出结论:对于商业价值已在明显缩水中的项目,大动干戈意义确实不大;而对于一个急速成长或稳定运行中的项目而言,有计划有步骤地整理和翻新,是非常必要而且很有讲究的。各种在初期不会显山露水的局限和瓶颈,会随着项目规模的成长不断凸显,此时,若不能水涨船高,通过积极手段逐步改良其内部实现,随着贪一时之快的补丁越积越多,系统将日趋僵化,后果自不必说。

对于重写本身,我们也大可不必畏之如虎。虽说正如 Joel 所说,“废弃现存可运作的代码跑去完全重写”几乎总是个错误的决定,但“中小型系统或组件的受控重写”却是很常见的改良系统的手段。比如这个:

Rewriting a large production system in Go

在这篇文章里,Matt Welsh 同学介绍了自己是如何使用 Go 来完全重写一个 Google 的生产环境下的系统的。推荐感兴趣的同学前往一读。此外我读过一篇讲 facebook 是如何决定和实施一个服务的重写的,还有一篇是 GitHub 如何保证重写的新系统和老系统之间无缝平滑过渡的,这两篇都蛮有趣,可现在一时之间找不到链接了,不过没关系,后面我会介绍一些我仍记得的思路。至于微软是如何(反复)重写 Windows 组件的大家可以到 The Old New Thing 上去看,老的例子有 GDI, Direct3D, Visual C++, MSE,新的例子则有 Edge (IE)。

关于从 IE 到 Edge 还有一个有趣的曲折——其实自从 IE8 之后微软就动了重写的心思了,在 IE9 中,微软尝试了所谓的“完全重写 (Rewrote From Scratch)”这个版本里把原来的 Javascript 解释器替换为一个新写的能生成本地的 native code 的执行引擎,把图形系统内的大多数渲染工作挪到了 GPU 上,还有一个全新的布局引擎 (With IE9, we rewrote our layout engine from scratch) 但是(这里才是重点),就连这种程度的重写也还是不够的,微软后来才意识到,人们的关注点变了,互联网的焦点已经在向移动端转移,于是才有了现在更彻底的重写——Windows Edge(原来的 code name 叫 Project Spartan)

好了,在了解到在有重大商业影响的项目中,重写也不是什么偶然的事情之后,我们就会明白,已有的 Legacy Code 并非刻在石头上的神谕,尝试着去逐步改进自己维护的代码,重点不在于“能不能”,而在于“应不应该这么做” ,“如果需要,应该做到什么程度?”,还有“实践中,如何以受控的方式去实施”,这样才能在避免失控的悲剧的同时,周期性地抛下越来越沉重的负担,让系统得以轻快而长久地健康运行。


Legacy Code 在不同的人眼里长什么样?

在新来的萌宠小师妹眼中,现有系统是这样的:

0?wx_fmt=jpeg在曾经沧海的大师兄眼中,现有系统是这样的:

0?wx_fmt=jpeg在新加入的同事眼中,大概还能分得出的几坨貌似解耦的模块,(由于各种不足为外人道的潜规则)在老同事眼里,其实跟一整坨也没什么区别。不同的是,老同事对系统的全貌和脉络,至少还有逻辑上的概念,知道整个系统的重心和支撑点在哪儿,知道那茂密毛发下面隐藏着什么(……)。

所以,在你感觉眼前的代码比较混乱的时候,想想这只羊吧。虽说不管毛长毛短,能挤奶的就是好羊,可为了让自己以后能活得轻松点,给它洗洗澡剪剪毛啥的还是值得考虑的。


标准的受控重写 (Managed Rewrite) 应该长什么样?

0?wx_fmt=jpeg

当你决定撸起袖子大干一场的时候,如果没有上图这样的详细计划和分步的路线图,而只是盲人摸羊,走到哪里算哪里的话,会很容易掉到坑里的,达到预期的可能性也会大大降低。请注意,这张图最重要的价值在于,它把一个风险很大的单步决策拍碎成了许多细碎的小步骤,每个步骤彼此独立,需要承担的风险或重要性用颜色表示。这样一方面清晰地知道自己的目标和进展,不会迷失方向;另一方面也随时保留可以撤销至某个安全点上的能力。

进化 (Evolution),而非革命 (Revolution)

0?wx_fmt=png这与上一张图表达的实际上是一个意思。正如在做代码重构时的策略那样,我们在战略上也把大的目标切成小块,始终谨慎地保持小步前进,始终避免做过大的决定,始终把风险控制在能接受的范围内。

平行实现 (Parallel Implementations)

平行实现是完全重写某个服务的重要手段,关于这个主题 John Carmack 曾写过一篇非常精彩的文章“Parallel Implementations”,现在由于 altdevblogaday 这个网站关闭链接已经失效了。此文非常精彩,强烈推荐。

此文是这样开头的:I used to Code Fearlessly all the time, tearing up everything(!!!) whenever I had a thought about a better way of doing something. There was even a bit of pride there — “I’m not afraid to suffer consequences in the quest to Do The Right Thing!” 三个黑色加亮部分体现了卡马克同学一贯的价值观,俺写到这里心里默默为卡神点了三个赞。

整个文章的精华在这一段:

What I try to do nowadays is to implement new ideas in parallel with the old ones, rather than mutating the existing code. This allows easy and honest comparison between them, and makes it trivial to go back to the old reliable path when the spiffy new one starts showing flaws. The difference between changing a console variable to get a different behavior versus running an old exe, let alone reverting code changes and rebuilding, is significant.

还有这一段:

There are two general classes of parallel implementations I work with: The reference implementation, which is much smaller and simpler, but will be maintained continuously, and the experimental implementation, where you expect one version to “win” and consign the other implementation to source control in a couple weeks after you have some confidence that it is both fully functional and a real improvement.

文章的最后,卡神写到:

Every single time I have undertaken a parallel implementation approach, I have come away feeling that it was beneficial, and I now tend to code in a style that favors it. Highly recommended.

正是因为这几段都很精彩,所以原封不动摘录于此。(其实要不是篇幅所限,真想干脆全文摘录了) 平行实现的细节我就不展开讲了,大家直接看原文好了。

幽灵替补 (Ghost Alternative) ,柔性服务和灰度发布

“幽灵替补”是我为前文提到的一种做法随便起了个名字,方便记忆。前文提到,在一篇讲 GitHub 的某服务的重写过程中,他们把该服务的新实现挂在老实现上一起跑(正如附身的幽灵),当有新的请求过来时,新老两套系统同时开始处理,但最后的输出仍采用老系统的结果,新的系统输出结果被记录下来,与老系统的结果比对。千万次运行下来后,新系统得到了足够的考验,错误率低到一个程度后,再淘汰掉老系统。

写完了才发现这里(Parallel Adoption)有 wikipedia 上对此方法的综述,也可供参考。

这里是一个典型的例子:

0?wx_fmt=jpeg至于最近说的比较多的柔性服务和灰度发布,可以参考这两篇:

  • 腾讯大讲堂:发10亿个红包,微信为啥没崩溃?

  • 微信技术总监周颢:一亿用户背后的架构秘密

这些技术,都可以帮助我们实现新老系统之间顺利的迁移和过渡工作。


总得来说,对系统的维护者来说,一味地积极重构,和一味的消极补丁,都是不可取的。有经验的开发者,会更准确地评估权衡改动带来的风险和工作量。如同我在“一个有趣的交互 bug ——兼谈游戏的引导系统”一文中提到的那样,大部分问题都可以由浅至深地分析出多个不同的解决方案,以便于在不同的情形下去取舍和平衡。


最后这句话,与大家共勉吧 0?wx_fmt=gif

0?wx_fmt=jpeg

================================================

感谢 Coding 和 UPYUN 对本微信的支持。Coding.net 是一个面向开发者的云端开发平台,目前提供代码托管、运行空间、质量控制、项目管理等功能。

upyun.com是国内领先的云服务提供商,专注于提供静态文件的云存储、云处理和CDN加速服务。现在注册,即可免费体验!

### 回答1: 我在这家公司工作了几个月,经历了许多令人印象深刻的事情。 一件印象深刻的事情是,我有机会参加了一次跨部门的合作项目。我们花了几周的时间与其他部门的同事一起努力,最终成功地完成了这个项目。我感到非常欣慰,因为这次合作项目不仅让我学到了很多新知识和技能,还增强了我的团队合作能力。 另一件印象深刻的事情是,我有机会参加了公司举办的培训班。这次培训不仅让我学到了很多有用的东西,还让我感受到了公司对员工的重视。我感到非常感激,并且希望能够继续在这家公司工作,不断成长和发展。 总的来说,在这家公司工作的这几个月里,我感到非常充实和满足。我希望能够继续在这家公司工作,与同事们一起共同进步,为公司做出贡献。 ### 回答2: 职后的经历中,有许多令我印象深刻的事情。首先,我对公司的热情接待给我下了深刻的印象。当我踏公司大门时,高管和同事们都亲切地迎接着我,并介绍了公司的文化和价值观。我感受到了团队的温暖和凝聚力,这让我对公司的未来充满了信心。 其次,我参加的职培训也给我下了深刻的印象。公司为新员工提供了全面的培训计划,包括了相关业务知识、技能培养以及团队合作等方面的内容。我深深感受到了公司对员工成长的重视和支持,在培训中我学到了很多实用的知识和技能,这为我今后的工作打下了坚实的基础。 在工作中,我也遇到了一些挑战,但这些挑战也成为了我成长的机会。当初可能会让我感到困惑和不知所措的问题,在同事们的帮助和指导下逐渐变得清晰起来。与此同时,我也发现自己的学习能力和适应能力得到了进一步提高,我逐渐学会了解决问题和独立思考。这种成长的过程让我感到非常自豪和满足。 此外,公司组织的团建活动也给我下了深刻的印象。这些活动不仅丰富了员工的业余生活,更加强了同事之间的交流和互动。我与同事们一起参加了团队建设活动、健身比赛、年会等等,这不仅让我更好地了解了同事们的个性和才能,也帮助我们建立了更紧密的联系和友谊。 综上所述,职后的经历让我感受到了公司的温暖、成长和团队协作的重要性。我深深地明白了团队的力量以及每个人在其中的重要性,我对公司充满了信心和归属感。我将继续努力工作,为公司的发展贡献自己的力量。 ### 回答3: 职后的经历令我印象深刻。第一天到公司,我被人事部门热情地接待,他们详细介绍了公司的各个部门和岗位,给我下了深刻的印象。我感受到了他们对新员工的重视和关心。 在实际工作中,我被分配到了一个团结和谐的团队中。大家相互合作,互相支持,共同完成任务。我发现团队成员之间的默契和协作精神非常令人感动。每个人都愿意互相倾听和分享经验,共同进步。 在工作中,我经常有机会参与各种培训和学习活动。这个公司非常注重员工的专业发展和成长。每次培训都给我带来了新的知识和技能,让我在工作中能更加胜任。同时,我也深受公司文化的影响,学会了团队合作和沟通技巧。 除了工作,公司也注重员工的生活质量。每个月会组织丰富多样的团队建设活动和员工福利活动,使我们感受到了家的温暖。公司的领导也经常与员工进行面对面的沟通,倾听我们的意见和建议。这种平等和开放的文化让我感到很温暖。 总的来说,我职后的经历给我下了非常深刻的印象。在这个公司,我感受到了团队的温暖和互相支持,感受到了公司对员工的重视和关心。我也在这里学会了很多东西,不仅是专业知识,还有团队合作和沟通技巧。我非常庆幸能够加这个大家庭,我对未来充满了信心和期待。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值