加载中

When I found out I would be working on porting an old Python codebase to Node, I was slightly excited. These kinds of projects always give you more creative freedom than the ordinary code maintenance gig, and something about the challenge of rewriting other people’s code makes it fun as hell.

The excitement significantly faded once I actually got a look at what we were going to work with. Legacy code can be nasty, but I’ve been programming for 15 years and only a couple of times had I seen something like this. The authors had created their own framework, and it was a perfect storm of anti-patterns: no separation of concerns, mixed spaces/tabs for indentation, multiple names for the same concept, variables being overwritten by the exact same data coming from a different yet nearly identical method, magic strings… this mess could only have been the product of a room full of babbling monkeys copying code randomly from Google.

And yet, it was not the code’s dismal quality that piqued my interest and led me to write this article. What I discovered after some months working there, was that the authors were actually an experienced group of senior developers with good technical skills. What could lead a team of competent developers to produce and actually deliver something like this? What I’ve come up is a list. These are some bad habits that even experienced teams can get into which will severely affect your end product, more than any static code checker or development methodology could rescue it from.

当在将老的 Python 代码库移到 Node 的时候,我内心是有点小激动的。这些项目相对于常规的代码维护工作总会给你更多的创造性的自由。重新编写其他人的代码带来的挑战使得这一切变得非常开心。

但这种兴奋之情在我看了一眼我们即将要做的事情的时候很快就消失了。旧代码真的是很恶心,我已经编程 15 年了也就只见过几次这样的情况。原作者创建了他们自己的框架结构,而且可以称得上是一个反模式的劫难:没有关注点的划分,混合空格/制表符缩进,同一个概念有多个名字,变量被来自不同的但是几乎有相同的方法下的同一个数据过多的重写,字符串。。。这一烂摊子就好像是呀呀学语的猴子从 Google 随意复制代码的成果。

但是,刺激我写下这篇文章还不只是因为代码本身糟糕的质量,而是在经过几个月工作下来,我惊奇地发现原作者实际上是一群拥有很高技术水平的资深工程师。是什么导致一群有能力的开发者产出并交付这样一堆垃圾呢?我能想到的原因有很多。这些是我认为连资深的团队都可能会沾染的坏习惯,这些坏习惯会严重地影响你的终端产品,甚至连源码检查或者开发方法论都无法拯救。

Giving excessive importance to estimates

An important component of this project was the focus on deadlines, even to the detriment of code quality. If your developers have to focus on delivering rather than on writing good code, they will eventually have to compensate to make you happy. The two ways in which they can do this are over-estimating and over-promising, and they both come with added baggage.

Typically it’s more difficult to over-estimate because the effects are immediately evidenced on project cost, so your developers might choose to over-promise instead, and then skip important work such as thinking about architectural problems, or how to automate tasks, in order to meet an unrealistic deadline. These tasks are often seen as added value, so they get cut without notice. Product quality will decline as you accumulate technical debt, and you’ll find out about it later than you’d really want to, because reorganizing code later in a project costs exponentially more.

As an example, on this project I would find code that was obviously duplicated elsewhere, but it seemed that people were in such a rush to deliver that some developers would not bother to check if someone else had written the same method or SQL query before.

Sometimes estimates can even be deceiving. For example, Agile has a term called “velocity”. The idea is to calculate how fast your team can deliver, and make the necessary changes to go faster. The problem is that it’s not possible to come up with an accurate velocity in the short to mid term. The law of averages says that you can’t look at past performance to gauge how fast you can go right now, because past performance is not a good indicator of future results.

The law of averages is a layman’s term for a belief that the statistical distribution of outcomes among members of a small sample must reflect the distribution of outcomes across the population as a whole.

In truth, a developer can write a large amount of code one day, and she can take three days to write five lines of code after reading documentation and collaborating with teammates. Averaging estimates will not net you valuable information in the short or mid term.

过于强调预算

这个项目的一个重要问题就是过多的关注截止期限,这对代码质量带来了很大的伤害。如果开发者们被迫关注交付而非编写一个好的代码本身,他们最终不得不为让老板开心而买单。原因有两种,一是估计过高,二是承诺过多,不管怎样,最终都会带来更多的包袱。

