注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

埖堓

 
 
 

日志

 
 
关于我

雨落风尽花红, 太匆匆, 路几重, 一夜春来秋去晚来风。 月色朦, 云雾胧, 清华过尽逍遥醉苍穹。 人生路, 视不同, 自是如水若空怎能懂? 江湖泪, 是与非, 爱恨情仇流去几个冬。

沈阳华威天下科技有限公司分析代码重用问题解决一次可以吗?  

2017-03-03 10:43:05|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

刚学编程的那会有种想法认为难题应该只解决一次。

但渐渐接触多了前端开发经常要重复编写代码,特别是生成页面时更是这样

是什么导致了代码无法重用呢?

sapjax

为什么要经常要重复编写代码呢?问题本身并不是同一个问题了,如果是同一个问题即使不做抽象CTRL+C/CTRL+V大法就解决了。

 

举前端的例子来说,如果在同样的基础库/框架下一个UI控件的外观和交互都一致的情况下代码就可以直接拿来复用。业务逻辑的模块也同理假设业务逻辑真的一致直接copy过来也未尝不可。

 

试想一下假设你们前端团队决定使用Bootstrap或者Semantic UI作为UI库,你们说服了产品经理和设计师都去阅读了Bootstrap/Semantic UI的文档,做出来的原型和视觉稿都是基于UI库已有的规范和控件,那么到了前端这里在UI实现的工作上就变成了简单的拼装组合,并不需要重复去写UI控件的样式和交互这将是多么和谐的一幅画面...

 

退一步说产品经理和设计师都是有追求的,不甘于拿来和定制别人的东西要做出自己风格化的设计,前端基于这些设计提取出一套类似BootStrap/Semantic UI的库供自己内部使用,后续有类似的需求,同样是简单的拼装组合能做到这一步也是极好的。

 

然后实际中情况是这样的产品经理和设计师大多数并不知道重用是什么概念,原型和视觉元素大多数时候都随意发挥,是拍脑拍出来的灵感集合也从来没有一套设计规范,同一个元素出现十个地方就有可能有八种变形交互规则也是千奇百怪。在这种情况下前端要提取出通用元素实现一套UI库就变成了不可能的任务。

 

复用这个观念不仅仅是程序猿要思考的更是产品经理和设计师需要注意的,如果他们给的东西本来就不具有复用性程序猿自然要经常要重复编写代码了。如果在原型和设计层面就已经抽象得很好了开发的工作就会变得很简单,蚂蚁金服的ant.design 就很明白所以他们叫做一个UI设计语言

 

那么问题就明显了是什么阻碍了代码的重用?是设计狗和产品汪啊!

因为复用并非无代价而且代价往往还很高。

 

从工程上说任何特性都可能是有代价的。复用提供了解决一类问题的灵活性而灵活性作为一种功能同样有代价——正如过多地使用虚函数有性能损失,而过多地使用 interface 则一定程度上降低代码可读性。如果构建灵活性的基石皆有代价那么我们不可能期望灵活性可以免费获得。而所有的问题解决之道本质上都一样:我们需要权衡每一个选择的好处和坏处做出对我们现在的项目最有利的方案。举例来说我们不会在项目最紧张的时候讨论把业务逻辑抽取出来做一个通用的框架,原因很简单时间不够用。我们也不会在讨论怎么设计通用框架的时候过多地讨论我们具体项目的逻辑,因为追求通用性的设计目的导致不可能完全为某一个具体的业务优化。

 

所以从这个意义上来说阻碍代码重用的最大原因,事实上来自项目自身:复用代码在绝大多数情况下都不是一个项目的最终目的。对任何项目来说唯一绝对存在的目的是在指定的时间内完成客户给出的需求。当短期内完成功能的需求和复用发生冲突时理智的项目管理者都不会选择将注意力放在复用上。当然热衷于复用的程序猿必然会以长远的好处为理由为复用辩护;但正如前面的规则指出的这依然是一个工程上的选择问题因而仍然需要折衷。在遇到问题时总是先倒向某一个结果再试图解释这不是折衷,而是预设立场这恰恰是工程的大忌。

 

至于第二个问题回答是:是的对任何问题只解决一次是理想状态,但重复解决三到五次问题并非十恶不赦。客户关心的是我们能不能解决问题,而不是能不能对任何问题都只解决一次。——不要把自己的需求误以为是用户的需求这仍然是一个工程问题。

 

