励志司机锐锐|高级软件工程师成长秘诀( 六 )


但是 , 它不起作用 。 我发现permutations返回了一个元组列表 , 因此我返回我的排序函数 , 并将它改成一个处理元组列表的排序函数 。
过了一会儿 , 产品又有了新需求:这些排列太长了 , 而且我们想让处理的速度更快一点儿 。 无论这个列表多大 , 我们只需要长度为4的排列 。
啊 。 好吧 。 由于我已经有了一个生成所有排列的函数 , 因此我使用这个函数并从每个排列元组中取前4个元素 。 我意识到这会导致重复 , 因此我将这些元组放到一个set中 , 然后应用排序函数来使它们按正确的顺序排序 。
现在我又做完了 。 哦 , 这真是辛苦 , 但是嘿 , 每个人都有点开心!这个排列函数对于长列表还是很慢 , 因此我添加了一条日志 , 以便某个时候再来看看这个问题 。
如果我花时间去查看itertools.permutations的文档 , 去理解它是如何工作的 , 我就会注意到:它有一个参数可以决定你想要的返回的排列长度 。 它返回一个元组列表 。 而且它返回的时候是排过序的 。 此外 , 输入参数不是一个列表 , 而是一个iterable , 因此我本可以传入generator 。 无论如何 , 它都会被转换成一个元组 , 因此传入列表还是generator都没有关系 。
这个例子可能看起来微不足道 , 但是这背后的思维机制却并非如此 。 我注意到 , 每当我遇到复杂的API和误导的命名时 , 这都会发生在我身上 。
简而言之 , 我的规则是“我不写我不理解的代码” 。 就像“从StackOverflow复制”的习惯一样 , 这条规则包含许多隐性知识 , 而这些知识在翻译过程中会丢失 。 例如 , 理解代码是什么意思?
至少有三个层次的理解:你可能完全理解itertools.permutations会产出什么 , 你可能理解它是如何工作的 , 或者在更深的一个层次 , 你可能理解它的实现决策为什么是那样的 。
层次1是理解函数或API是做什么的 。
层次2是理解它是如何实现的 。
层次3是理解它为什么是那样实现的 。
对于设计良好的API和你不想深入学习的东西 , 级别1就可以了 。
然而 , 级别1是最低要求 。 层次0就是我们在上述例子中看到的 , 这是有问题的 。 另外一个例子是第一次复制现有团队模板 , 这介于层次0额层次1之间 。
是的 , 这是一种权衡 。 层次0非常快 , 而达到层次3需要很多时间 。
当我不复制粘贴现有模板时 , 我的速度就会降下来 。 但当我有足够空闲时 , 我选择在写代码之前达到层次1理解 。 这通常意味着我第一次的时候会很慢 , 但是随着时间的推移 , 我会变得更快 。 每次我都会加深一点儿自己的理解 , 而且这有助于我快速地解决bug 。 我把学习放在完成事情之上 。
有时我也会打破这个规则 。 一些情况下需要快速简单的修改方式 。
有时候 , 开源文档很烂 。 这些时候 , 你需要层次2的理解来给你层次1的理解:你需要去阅读源码 。 每当我必须这么做的时候 , 我都记得为将来的我保留上下文 。 理解别人的代码是很难的 , 特别是如果它是用你不熟悉的语言编写的时候 。 最好不要重复做这种辛苦的工作 。 当你发现有些东西很重要 , 把它写下来——那就是需要评论的点 。 另外 , 你的团队会为此感谢你 。 这是一种建立力量倍增器的简单方法 。
这很像“存”信息包 。 它们是你已经完成的工作单元 , 因此下次你不需要再做了 。
理解层次也适用于你的团队拥有的代码 , 而不仅仅是你复制粘贴的代码 , 或者从其他人那里“继承”来的代码 。 理想情况下 , 你应该对你团队的代码有一个层次2的理解 , 对你自己的代码有个层次3的理解 。 这种理解构建了代码如何工作的思维模型 。
我发现 , 代码审核对于构建这种思维模型有很大帮助 。 我尽可能多地做代码审核:它使我能够跟进我的团队正在做什么 。 对此还有一种非常有意思的反馈机制 。 我可以通过我的审核评论判断我对代码的理解程度 。 我对代码库越不熟悉 , 我的评论就越无关紧要 。 随着我的思维模型的改进 , 我开始将系统看作一个整体以及新的部分是如何与其它部分交互的 。 我能在某个东西不生效时发现不协调的地方并找出来 。 当我这样做评论时 , 我就知道我的理解层次正在慢慢提升到层次2-3 。


推荐阅读