2019独角兽企业重金招聘Python工程师标准>>>

以下是我在工作过程中思考得到的一点感悟,相信我,遵循下面的原则,生活会更加的美好。星爷不是说:

只要能好一点点,那就要好一点点

好了,废话到此结束,写起:

一、无重复

在保证代码整洁的基础上,<strong>无重复</strong>是好代码追求的首要目标。因为<strong>无重复实在是太重要了</strong> ,如果整篇文章的内容你只能记住几个字,那就该是:无重复。好了,在你脑袋被我弄傻之前,让我们来讲讲为啥要做到无重复。

你一定见过这样的场景:

某个程序员要做一个功能,于是他先找到类似的代码贴过来,再根据自己的理解进行修改,改完运行一遍,看看结果
恩,不错,搞定~~

我不得不说:在我刚刚工作的时候,有那么两个月也是这么来干的。

这种拷贝粘贴的做法,唯一的好处是:如果你处于新手阶段,当你面对一个具体的功能A,即使你没有完整的思路,也可以通过分析A与其它类似业务的差异性,屏蔽相同或者相似部分,通过试错只对有差异部分做修改就能快速完成任务。粘贴拷贝,真乃神器,真乃福音。

<strong>但请记住,就是拷贝粘贴导致“重复代码”大量的出现</strong>。

虽然看起来好处不小,但它的好处就如同晨露一般短暂,而它带来的副作用却往往是长远和灾难性的。

这绝不是危言耸听:

在我曾经经历过一个项目中,报表模块由于设计上的失误,我所负责的地方,有二十多份相似的拷贝,每一个拷贝负责一张报表的功能。这些拷贝们业务逻辑大量重复,只在少数参数和输出图形形式(饼图或者柱状图或者曲线)上存在差异。试想如果每份代码只是编写完成就不需要修改还好,但是需求嘛,你们懂得,变化总是来得那么猛烈,我需要频繁的修改二十多份不同的拷贝,并且拷贝的数量还在成上升趋势,这导致了什么呢?即使像改变初始值这种微不足道的修改,我都需要十分钟甚至更久来维护二十多份重复的代码,毕竟人不是机器,总是难免漏掉那个几个忘了修改,于是不一致性表现了出来,bug从天而降---我要花上拷贝一千倍的时间来断点调试debug,并且经常性的发生失误(改错拷贝了,把对的改错了)同时忍受着测试“大妈”说:“怎么又错了,刚刚不是好好的?”苦逼二字用来形容此刻的心情真是太TMD合适了。

很快我变得筋疲力尽,我厌恶甚至是憎恨这些重复的代码,他们让那种简单分析一下就能定位错误的美好愿景变得无从谈起~这种痛苦,只可意会,这种经历,终身难忘……

很好,你现在和我一样厌倦了重复,那么该怎么干呢?

相同的逻辑永远在上层,而差异散列在下层

上层代码并不局限于父类,它也可以是模板模式中的模板类等等,记住不要局限于任何形式化的方法,灵活一点,只要你想到一种方式可以避免重复,那就是ok的。

无重复,之所以重要不仅因为它可以解放我们,还有一个更重要的原因:它可以升华我们。

为了做到无重复,你要努力的从纷繁复杂的表象中抽象出相同的逻辑,这种能力是所有OO设计的能力的基础,你所有的设计手段将源自于此。做到无重复,是成为高手的敲门砖。

好了,这就是我要说的第一点:无重复。我相信肯定很多人仍然是这么干的,但是请不要灰心,这对一个新手是必须经历的过程,努力跳出来,好日子等着你。

如果你还感兴趣,山治说:第二道菜来了。

二、职责单一

所谓 <strong>职责单一</strong> 包含三个指标:

  1. 是指程序中每个子系统、模块、包甚至是类所提供的服务都应在逻辑上具有很强的内聚性,他们只应服务于一个或者一类任务。

  2. 每个类或者模块都应该尽量独立的完成自己的功能,即不依赖于其它平行逻辑也可以做好自己的工作。

  3. 尽量和具体的业务隔离开(除了必须了解的那部分业务除外),切记逻辑上不相干的东西千万不要丢进来。

