电子说
刚学编程的时候有种想法,认为难题应该只解决一次。 但渐渐接触多了前端开发,经常要重复编写代码,特别是生成页面时。 是什么原因导致了代码无法重用呢?
来看看大家是怎样看待这个问题的吧,也许会有所启发。
Aa:主要的问题在于,如果一个问题你没有去在不同的环境下解决很多遍,你很难分得清楚,哪个部分是通用的,哪个部分是跟你当前的环境紧密相关的。如果你什么都不懂,你做出来的代码当然也没办法很好的被重用。所以问题不可能只被解决一次,我们追求的只能是每一次解决的时候花的代价要更少,长远来讲趋向于0。
Ab:因为复用并非无代价,而且代价往往还很高。
从工程上说,任何特性都不是无代价的。复用提供了解决一类问题的灵活性,而灵活性作为一种功能,同样有代价——正如过多地使用虚函数有性能损失,而过多地使用 interface 则一定程度上降低代码可读性。如果构建灵活性的基石皆有代价,那么我们不可能期望灵活性可以免费获得。
而所有的问题解决之道本质上都一样:我们需要权衡每一个选择的好处和坏处,做出对我们现在的项目最有利的方案。举例来说:我们不会在项目最紧张的时候讨论把业务逻辑抽取出来做一个通用的框架,原因很简单:时间不够用。我们也不会在讨论怎么设计通用框架的时候过多地讨论我们具体项目的逻辑,因为追求通用性的设计目的导致我们不可能完全为某一个具体的业务优化。
所以从这个意义上来说,阻碍代码重用的最大原因,事实上来自项目自身:复用代码在绝大多数情况下,都不是一个项目的最终目的。对任何项目来说,唯一绝对存在的目的,是在指定的时间内完成客户给出的需求。当短期内完成功能的需求和复用发生冲突时,理智的项目管理者都不会选择将注意力放在复用上。当然,热衷于复用的程序员必然会以长远的好处为理由为复用辩护;但正如前面的规则指出的,这依然是一个工程上的选择问题,因而仍然需要折衷。在遇到问题时,总是先倒向某一个结果再试图解释,这不是折衷,而是预设立场,这恰恰是工程的大忌。
至于第二个问题,回答是:是的,对任何问题只解决一次是理想状态,但重复解决三到五次问题并非十恶不赦。客户关心的是我们能不能解决他们的问题,而不是能不能对任何问题都只解决一次。——不要把自己的需求误以为是用户的需求,这仍然是一个工程问题。
Ac:可复用的东西(小到函数,大到框架),一定是从诸多应用场景中抽取出来的,换句话说,一定要先有场景,在场景达到一定数量一定复杂度之后才能抽象出来可复用的部分,也就是常说的重构.一开始就追求复用性没什么意义,浪费时间不说,更可能假象的场景根本就不存在,或者实际情况超过想象.一些老手们经验足够丰富,之前遇到过的问题越多,在开始设计的时候就能兼顾到更多的复用场景.做开发,成长的几个阶段必不可少:
1. 不做设计(新手阶段,能实现就好)
2. 过度设计(了解的东西多了,总想追求完美)
3. 简化设计(认知逐渐深入,学会取舍)
4. 最优设计(熟练掌握,知道概念适配场景)
其中23两个状态可能会往复多次,最终达到找到一个平衡的位置.
所以我觉得题主的状态正是逐渐进入过度设计的状态,想追求绝对的复用,没什么不好,有想法就去实践,让结果来验证你的观念,很多东西的度不是别人能教会的,是必须要亲自体验才能了解的和掌握的.
Ad:重用的代码,底层的好写,上层的难写。
底层代码抽象的是机器,服务的是程序员。程序员就那么点追求,读写数据,操作数据,要快,要稳,要容易用,满足就行了。
上层代码抽象的是需求,服务的是用户。用户的需求各不相同,但每个人都觉得自己的需求特有道理,特正义。你说这个我们做不到,因为用了XX lib,立马被喷。
那么多前端库前仆后继,折戟沉沙,却又层出不穷,无非是因为某些需求满足不了。需求总在变,库也跟着花样翻新,但总是差了一两步。说到底,是什么阻止了重用?
是人心呐,是变幻莫测得人心。
人心是一个 moving target,以固定的 pattern 来揣摩人心,结果就是一段想要解决十个需求,却一个需求都解决不好的代码。
所以,底层库可以自顶向下的设计;而面向客户的代码,还要以解决当前问题为先,等到类似的问题多了,再考虑重用。不要刚遇到一个问题,就想写个通用的解法,这样的往往悲剧。
长恨人心不如水,等闲平地起波澜。
Ae:一句话介绍不清楚的,是因为懒惰。
同样的问题应该只解决三次。第一次,你怎么知道这段代码能够重用呢?第二次,也许只是巧合?第三次,看来这确实是个重复出现的问题。然后你就该重构以重用代码了。
当然还可能是因为偏执。重构容易出一些很明显的问题,特别是当你使用的语言类型系统不够强大而你又没有足够的测试的时候。这种时候,维护者通常的反应是:重构代码首先放测试版,出了小问题就修正,只要不是很难处理的大问题一切好说。但是遇到偏执的维护者嘛,就只好放弃了: 放弃 you-get,转投 youtube-dl。
Af:过早优化是万恶之源。
编写代码时,对“可复用”和“扩展性”的考虑,都应限定在一个很小的范围内。否则的话,在当前版本多消耗的时间要远远大于未来复用代码时省下的时间。
从“编程艺术”的角度来讲,这种解决方法一点都不漂亮。每个人初学开发时都会有这种想法:要完美、要考虑周全、为了不存在的需求而编写一堆“预备代码”。但是,在经历过几个项目后总结一下,就会发现这种事是多么浪费时间和精力,当初预想的需求90%没有出现,出现的那部分也和设想大相径庭了。
Ag:编写代码时,如果考虑今后的重用,工作量一般是只为当前情况考虑的三倍。(参见《人月神话》)「考虑今后的重用」只能靠猜,一般都是错的。
读代码比写代码难,所以那些「只为当前情况考虑的」代码很少在问题稍稍发生变化的时候被改写成更通用的代码。补充一下,原来的第三条写的太简短。第三条虽然再说一个困难的现状,但是它也同时说明这是正确的重用方式。就是每次写代码的时候,只为当前情况考虑。准确的说是只为迄今为止遇到过的情况考虑。这样一份代码会经历从专用到通用的过程。但是这个过程也是非常困难的。
全部0条评论
快来发表一下你的评论吧 !