您或您的公司是否尝试重用代码?如果是这样,如何以及在什么级别,即低级 api、组件或共享业务逻辑?您或您的公司如何重用代码?
我曾经在一个代码库中工作,使用 uber 代码重用,但由于重用代码不稳定,因此很难维护。它很容易以级联到所有使用它的方式进行设计更改和弃用。在此之前,我在一个没有代码重用的代码库中工作,其中老年人实际上鼓励复制和粘贴作为重用甚至应用程序特定代码的一种方式,所以我看到了两个极端,我不得不说一个不一定很多在极端情况下比另一个更好。
我曾经是一个超级自下而上的程序员。你让我构建一些特定的东西,我最终构建了通用工具。然后使用这些工具,我构建了更复杂的通用工具,然后开始构建 DIP 抽象来表达低级工具的设计要求,然后我构建更复杂的工具并重复,在某个时候我开始编写真正的代码你要我做什么。尽管这听起来适得其反,但我的速度非常快,并且可以以令人惊讶的方式运送复杂的产品。
问题是几个月、几年的维护!在我构建了这些通用库的一层又一层并重用它们之后,每个人都希望服务于比您要求我做的更大的目的。每一层都想解决世界的饥饿需求。所以每个人都非常雄心勃勃:一个想要令人惊叹并解决世界饥饿需求的数学图书馆。然后建立在数学库之上的东西,比如想要令人惊叹并解决世界饥饿需求的几何库。当您尝试发布产品时,您知道出了点问题,但是当您应该处理动画时,您的大脑正在考虑您的超级通用几何库在渲染和建模方面的效果如何,因为您正在处理的动画代码on 需要一些新的几何函数。
平衡每个人的需求
我发现在设计这些超级通用的库时,我必须着迷于每个团队成员的需求,我必须学习光线追踪是如何工作的,流体动力学是如何工作的,网格引擎是如何工作的,反向运动学是如何工作的,如何角色动画工作,等等等等等等。我必须学习如何完成团队中几乎每个人的工作,因为我在设计这些超级通用库时平衡了他们的所有特定需求,我在走钢丝平衡行为时留下了所有代码重用的设计妥协(试图让正在使用其中一个库的 Bob 进行光线跟踪但又不会伤害到 John 正在研究物理的同时也在使用它但不会使库的设计复杂化的情况太多了,无法让他们俩都开心)。
到了这样一个地步,我试图用策略类对边界框进行参数化,以便它们可以存储为一个人想要的中心和一半大小,或者其他人想要的最小/最大范围,并且实现变得非常复杂快速尝试疯狂地跟上每个人的需求。
委员会设计
而且由于每一层都试图满足如此广泛的需求(比我们实际需要的要广泛得多),他们找到了许多需要更改设计的理由,有时是委员会要求的设计(通常有点粗俗)。然后这些设计更改会向上级联并影响所有使用它的更高级别的代码,并且这些代码的维护开始成为真正的 PITA。
我认为您可以在志同道合的团队中共享更多代码。我们的想法完全不同。这些不是真名,但我这里有比尔,他是一个高级 GUI 程序员和脚本编写者,他创建了很好的用户端设计,但有很多 hack 的有问题的代码,但对于那种类型的代码来说往往没问题。我在这里找到了 Bob,他是一位自打孔卡时代以来一直在编程的老手,他喜欢编写带有 goto 的 10,000 行函数,但仍然不明白面向对象编程的重点。我在这里找到了乔,他就像一个数学向导,但编写的代码没有其他人可以理解,并且总是提出数学上一致的建议,但从计算的角度来看不一定如此有效。
试图在想出一个体面的设计的同时满足这里每个人的需求,回想起来可能是不可能的。在每个人都试图分享彼此的代码时,我认为我们变得适得其反。每个人都在某个领域胜任,但试图提出每个人都满意的设计和标准只会导致各种不稳定并减慢每个人的速度。
权衡取舍
所以这些天我发现平衡是避免代码重用最底层的东西。我可能会使用中层自上而下的方法(与您要求我做的事情相差不远),并在那里建立一些独立的图书馆,我仍然可以在很短的时间内完成,但是图书馆不打算生产试图解决世界饥饿需求的迷你库。通常,此类库的用途比较低级别的库要窄一些(例如:物理库,而不是广义几何交叉库)。
YMMV,但是如果这些年来我以最艰难的方式学到了什么,那就是可能存在一种平衡行为,并且我们可能希望在某个细粒度级别故意避免在团队设置中重用代码,放弃一些支持解耦的最低级别代码的通用性,拥有可延展的代码,我们可以更好地塑造以服务于更具体而不是笼统的需求,等等——甚至可能只是让每个人都有更多的自由以自己的方式做事。但是当然所有这一切都是为了仍然产生一个非常可重用的通用库,但不同的是,库可能不会分解成最小的通用库,因为我发现跨越某个阈值并试图制造太多蝇头,
如果您有一段可能在中型组织中共享的代码,您将如何通知公司的其他成员该 lib/api/etc 存在并且可能有用?
这些天我实际上更不情愿,如果同事做一些多余的工作,我会觉得更可原谅,因为我想确保代码做一些相当有用和不平凡的事情,并且在我尝试分享之前也经过很好的测试和设计和人在一起,积累了一堆对它的依赖。如果我与团队的其他成员分享,那么从那时起,设计应该有非常非常少的理由要求进行任何更改。
否则,它可能会导致比实际节省更多的悲伤。
我曾经非常不能容忍冗余(在代码或工作中),因为它似乎转化为一个在内存使用方面非常有问题和爆炸性的产品。但是我把冗余作为关键问题过分强调了,而真正的问题是质量差、仓促编写的代码以及缺乏可靠的测试。即使有些人在这里和那里复制一些数学函数,经过良好测试、可靠、高效的代码也不会在很大程度上受到这个问题的影响。
要注意并记住我当时没有注意的常识之一是,当我们使用非常可靠的第三方库时,我们如何不介意一些冗余。你们可能会使用一两个第三方库,这些库与您的团队正在做的事情有一些多余的工作。但是我们不介意在这些情况下,因为第三方库很棒并且经过了很好的测试。我建议将相同的思维方式应用于您自己的内部代码。目标应该是创建一些很棒且经过良好测试的东西,而不是像我很久以前错误地做的那样在这里和那里大惊小怪。
因此,这些天来,我已经将我的不容忍转变为缺乏测试。与其对多余的工作感到不安,我发现对其他人缺乏单元和集成测试感到不安更有效率!:-D