做到这些有很多好处,如果你面对的是一个按照这种原则来设计的系统,那么无论是在编写新功能还是优化旧有的代码,你的所有注意力都集中在这一个类或者包中,没有无关的东西来扰乱你的思考,你所有的注意力都集中在相关性上,其它的任何无关业务、逻辑都不入你的法眼,你会发现很容易保持一个干净的大脑环境,灵台清明,自然效率高高。

其次,由于模块的职责非常单一(很少甚至不关心平行模块的细节),类之间的相互依赖因而被弱化,模块的功能显得内聚和完整,代码重用神马的真是水到渠成……

还有另外一个好处,因为独立了、单一了、耦合降低了,你会有更大的自主权来进行合理的封装,你完全可以决定你的模块提供哪些服务,良好的api设计因而成为了可能。

觉得有道理?第三点来了。

三、尽量的封装细节

为何要 <strong>封装细节</strong> ?我们都知道代码一旦写出来,是要被其它人阅读或者作为代码基来使用的,而使用者首先需要了解你的代码,那他们会如何做呢?最直接的办法是浏览一遍你的包开放了哪些类,还有你的类放开了哪些方法。

因此,你的代码所暴露出来的细节越少,别人就越容易找到重点,也就是说,你的api设计的也越好用。

下面是我在 <a href="http://dtubest.github.com/Razor/">Razor</a> 中对参数绑定的设计:

这个包中,所有的类都服务于参数绑定这个任务(职责单一原则),用来辅助从request中取出各种类型的参数。

它们可以应用于各种不同的参数类型的场景,但整个包只对外暴露了Binder一个类,其它所有的类都是包访问权限的,也就是说在包外,是不可见的,仅仅被限制在包的作用域里面来完成逻辑的细分, 而对外,你只要知道我这个Binder可以完成各种类型的参数绑定,怎么做的,you don't care!

相比于要你来区分场景然后选择合适的类,是不是一个简单的通用的方式适用与多个场景更加简单,更容易理解,这就是封装的力量。

ps:这个参数绑定模块的设计将处理不同类型的细节隐藏起来(封装细节原则),重复的逻辑全部放到了Binder中(无重复原则),只服务于参数绑定(职责单一原则),因为遵循了这些原则,他们很容易被移植到完全不同的场景中。具体的代码:<a href="https://github.com/dtubest/Razor/tree/master/src/main/java/com/me/web/servlet/binding">看这</a>

看到这里还有兴趣,很好。来接着看。

四、依赖简单化

先解释一下什么是 <strong>依赖简单化</strong> :

// 只是个示例, 请不要苛求语法细节
class Target {public String getProperty(){}
}class B {public void logic(Target target) {String tempVariable = target.getProperty();}
}class C {public void logic(String target) {String tempVariable = target;}
}class Main {main() {Target target = new Target();B b = new B();C c = new C();b.logic(a);c.logic(target.getProperty());}
}

我们可以看到,B、C都依赖于目标对象Target的一个状态属性,但是我们说C的依赖更加的简单,先别问为什么,来看另外一个单元测试的例子:

// 同样不要关注细节,我希望只传达了重点所在
void unitTestForB() {Target target = new Target();B b = new B();assertThat( b.logic(target), "expected result");
}void unitTestForC() {C c = new C();assertThat( c.logic("target value"), "expected result");
}

貌似还没有看出什么区别是吧?别急,一步步来,现在我们假设Target是这个样子的:

class Target {// constructorTarget(Another1 a) {}
}class Another1 {// constructorAnother1(Another2 a) {}
}class Another2 {// constructorAnother2(Another3 a) {}
}class Another3 {// constructorAnother3(Another4 a) {}
}class Another4 {// constructorAnother4(Another5 a) {}
}class Another5 {// constructorAnother5(Another6 a) {
}
.....

现在你要怎样去测试类B呢?你突然发现测试真不是个好东西,因为测试本身开始变得比你要测试的对象还要复杂,你无法初始化你要测试的对象或者其他依赖,因为为测试准备的站桩太复杂了。

其实只要你把类写成类C那个样子将依赖解开,什么问题都没了。

也许有的人会说我可以mock啊,但是mock相比于依赖简单化,真的是更加优选的方式么,我想你有你自己的答案。