通常来说,由于效果很快会在项目的成本上体现,因此您的开发人员可能会选择过度承诺,然后跳过重要的工作,如考虑架构的问题,或者如何使任务自动化,从而达到一个不现实的截止期限。这些任务通常是被视为附加值,所以它们会在没有通知的情况下直接削减。积累的技术债务越多,产品的质量也就随之下降,甚至会比以前设想的更多,因为在一个项目上后期重编代码的代价会成倍增加。

举一个例子,在这个项目上,我会发现一些代码明显在其他地方已被写过,但是好像当时急于交付,一些开发者也就懒得检查是否有其他人在此之前已经写了相同的方法或者SQL查询。

有些时候,预算可能是假的。例如,Agile有一个术语叫“速度”,这个概念是为了计算你的团队交付有多快,然后做一些必要的调整来提速。问题是在短期到中期里是不太可能算出一个精准的速度的。平均法则强度,你不能凭借过去的业绩来测量你现在的速度,因为过去的业绩并不是一个好的未来结果的指示器。

(注:平均法则是一个外行术语,认为一部分小样的数据分布的结果肯定会反映整个数据分布的结果)

事实上,一个开发者可以一天可以编写很多的代码,也可以在读完文档并在考虑和同事们如何合作后,三天只写五行代码。平均预算并不会在短期和中期得到有价值的反馈。

Giving no importance to project knowledge

As your project progresses, your team learns about the business, the concepts behind it and how they connect together. They also learn about the implementation as they write code, because you can never fully visualize how things will turn out and which challenges you will face. Some business fields even have an inherent complexity that takes a long time to digest.

As this was a full rewrite of old code, it was particularly interesting in this regard, because it serves to show whether your team’s management understands project knowledge and how it impacts development. If you’re in a large project and there are modules for which you have no expert, no-one to ask about, that’s a big red flag. The value in rewriting code rests entirely on taking advantage of what you learned the first time around, so value that knowledge dearly.

If you put a different team to do the rewriting, as was done in my case, you are ignoring all your learning and relying solely on your new team’s skills, which likely won’t make up for the lack of information. A mediocre developer is going to do a better job at rewriting something he wrote himself, and he’ll do it faster, than if you give the job to someone else entirely.

Even hiring is impacted by project knowledge. The more information the project carriers, the longer it will take to bring people up to speed, so not only is domain knowledge more valuable then, it’s also important to focus on hiring good people. If you don’t hire well, you’ll get tied up to a bad team that will go nowhere for months.

不重视项目知识

随着您的项目的推进,您的团队会学习业务,业务背后的概念以及它们是如何联系在一起的。他们还会在编写代码时研究实现方式,因为您无法完全了解业务的演变以及将会面临的挑战。一些业务领域甚至本身就很复杂,需要很长时间才能消化。

由于这是对旧代码的全面重写,在这方面特别有趣,因为它可以显示您的团队的管理层是否了解项目知识以及它对开发的影响。如果你在一个大型项目中,没有专家,没有人过问项目知识,这是一个很大的危险信号。重写代码的价值完全在于利用你第一次学到的项目知识,所以项目知识很珍贵。

如果你把不同的团队放在一起做重写,就像我的情况一样,你忽略了所有的项目知识学习,只依靠你的新队员的技能,这可能不会弥补缺乏的信息。比起把工作完全交给别人,一个普通的开发人员能更好地重写他自己写的内容,他会做的更快。

即使招聘也受到项目知识的影响。项目的信息越多,人们成长需要的时间就越长,所以不仅仅知识很重要,还要注重招聘好的人才。如果招的不好,你会忙于应付一个糟糕的团队,几个月内什么事也做不成。

Focusing on poor metrics such as “issues closed” or “commits per day”

When a measure becomes a target, it ceases to be a good measure.
– Goodhart’s law

At some point while I was getting up to speed on this project, somebody asked me why another developer was closing issues much faster than me, as if delivering faster is a good thing. As you can imagine, it took me a glance at his code to find four bugs in a single line. Focusing on unreliable metrics such as this will completely derail your project, and cause people as much stress as deadlines.