过早优化是万恶之源。

编写代码时,对可复用扩展性的考虑,都应限定在一个很小的范围内。否则的话,在当前版本多消耗的时间要远远大于未来复用代码时省下的时间。

 

编程艺术的角度来讲,这种解决方法一点都不漂亮。每个人初学开发时都会有这种想法:要完美、要考虑周全、为了不存在的需求而编写一堆预备代码。但是,在经历过几个项目后总结一下,就会发现这种事是多么浪费时间和精力,当初预想的需求90%没有出现,出现的那部分也和设想大相径庭了。

1、编写代码时,如果考虑今后的重用工作量一般是只为当前情况考虑的三倍。(参见《人月神话》)

 

2、「考虑今后的重用」只能靠猜一般都是错的。

 

3、读代码比写代码难,所以那些「只为当前情况考虑的」代码很少在问题稍稍发生变化的时候被改写成更通用的代码。


补充一下原来的第三条写的太简短。第三条虽然再说一个困难的现状,但是它也同时说明这是正确的重用方式。就是每次写代码的时候,只为当前情况考虑。准确的说是只为迄今为止遇到过的情况考虑。这样一份代码会经历从专用到通用的过程。但是这个过程也是非常困难的。

 

作为曾经对复用问题非常关心的前软件行业从业人员把知乎的第一答献给这个问题。

 

我相信许多对复用抱怨的人可能了误解的复用的含义。而那些强调局限性和折中的人很可能本身已经拥有良好的复用功底,因此对他们来说复用的程度更多取决于现实需要。因此这个问题对于开发老手来说或许不值一提对于新人来说,却绝对重要,它在某种程度上决定了你作为一个程序猿所能到达的技术高度。

 

直截了当的回答在我看来阻碍复用的因素只有一个:开发者自己。具体的说是开发者自己的习惯、思维方式和经验。软件设计是一项思维工作工作的一个重点就是描述流程和划分模块。划分模块的目的除了逻辑清晰化和便于分工之外最重要的就是复用。只有把一大堆功能拆分成若干相对独立的小功能才方便我们把小功能封装起来,随时随地被其它功能(模块)反复使用(调用)这本身就是复用。

从最原始的程序块上升到函数、类乃至设计模式和架构是对程序功能一步步抽象和灵活描述的过程也是提高复用性的过程。为什么我们需要架构师?就是因为架构师能够对整个程序以及程序可能发生的变化做一概括性的描述,在此描述之内可容纳程序所需的所有具体功能,并可对功能变化表现出适当的容忍性、灵活性和可扩展性。如果不考虑复用功能稍有变化就要修改或复制大量代码,我们要灵活性和可扩展性有何用?要架构和架构师又有何用?

 

或许有人会说我们开发的程序很小,根本不需要架构师对复用没有那么高的要求尽快满足客户的要求就好。这个说法的逻辑,如同磨刀一定会误了砍柴功一样,正确但不合理。我见过泾渭分明的两类程序猿同样从几乎完全没有经验的应届毕业生开始,一类天天忙的喘不过气来成果却不多。另外一类却越做越轻松进而经常帮助别人解决问题。除了努力程度之外,是否具有抽象、复用的思维(当然这也可以归结为悟性)是他们在开发能力上的一大分野。

 

相信大家见过这样的优秀程序猿从一个项目转战到另外一个项目时优秀从一种语言转战到另外一个语言的时候依然优秀,甚至从一个领域转战到另外一个领域时还是优秀。尽管这种优秀是相对的,但是主要原因在于他能把一个项目、语言、领域的经验复用到另外一个。这是更高层次的复用,而其基础依然来源于软件开发时复用思维的培养与实践经验。

 

那么具体来说开发者自己的习惯、思维方式和经验是如何阻碍复用的呢?首先如果一个开发者在编码之前根本不做任何程序设计方面的工作,一接到任务就开始埋头于功能的实现那么别指望他的代码能有什么复用性也别指望他能培养起什么复用的思维;其次如果一个开发者不经常寻找相似模块之间的共性不打算让自己的模块体现出更强的灵活性,他就没有复用能力也无法建立复用的思维;最后如果一个开发者没有足够的经验,他也很难确定复用的边界很有可能引发过度设计或者放弃复用。

 