其实除了测试,在所有的业务代码中,简单化依赖后也是好处多多,试想一下,如果要从一个深层次的依赖中去挖出缺陷该有多么痛苦,如果你能解开类之间的复杂依赖,缺陷自然无出藏身。

好了,依赖简单化是原则,解依赖是手段。

接下来让我们来谈谈setter。

五、不要用setter来进行初始化

在具体开始之前,先来说说什么是一个好类,什么是一个坏类,还有不及格类:

我们知道,很多类都需要在投入使用之前进行初始化,他们的工作机制严重的依赖于初始化的情况。在初始化正确的基础上,好类和坏类都可以正常工作,而那些不能好好工作的,我认为它是不及格的。再来看,没有正确初始化的基础上,好类通常严重抗议(自举抛异常,或者有良好的默认设置),坏类则偷偷接受(默不作声,心思邪恶),不及格类嘛~~直接忽略。

好了,言归正传,setter方法其实从来都不是问题的根源所在,她是一个好姑娘,她们通常用在改变类的状态上,非常ok没任何问题,可是他们还可以用在初始化类的状态上,碰到一个好类,没有问题。要是碰到居心叵测的坏类,噩梦就开始了(想象力在哪?):

我们直接来看最糟糕的情况(setter碰上坏类 == 好姑娘碰上怀牛氓):

试想在你的某一个程序中使用了一个坏类,你用好姑娘来初始化它,好姑娘虽好,但你很粗心,你忘了初始化几个重要的属性,坏牛氓看在眼里,偷偷诡笑,默不作声,它不抛出异常,没有error也没有warn,只会得到和预期不同的结果。在这种情况下,你会被程序不报任何异常,却不正确工作的诡异行为搞的晕头转向,怀牛氓不时瞎搞,各种临界问题不断出现,而由于坏牛氓偷偷隐瞒了问题所在,你完全无法定位问题出在哪里,怀牛氓如同鬼魅幽灵潜伏在你的code中,杀机四起。这时候,如果你同时没有布下单元测试这张天罗地网来捕获他们的话,那你就准备大巴的时间来debug吧……

这些个畸形的、没有正确初始化的、又不自举的坏类的对象,我把它称之为 <strong>魔化对象</strong>

setter本无罪,只是如果使用setter方法来初始化坏类,会容易导致问题的出现,坏类却偏偏又无法杜绝,因为有时候他是来自其他的类库(例如讨厌的commons-net),那如何解决这个问题呢?

孙猴子其实也是一个坏类,想想孙猴子是如何老老实实跟唐三儿去打下手的吧,唐三儿有温柔劝服嘛,NO,他用了紧箍咒,要踏上征程先带上紧箍咒,否则免谈。

聪明的你也许你已经想到了,那就是“构造方法”,一个类的旅程必须从这里开始,我们将初始化集中到构造方法中,每个从构造方法中构造出来的类都是ok的,这就避免了setter初始化中出现的所有问题(粗心、错误、遗漏、初始顺序)。对于其他你没办法改变的类,你也可以通过再包装一层来使用。

最后,写在最后

好不容易写到这里,差不多该结束这篇文章了,如果你有耐心看到这里还能记得前面,或者觉得津津有味,那真是太好了,可是我不好,我要吐了,写得好累,哈哈~——~或许这些东西你从没听过,或许你已经烂熟于心,有则改之,无则加勉吧。小弟水平有限,只能抛砖引玉,大侠们保持队形……

一点小小感悟,希望能听到大家不同的声音,如果大家捧场,以后再来个续集吧

转载于:https://my.oschina.net/dtkking/blog/113541