One metric that few seem to focus on is regression rate of issues. There are bugs such as null pointer exceptions that might show up much later, and if you’re not tracking regressions, it will seem as if bugs keep springing up out of nowhere. In this situation, you’ll never find the source of your problems, because you’re looking in the wrong place.

Ultimately what matters is what is delivered to the client, how happy they are with the product, and how it affects their bottom line, but it takes a lot of self-control to focus on delivered quality and ignore juicy metrics such as commit rate or issues closed.

A good way to know if a metric is useful or not, is to try to understand what personal values it outlines. Concentrate on metrics that advertise good attention to details, good communication skills and good attitude, especially if they require great effort to cheat.

重点关注诸如 “关闭的问题” 或 “每天的提交” 等不好的指标

当一个政策变成目标,它将不再是一个好的政策。 - 古德哈特定律(Goodhart's law)

一些时候当我开始着手于推进项目的进度,一些人会问我为什么另一些开发者关闭问题的速度远远快于我,似乎解决得越快是一件好事。你可以想象到,当我去瞥一眼他写的代码,在一行里面发现了 4 个 bug。关注于像这样不可靠的指标完全是与项目脱轨的,会引起人们类似于项目截止期即将到来般的压力。

似乎很少人关注的一个指标是问题的重现率。一些 bug,例如空指针异常, 可能会在后期重复的出现,如果你并没有跟踪它的复现,那看起来就像 bug 会无处不在地不断涌现。在这种情况下,你将永远无法找到问题的源头,因为你的关注点错了。

最终真正重要的是交付给客户的东西,他们拿到产品时的愉悦,以及它如何影响他们的底线,但是它需要大量的自我管理,专注于提高交付的质量和对无意义指标的忽略,如提交率或关闭的问题。

了解一个指标有意义与否的一个好的方法是试着去理解其所体现的个人价值。关注那些可以给出好的建议、体现沟通技能和良好态度,尤其是需要巨大的付出才能作弊的指标。

Assuming that good process fixes bad people

Good process is portrayed as a kind of silver bullet in business. In my experience some companies, especially large ones with a poor hiring methodology, end up making their process increasingly strict to put toxic people in line, in turn restricting the creative freedom of the ones carrying the team. Not only that, but you still need people to carry out your process properly in the first place for it to work.

It never ends, and this entire problem can be disregarded by just fixing the hiring. Talent makes up for any other inefficiency in your team. That’s the entire point of favoring smart work over hard work.

Developers can be especially tricky to communicate with. In such a complex codebase, I had to constantly ask others for help, and would not often have people happily set time aside to give me a hand. That does not reflect a good attitude, and in tough tasks things can get especially stressful if you have to ask for help and can only count on a few of your teammates to have both the knowledge and the will to give you a hand.

You need people who can apply common sense and good taste, and who will call you out if your process is holding them back. Every build tool, every static checker and every communication tool has good and bad use cases, and you need people to tell you about it, not to blindly apply something that looked good in a different context months ago.

假想好的流程能弥补人员素质的不足

良好的流程常在商业上被认为是灵丹妙药。以我在一些公司里的经验来说,尤其在那些使用了差劲的招聘方法的大公司,最终使得他们的操作流程越来越严苛,这反过来限制了团队参与人自由的发挥创造性。话虽如此,但是仍然需要人们首先按照正常的流程工作。

这永远不会结束,除非通过改进招聘方法来弥补该问题。人才可以弥补你的团队在效率上的不足,这是使工作化艰巨为高效的整个关键点。

开发人员之间可能特别难以沟通。在使用一个复杂的代码库时,我不得不从他人那里寻求帮助,也不见得每一次他人都能愉快的抽出时间给予援手。无法回馈一个良好的态度,而且在艰难的任务面前如果你需要寻求帮助,却只能指望那有限的几个有能力且愿意帮你一把的队友,此时你会倍感压力。

你需要的队友应该具备足够的开发常识且乐于助人,如果你的流程对他们产生了影响,会向你反馈。每个构建工具,每个静态检查器和沟通工具有好或坏的用例,你需要人们告诉你这件事,不要盲目地在不同的环境下应用这些仅仅是几个月前看起来好的东西。

Ignoring proven practices such as code reviews and unit testing

Staying up to date on modern software development processes might not be enough to put a derailed project back on it’s tracks, but it’s certainly necessary anyway if you want your team to stay competitive. This is where proven practices step in, and there are a few of them. Test-driven development has been shown to reduce defect rates 40% to 90%, with an increase in development time in the 15%-35% range. Code reviews have also been shown to decrease defect rates, in some cases up to 80% over manual testing.

Imagine my dismay when I had to collaborate with a colleague on that legacy project and his screen displayed Notepad in its full glory. Using “search” to find methods might have been rad back in the nineties, but these days, refraining from using tools such as modern IDEs, version control and code inspection will set you back tremendously. They are now absolutely required for projects of any size.

For an in-depth look at what is proven to work in software development, check out the book Making Software: What Really Works, and Why We Believe It. It has a nice list of valuable and proven practices which have been backed by studies over the years.

忽略已经被验证的实践,比如代码评审和单元测试

保持最新的现代软件开发过程可能不足以使脱轨的项目回到其轨道上,但如果你希望团队保持竞争力,那肯定是必要的。这是经验证过的实践的介入点,这里是其中一些。测试驱动的开发已经被证实可将缺陷率降低 40% 至 90%,开发时间增加约在 15%-35% 的范围内。代码评审也被证明可以降低缺陷率,在某些情况下比手动测试高出 80%。

想象一下,当我不得不与那位遗留下来的项目的同事合作时,我沮丧的样子。他的屏幕上用记事本显示了所有代码。使用 “搜索” 来查找方法可能已经在九十年代被忽略了,但是这些天,避免使用诸如现代 IDE,版本控制和代码检查等工具,将使你极大地重视它。它们现在对任何规模的项目都是绝对需要的。

为了深入了解在软件开发中有哪些工作,请查看 Making Software: What Really Works, and Why We Believe It (软件制造:真正的工作原理是什么以及我们为什么信任它)。它有一个很好的关于有价值和成熟的实践列表,并且已经被研究证实多年了。

Hiring developers with no “people” skills

It’s not that developers can’t talk to other people. I was once a shy developer myself and eventually managed to stand in front of an audience and give a talk just fine.

The problem comes when someone isn’t willing to even try, or becomes annoyed by requests to improve communication. If there’s one thing that can speed up development time more than anything else that I’ve mentioned, it’s improving communication. Particularly when you reduce distances and work on informational proximity, you enable a more fervent and articulate connection in the workplace. It doesn’t matter that the other guy might be ten thousand miles away. One Skype call can turn a long coding marathon into a five-minute fix.

雇用没有人际沟通技巧的开发者

这不是说开发人员不能和其他人交谈。我曾经是一个害羞的开发者,最终成功地站在观众面前,很好地说话。

当有人不愿意尝试,或者因为提高沟通的要求而感到烦恼时,问题就会出现。 如果有一件事可以比我所提到更多地加快开发时间,那就是正在改善沟通技巧。 特别是在你为了降低距离感以及从事与信息相关工作时,你可以在工作场所实现更加热切和清晰的连接。 另一个人可能在万里之外并没有什么问题。一个Skype通话可以将长的编码马拉松变成一个五分钟的解决方案。

Conclusions

When you enable and encourage working smart by using the best tools, proven techniques and great communication, software development will definitely flow more naturally. What you can’t assume is that just because you’ve signed up to apply Agile or some other tool, that nothing else matters and things will sort themselves out. There’s a synergistic effect in action here which can make a team exponentially more productive if they’re set up right, and terribly slow and sloppy when no attention is paid to the details.

结语

当你通过使用最好的工具、成熟的技术和良好的沟通来实现和鼓励聪明的工作方式,软件开发肯定会推动得更加自然。 你不能假定的是:因为你已经笃定了应用敏捷开发工具或其他工具,其他事情都不重要了,事情能够自动排序。 这里有一个协同效应,如果设置正确,这可以使一个团队按照指数级得变得更有成效,并且在不关注这些细节的情况下会非常缓慢和混乱。

返回顶部
顶部