0
Do you or your company try and reuse code? If so how and at what level, i.e. low level api, components or shared business logic? How do you or your company reuse code?
您或您的公司是否尝试重用代码?如果是这样,在什么级别,即低级API,组件或共享业务逻辑?您或您的公司如何重用代码?
I used to work in a codebase with uber code reuse, but it was difficult to maintain because the reused code was unstable. It was prone to design changes and deprecation in ways that cascaded to everything using it. Before that I worked in a codebase with no code reuse where the seniors actually encouraged copying and pasting as a way to reuse even application-specific code, so I got to see the two extremities and I have to say that one isn't necessarily much better than the other when taken to the extremes.
我曾经在代码库中使用超级代码重用,但由于重用的代码不稳定,因此难以维护。它倾向于设计更改和弃用的方式级联到使用它的一切。在此之前,我在代码库中工作,没有代码重用,老年人实际上鼓励复制和粘贴作为一种方法来重用甚至特定于应用程序的代码,所以我看到了两个极端,我不得不说一个不一定多在走向极端时比其他更好。
And I used to be an uber bottom-up kind of programmer. You ask me to build something specific and I end up building generalized tools. Then using those tools, I build more complex generalized tools, then start building DIP abstractions to express the design requirements for the lower-level tools, then I build even more complex tools and repeat, and at some point I start writing code that actually does what you want me to do. And as counter-productive as that sounded, I was pretty fast at it and could ship complex products in ways that really surprised people.
我曾经是一个自上而下的程序员。你让我建立一些特定的东西,我最终建立了通用工具。然后使用这些工具,我构建了更复杂的通用工具,然后开始构建DIP抽象来表达低级工具的设计要求,然后我构建更复杂的工具并重复,并且在某些时候我开始编写实际执行的代码你要我做什么。虽然听起来适得其反,但我的速度非常快,可能会以令人惊讶的方式运送复杂的产品。
Problem was the maintenance over the months, years! After I built layers and layers of these generalized libraries and reused the hell out of them, each one wanted to serve a much greater purpose than what you asked me to do. Each layer wanted to solve the world's hunger needs. So each one was very ambitious: a math library that wants to be amazing and solve the world's hunger needs. Then something built on top of the math library like a geometry library that wants to be amazing and solve the world's hunger needs. You know something's wrong when you're trying to ship a product but your mind is mulling over how well your uber-generalized geometry library works for rendering and modeling when you're supposed to be working on animation because the animation code you're working on needs a few new geometry functions.
问题是几个月,几年的维护!在我构建了这些通用库的层和层并重新使用它们之后,每个人都希望提供比你要求我做的更大的目的。每一层都想解决世界的饥饿需求。所以每个人都非常雄心勃勃:数学图书馆想要惊人并解决世界的饥饿需求。然后建立在数学库之上的东西就像几何图书馆一样,想要惊人并解决世界的饥饿需求。当你试图发布一个产品时,你知道出了什么问题,但是当你应该处理动画时,你的头脑正在考虑你的超级通用几何库如何用于渲染和建模,因为你正在使用动画代码on需要一些新的几何函数。
Balancing Everyone's Needs
平衡每个人的需求
I found in designing these uber-generalized libraries that I had to become obsessed with the needs of every single team member, and I had to learn how raytracing worked, how fluids dynamics worked, how the mesh engine worked, how inverse kinematics worked, how character animation worked, etc. etc. etc. I had to learn how to do pretty much everyone's job on the team because I was balancing all of their specific needs in the design of these uber generalized libraries I left behind while walking a tightrope balancing act of design compromises from all the code reuse (trying to make things better for Bob working on raytracing who is using one of the libraries but without hurting John too much who is working on physics who is also using it but without complicating the design of the library too much to make them both happy).
我发现在设计这些超级通用库时,我必须痴迷于每个团队成员的需求,我必须学习光线跟踪如何工作,流体动力学如何工作,网格引擎如何工作,反向运动学如何工作,如何我不得不学习如何在团队中完成每个人的工作,因为我在设计这些超级广义图书馆的同时平衡了他们在走钢丝平衡行为时留下的所有特定需求所有代码重用的设计妥协(试图让Bob更好地处理使用其中一个库的光线追踪,但不会伤害John过多的正在使用物理的人也在使用它,但没有使图书馆的设计复杂化太多让他们都开心了。
It got to a point where I was trying to parametrize bounding boxes with policy classes so that they could be stored either as center and half-size as one person wanted or min/max extents as someone else wanted, and the implementation was getting convoluted really fast trying to frantically keep up with everyone's needs.
它达到了我试图用策略类对参数化框进行参数化的程度,以便它们可以像一个人想要的那样存储为中心和半尺寸,或者像其他人想要的那样存储最小/最大范围,并且实现真的很复杂。快速尝试疯狂地跟上每个人的需求。
Design By Committee
委员会设计
And because each layer was trying to serve such a wide range of needs (much wider than we actually needed), they found many reasons to require design changes, sometimes by committee-requested designs (which are usually kind of gross). And then those design changes would cascade upwards and affect all the higher-level code using it, and maintenance of such code started to become a real PITA.
而且因为每一层都试图满足如此广泛的需求(比我们实际需要的要宽得多),他们发现需要改变设计的原因有很多,有时是委员会要求的设计(通常是粗略的)。然后,这些设计更改将向上级联并影响使用它的所有更高级别的代码,并且此类代码的维护开始成为真正的PITA。
I think you can potentially share more code in a like-minded team. Ours wasn't like-minded at all. These are not real names but I'd have Bill here who is a high-level GUI programmer and scripter who creates nice user-end designs but questionable code with lots of hacks, but it tends to be okay for that type of code. I got Bob here who is an old timer who has been programming since the punch card era who likes to write 10,000 line functions with gotos in them and still doesn't get the point of object-oriented programming. I got Joe here who is like a mathematical wizard but writes code no one else can understand and always make suggestions which are mathematically aligned but not necessarily so efficient from a computational standpoint. Then I got Mike here who is in outer space who wants us to port the software to iPhones and thinks we should all follow Apple's conventions and engineering standards.
我认为你可以在一个志同道合的团队中共享更多代码。我们根本没有像志同道合的那样。这些都不是真正的名字,但我在这里有Bill,他是一个高级GUI程序员和脚本编写者,他创建了很好的用户端设计,但是有很多黑客可疑的代码,但是对于那种类型的代码来说它往往是可以接受的。我让鲍勃在这里是一个老计时器,自从打卡时代以来一直在编程,他喜欢用里程碑编写10,000行函数,但仍然没有得到面向对象编程的观点。我在这里得到了乔,他就像一个数学向导但编写了其他人无法理解的代码,总是提出数学对齐的建议,但从计算的角度来看并不一定非常有效。然后我让Mike在这里,他们希望我们将软件移植到iPhone,并认为我们都应该遵循Apple的惯例和工程标准。
Trying to satisfy everyone's needs here while coming up with a decent design was, probably in retrospect, impossible. And in everyone trying to share each other's code, I think we became counter-productive. Each person was competent in an area but trying to come up with designs and standards which everyone is happy with just lead to all kinds of instability and slowed everyone down.
试图满足每个人的需求,同时提出一个体面的设计,可能是回想起来,不可能。在每个试图分享彼此代码的人中,我认为我们变得适得其反。每个人都有能力在一个地区,但试图提出每个人都满意的设计和标准,只会导致各种不稳定,并减慢每个人的速度。
Trade-Offs
So these days I've found the balance is to avoid code reuse for the lowest-level things. I use a top-down approach from the mid-level, perhaps (something not too far divorced from what you asked me to do), and build some independent library there which I can still do in a short amount of time, but the library doesn't intend to produce mini-libs that try to solve the world's hunger needs. Usually such libraries are a little more narrow in purpose than the lower-level ones (ex: a physics library as opposed to a generalized geometry-intersection library).
所以这些天我发现平衡是为了避免代码重用最低级别的东西。我可能会使用自上半场的自上而下的方法(与你要求我做的事情不太分离),并在那里建立一些我可以在短时间内完成的独立库,但是图书馆不打算生产试图解决世界饥饿需求的小型库。通常这些库的目的比较低级的库要窄一些(例如:物理库而不是广义几何交叉库)。
YMMV, but if there's anything I've learned over the years in the hardest ways possible, it's that there might be a balancing act and a point where we might want to deliberately avoid code reuse in a team setting at some granular level, abandoning some generality for the lowest-level code in favor of decoupling, having malleable code we can better shape to serve more specific rather than generalized needs, and so forth -- maybe even just letting everyone have a little more freedom to do things their own way. But of course all of this is with the aim of still producing a very reusable, generalized library, but the difference is that the library might not decompose into the teeniest generalized libraries, because I found that crossing a certain threshold and trying to make too many teeny, generalized libraries starts to actually become an extremely counter-productive endeavor in the long term -- not in the short term, but in the long run and broad scheme of things.
YMMV,但如果我多年来以最困难的方式学到了什么,那就是可能存在一种平衡行为,并且我们可能想要在一个细粒度级别的团队设置中故意避免代码重用,放弃一些最低级代码的一般性有利于解耦,具有可塑性代码我们可以更好地塑造以提供更具体而非一般化的需求,等等 - 甚至可以让每个人都有更多自由以自己的方式做事。但当然所有这一切都是为了仍然生成一个非常可重用的通用库,但不同之处在于库可能不会分解成最青睐的通用库,因为我发现超过某个阈值并试图制造太多从长远来看,从长远来看,广义的图书馆开始真正成为一种极其适得其反的努力。
If you have a piece of code which could potentially be shared across a medium size organization how would you go about informing other members of the company that this lib/api/etc existed and could be of benefit?
如果您有一段可能在中型组织中共享的代码,您将如何通知该公司的其他成员这个lib / api / etc是否存在并且可能有益?
I actually am more reluctant these days and find it more forgivable if colleagues do some redundant work because I would want to make sure that code does something fairly useful and non-trivial and is also really well-tested and designed before I try to share it with people and accumulate a bunch of dependencies to it. The design should have very, very few reasons to require any changes from that point onwards if I share it with the rest of the team.
这些天我实际上更不情愿,并且如果同事做了一些多余的工作,发现它更可原谅,因为我想确保代码做一些非常有用且非平凡的事情,并且在我尝试分享它之前也经过了充分的测试和设计与人共同积累一堆依赖。如果我与团队的其他成员分享,那么设计应该有很少的理由要求从那时起进行任何更改。
Otherwise it could cause more grief than it actually saves.
否则它可能比实际节省更多的悲伤。
I used to be so intolerant of redundancy (in code or efforts) because it appeared to translate to a product that was very buggy and explosive in memory use. But I zoomed in too much on redundancy as the key problem, when really the real problem was poor quality, hastily-written code, and a lack of solid testing. Well-tested, reliable, efficient code wouldn't suffer that problem to nearly as great of a degree even if some people duplicate, say, some math functions here and there.
我曾经如此容忍冗余(在代码或努力中),因为它似乎转化为在内存使用中非常错误和爆炸性的产品。但是我把冗余放大了太多关键问题,真正的问题是真正的问题是质量差,编写匆忙的代码,缺乏可靠的测试。经过充分测试,可靠,高效的代码不会遇到这个问题,即使有些人在某些地方复制了一些数学函数,也几乎没有这个问题。
One of the common sense things to look at and remember that I didn't at the time is how we don't mind some redundancy when we use a very solid third party library. Chances are that you guys use a third party library or two that has some redundant work with what your team is doing. But we don't mind in those cases because the third party library is great and well-tested. I recommend applying that same mindset to your own internal code. The goal should be to create something awesome and well-tested, not to fuss over a little bit of redundancy here and there as I mistakenly did long ago.
在我们使用非常可靠的第三方库时,要注意并记住我当时没有的常识性事项之一就是我们不介意一些冗余。您可能会使用第二方或第二方库,这些第三方库与您的团队正在进行的工作有一些冗余的工作。但是我们并不介意那些情况,因为第三方图书馆很棒且经过充分测试。我建议将相同的思维方式应用于您自己的内部代码。我们的目标应该是创造一些令人敬畏和经过充分测试的东西,而不是因为我在很久以前错误地做过这里和那里的一点点冗余。
So these days I've shifted my intolerance towards a lack of testing instead. Instead of getting upset over redundant efforts, I find it much more productive to get upset over other people's lack of unit and integration testing! :-D
所以这些天我把我的不宽容转向缺乏测试。我发现,对于其他人缺乏单元和集成测试感到不安,我发现它不会因冗余工作而感到沮丧! :-D