一点coding的心得相关推荐

  1. 关于搭建视频直播运营平台的一点经验和心得

    视频直播,目前在各行各业得到了广泛的应用.那么该如何搭建一个自己的直播运营平台?需要投入多大的财力和物力呢? 下面根据我个人的从业经验讲一下,不具有绝对的权威性,但是都是经验的总结,希望和大家一起学习 ...

  2. 关于一点coding.net与git配合在AndroidStudio/Idea上的使用笔记个的

    编写程序的我们经常需要对我们写的代码做版本控制,或者分支管理,具备类似功能的软件很多,诸如SVN,Git,CVS等等!但配置版本控制服务器(SVN server etc.)是繁琐的并且需要一定的成本! ...

  3. 关于xs128单片机的一点小小学习心得--认识xs128

    XS128单片机简介** MC9S12XS128是Freescale公司的16位单片机,由16位中央处理单元(CPU12X).128KB程序Flash(P-lash).8KB RAM.8KB数据Fla ...

  4. 前端优化常用技术心得

    从建立http连接开始,到页面展示到浏览器里,经历了加载.执行.渲染,重构的几个阶段.将分享下我自己的心得和其他人的优秀经验. 加载和执行 浏览器是友善的客户端,对同域名并发请求是有数量限制,过去浏览 ...

  5. 12届毕业生回顾我的2012年,给2013届同学一点启迪

    我是2012年6月毕业的大专生,现在天津搞Java web开发,这篇文章将会详细得记录我从2012年初找工作到如今辞职的详细历程,因为时间贯穿求职.实习.毕业.工作.辞职几个关键阶段,希望我的经历能给 ...

  6. HTML项目心得500字,心得体会作文500字(精选10篇)

    心得体会作文500字(精选10篇) 我们得到了一些心得体会以后,不妨将其写成一篇心得体会,让自己铭记于心,这样可以帮助我们总结以往思想.工作和学习.那么如何写心得体会才能更有感染力呢?下面是小编为大家 ...

  7. 看过的最好的护肤心得

    第一次看到这贴是在瑞丽,今天在花窝又见,真的太强了,转来和大家分享 草草是80年年中的,19岁开始护肤,算算真的有6年了.老爸老妈皮肤一般,草草应该是没有所谓的天生丽质的基因,曾有过两个极端的错误护肤 ...

  8. ACM本周搜索做题小结和心得体会

    这周除了接着看上次没看完剩下的题,主要的就是做题了 我把这周新学到的和以前还没总结过的以及做题心得再主要说一下 这周做题和看到的主要是以下这几类 我把这周做题时遇到的某几类题简单归了一下类然后总结 遍 ...

  9. 结对第2次作业——WordCount进阶需求

    软工实践第五次作业 写在前面 本次作业题目链接 本次作业Github仓库链接 031602237吴杰婷博客链接 031602636许舒玲博客链接 具体分工 两个人一起在实验室完成的,有什么问题都当面沟 ...

最新文章

  1. Vue安装支持SCSS插件
  2. Amber计算MM能量
  3. 2016视觉目标跟踪总结
  4. JavaWeb总结(九)
  5. LCS最长公共子序列
  6. mysql safe无法启动_(转)mysqld_safe无法启动的解决办法
  7. LintCode解题目录
  8. matplotlib数据可视化实战——折线图+散点图
  9. 影视链进入区块链应用时代大潮 展现影视新巅峰
  10. AD7705在STM32F103RBT6上的移植[硬件SPI]
  11. (Research)泛癌单细胞分析揭示肿瘤微环境中癌相关成纤维细胞的异质性和可塑性
  12. 04---项目后端业务实现
  13. 以教育行业为例,教产品经理如何做行业分析
  14. android 置灰不可点击,Android全局实现控件变灰
  15. 如何根据移动端设计图设计rem比例
  16. 嵌入式硬件 软件测试,嵌入式系统软硬件功能测试方法及性能评估研究
  17. mysql 二进制分发版_安置MySQL二进制代码分发
  18. 【随便聊聊】Mac 笔记本该怎么选?
  19. war包和jar包的区别
  20. Windows设备管理器中的错误代码

热门文章

  1. [附源码]计算机毕业设计springboot云南美食管理系统
  2. Java字符串常见拼接方式
  3. 纯前端js(或者vue)导出excel实现:合并单元格、设置单元格样式、单元格内换行
  4. 前端点击移动生成小爱心
  5. FIDO框架分析2(FIDO UAF服务器)
  6. 转型Web前端需要学什么?如何提升Web前端技能?
  7. 办公小技巧4:一定要学会的Word分栏打印,方便阅览又省纸张
  8. 百度飞桨:春节写春联:你写上联,AI写下联
  9. 一篇让你彻底了解DNS原理及其解析过程
  10. 与编程无关,与生活相关