因此作为开发者抱怨用户是没有用的,抱怨需求分析师、项目经理或者架构师也是没有用的,交给你的模块在你手中它的复用性只取决于你,你想让它复用性高一点那就花点心思去分析和设计。如果你要偷懒那也随你只是不要把接口放在别人身上。如果你说你的工作实在太多了,根本没有时间考虑这方面的问题那我除了对你报以深深的同情之外,只能说一句:同学身体和职业前途为重。

 

那么如何培养程序猿的复用思维?就我的经验而言:

首先是严禁复制代码绝不允许同一个项目或产品的成员复制其它成员(包括自己)的代码直接插入自己的程序,复制已有代码的愿望说明代码上有较大重复已经构成了复用的条件在时间允许的情况下,应该要求原开发人对代码进行封装,然后由你来调用。如果时间上来不及,最低限度的折中也是你把这段代码复制过来之后进行分装然后调用;

 

其次是对设计过程的强调,新人在开发前一定要有老手带他进行程序设计和后期的代码审核,这会花费老手的时间,但是回报绝对值得设计过程培养的不仅仅是新手的复用思维,而是软件开发的基本功,这个基本功与对语言的熟悉程度和项目经验具有同等价值长期看甚至过之;

 

最后是适当的交流与指导实际上,复用问题是新人最容易遇到的第一个显著成长瓶颈有经验的管理者或者同事很容易发现,在对开发语言和项目逐步熟悉之后,编码成为最不费脑子的工作,而如何避免让自己成为体力劳动者或者说如何让自己的每一次劳动成果都获得尽量多的后续应用即复用开始检验新人的悟性。有悟性的人会自己琢磨、学习、尝试解决没有悟性的人就开始苦恼。这个时候就到了指导他们重温面向对象的设计、设计模式等知识的时间了,从这些老生常谈的知识结合具体的项目实践,所能挖掘出来的复用思维和技术可能超乎大部分计算机专业毕业生的想象。

 

事实上为了解决复用设计问题曾经为公司的新人专门开过一门夜校课程,名字就叫软件复用。我向他们解释软件复用的极端重要意义过程很简单,列出了某开源PHP框架对于MVC架构实现的核心代码,解释了短短几行代码所体现的多种设计模式与巨大灵活性。所有人都震惊了许多人开始意识到编程并不是写代码,更是一种逻辑思维,如果把编程只局限于写代码的水平那么码农的称谓当之无愧。而在这种逻辑思维中抽象能力是核心也是复用的基础。

通过大约10多个小时的夜校课程,我很难说显著的提高了他们的水平,但有一点值得欣慰:就是大多数人都接受了高内聚、低耦合的思想。众所周知高内聚、低耦合只是模块划分的核心原则,但真正掌握了这个,就基本上迈进了软件复用的门槛剩下的是实践和提高问题。

 

上面是从培养的角度来说。对于程序猿新人的自我学习,如何提高复用水平答案也很简单:思考、抽象与重构。首先思考模块划分问题怎么划分才能尽可能的保证模块的独立性和灵活性其次寻找相似模块之间的共性,如果找不到说明抽象程度不够,再往上抽象;最后舍得花时间重构代码。我完全同意前面大部分人所说的同样代码写到第三遍就会恶心的观点。如果你有时间写三遍却没有时间重构后,让它被调用两遍真的很难说到底是偷懒还是过于勤快。

 

当然复用总是有边界的开发过程中总会遇到复用所带来的复杂性与时间和代码可读性之间的冲突。这个时候发挥作用的是经验,这个经验既包括复用技术方面的经验也包括用户需求方面的经验都需要积累。但是这个冲突不应成为阻碍复用设计的借口复用首先应该是渗透入程序猿血液中的思想,否则前人所作的一切工作你自己完成的所有任务理论界、技术界大牛所提供给你的一切工具、模式都是白费。在拥有这个思想积累的一定的经验之后,你再说:在这个功能点或项目中复用考虑的不够;或者在那个功能点或项目中过多考虑复用并不合适;因为blablabla……

 

恭喜你这个时候你已经是一个合格的程序猿了。

 

因为在我看来,复用从来没有该不该的问题只有够不够和多不多的问题。

 

PS1. 以上所提新人均为普通大学(包括本科、专科和中专)毕业生天才不在此列;

 

PS2. 本人并非高水平程序猿,只是在培养新人方面有一些心得和体会,如答案不靠谱请直接点击没有帮助,但是千万不要让我背上误人子弟的骂名切记切记。

  评论这张
 
阅读(4)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018