OOBootcamp 回顾与总结

OOBootcamp,全称是Object-oriented Bootcamp,就是面向对象训练营的意思,在12月份和1月份,我们整个项目组一些senior一些的同事一起接受了OOBootcamp的培训,有这个培训呢,还多亏了训杰找骏总争取到了这个机会,Tech leader做得好,关心组员的技术成长,哈哈。讲师是袁慎建老师,intellij 的快捷键玩的出神入化,技术实力没得说,又会说话还又会写文章,关键是人还长得特别帅,这就让人有点嫉妒了,附上他的简书地址,欢迎大家前去骚扰. 😊

前些天这次OOBootcamp圆满结束,完结撒花🎉。领到了一张小奖状


image.png

当然还有一些附带的训战计划,是需要在实际项目中去落实所学到的知识。所以之后还会有一些在实际项目中实践这次学到的知识之后的感悟,好,废话不多说了,下面就来回顾总结一下这次的OOBootcamp.

这次OOBootcamp, 主要分了三大块的内容,一个是SOLID原则, Simple Design原则,贫血充血模型,二是TDD, 三是重构,主要用了Parking Lot 这个编程实例来给我们做练习,学以致用,先用例子实现一遍,再之后在真实项目中再操练一遍,几板斧下来,保准你映像深刻,又有自己的体悟。

SOLID 原则 (面向对象的基石)

SOLID原则,我自己就不多现丑了,附上一篇袁老师的博文,供大家参考,虽然主要讲的是里氏替换原则,但是其他原则附带也有讲,网上一搜索也是一大把。我下面就讲一下我在OOBootcamp结束后对SOLID原则的理解,就不会讲很多细节了。

先复制一波袁老师的一段文字😊
SOLID由五大原则构成:

  1. Single Responsibility Principle【单一职责原则】
  2. Open Close Principle【开闭原则】
  3. Liskov Substitution Principle【里氏替换原则】
  4. Interface Segregation Principle【接口隔离原则】
  5. Dependency Inversion Principle【依赖倒置原则】
    并且请记住一句话,所有的原则其实都是为开闭原则服务的

注:袁老师说,你们知道了这几个原则后,就把它忘掉,不过,我可能还没到这种无招胜有招的境界,所以需要详细记录一下😊

1. 单一职责原则

我理解的单一职责原则很简单, 就是一个类,或者一个方法,它就只做一件事情,当然这句话说了等于没说,你可能会说我知道单一职责是什么意思,但还是不会啊。对,我也不会,没人敢说他会。因为单一职责的难点就在于这个一件事,到底是怎么个一件事,或者说怎么分。大到组装一台车,小到造一个螺丝钉,它都是一件事。怎么分?

其实这是一个很难的问题,这个问题是没有一个标准的答案的,它跟你的业务相关,跟你具体的实践相关。不是一个精准的度量而是一个感官度量。唯有以面向对象的方式多多练习,才能找到那个感觉。以我的感受来说,当你觉得你找出的那一件事情,分无可分,不存在二义性,那么我认为这就是单一职责的一件事。

2. 开闭原则

开闭原则的定义是对扩展开放,对修改关闭。这个真的咋一看云里雾里,要理解这个原则,我觉得我们首先得把这句话的作用域缩小一点,就针对java 面向对象来说,其实应该说的是,扩展功能可以增加新的类,但应该尽量避免修改已有的类。其实还是有点不好理解哈,也不知道怎么做,我觉得这时候可以去看下设计模式,全部的设计模式都遵循了开闭原则,简直是最好的开闭原则示范。

3. 里氏替换原则

墙裂推荐袁老师的这篇博文 让里氏替换原则为你效力,写得很好,简直写到我心坎里去了。

我这里就只说说里氏替换原则的定义,任何基类可以出现的地方,子类一定可以出现,如果你覆写了父类的方法,那么其实你是违背里氏替换原则的。至于为什么,都在袁老师的博文里,欢迎大家去围观,哈哈。

4. 接口隔离原则

接口隔离原则的定义是 客户端不应该依赖它不需要的接口;类间的依赖关系应该建立在最小的接口上
这个原则,看定义就很好理解了,其实我认为它是对单一职责的一种补充,因为如果你单一职责做的非常好,那么你其实会很少碰到违背接口隔离的情况的,反之,如果真的出现了,那么一定是你单一职责做的还是不够好。

5. 依赖倒置原则

这个原则的定义 是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了耦合

这个其实也是有点绕的,面向抽象编程怎么就降低了耦合呢?其实我觉得还是很好理解的,比如你吃一个苹果,如果写实现,你写一个苹果类就完事儿了,但是如果面向抽象你需要定义一个苹果接口,然后我吃这个接口就好,不关心是什么苹果,然后再写苹果的实现,但是后面还有需求,说要吃一个美国的苹果,因为美国苹果又大又圆,面向实现的做法是,我改一下我的那个苹果类改成美国苹果就完了,面向抽象的做法是,我在写一个类,美国苹果类实现苹果接口,其实对比两种方式,你就能知道谁好谁坏。

Simple Design(简单设计)

简单设计原则 我还是推荐大家去读袁老师的文章 简单设计落地三板斧 其中链接了 简单设计的价值观简单设计原则,哈哈,都是他写的,十分高产。

简单设计原则在我看来核心就是 保持简单。对于程序开发来说,就是保持程序简单,不要去过度设计,我们写程序的时候常常会不由自主的为未来去考虑,比如一个好的程序员,他会有这样个习惯,他不会单单只完成自己手上的工作,他会去思考未来会有什么需求进来,于是这些思考会常常体现在代码上,形成过度设计。而如果你认同敏捷价值观,那么这其实并不是一个好的习惯,因为你思考的需求,其实有时候并不会实际产生,于是代码凭空复杂了很多,并且有一部分还是无用代码。

Simple Design 就是需要你去认同这样的价值观 保持程序简单,不要过度设计,你的程序实现应该是刚刚好满足你现有的需求的。

那么怎么去落地Simple Design呢?请看袁老师讲的Simple Design落地三板斧。TDD, 重构,clean code, 哈哈
培训的时候映像比较深的是这样一幅图


img

这个是说的在实践简单设计过程中,当面临冲突时,我们如何取舍,最重要的是通过所有测试,其次是消除重复和解释意图,优先级最低的是减少元素,当有冲突时,优先级越高的我们越应该关注。

贫血充血模型

期间由训杰给我们分享了贫血和充血模型,现在一般Java 项目多数都会采用spring全家桶,而spring所推崇的mvc结构是一种典型的贫血模型,于是迅杰给我们分享了贫血模型和充血模型的区别(好处和坏处),以及充血模型的架构应该是怎么样的

不了解贫血模型和充血模型的, 可以看看这篇文章 贫血模型与充血模型的对比

以下是摘抄自上面那篇文章

贫血模型的好处是:
1、每个贫血对象职责单一,所以模块解藕程度很高,有利于错误的隔离。
2、非常重要的是,这种模型非常适合于软件外包和大规模软件团队的协作。每个编程个体只需要负责单一职责的小对象模块编写,不会互相影响。

贫血模型的坏处是:
1、由于对象状态和行为分离,所以一个完整的业务逻辑的描述不能够在一个类当中完成,而是一组互相协作的类共同完成的。因此可复用的颗粒度比较 小,代码量膨胀的很厉害,最重要的是业务逻辑的描述能力比较差,一个稍微复杂的业务逻辑,就需要太多类和太多代码去表达(针对我们假定的这个简单的工时管 理系统的业务逻辑实现,ruby使用了50行代码,但Java至少要上千行代码)。
2、对象协作依赖于外部容器的组装,因此裸写代码是不可能的了,必须借助于外部的IoC容器。

对于Ruby来说,更加适合充血模型。因为ruby语言的表达能力非常强大,现在用ruby做企业应用的DSL是一个很热门的领域,DSL说白了就是用来描述某个行业业务逻辑的专用语言。

充血模型的好处是:
1、对象自洽程度很高,表达能力很强,因此非常适合于复杂的企业业务逻辑的实现,以及可复用程度比较高。
2、不必依赖外部容器的组装,所以RoR没有IoC的概念。

充血模型的坏处是:
1、对象高度自洽的结果是不利于大规模团队分工协作。一个编程个体至少要完成一个完整业务逻辑的功能。对于单个完整业务逻辑,无法再细分下去了。
2、随着业务逻辑的变动,领域模型可能会处于比较频繁的变动状态中,领域模型不够稳定也会带来web层代码频繁变动。

TDD

上面的理论讲完了之后,就是实践了,用TDD 这个工具来实现一个比较经典的题目ParkingLot Management,在回顾TDD之前我要先回顾一下Tasking 思维管理工具

Tasking

Tasking 是一种思维管理工具, 它要求你对于一个比较复杂的问题,列出它的每一个完整子路径,这样进行Task分解之后,复杂的问题就变成了一个个简单的容易实现的子问题了

Tasking 的经典格式是 Given When Then 格式,一个典型停车小弟的需求Tasking分解的例子是

Given: 我管理一个停车场,停车场有空位
When: 用户委托我停一辆车
Then: 停车成功

可以看到,Tasking要求你分解出的Task要尽量的简单并且可测试

一个错误的例子是

Given: 我管理N个停车场,停车场N个空位
When: 用户委托我停N辆车
Then: 停车成功

这个Task其实是很难去测试的,N是多少?测试里面你难道要穷举吗?怎么穷举?

TDD

TDD 测试驱动开发,是极限编程列出的12个团队实践之一,是其中重要的组成部分,TDD的具体理论和一些实践,在网上都有,我这里只讲我练写TDD的感受,首先 TDD 是一个工具,是工具就有适用场景的,也就是说,不是所有的软件开发过程都适合使用TDD,其次它是由三个单词组成

  1. Task Driven Development
  2. Test Driven Development
  3. Test Driven Design

三个词中都出现了Driven,所以,TDD的核心其实是那三个D, 而且从2,3两个词可以看出,TDD是必须Test First的

其实在课程开始之前,我对TDD的理解很粗浅,仅仅限于先写测试后写实现(当然,其实这样理解也没什么毛病),在实践中也几乎没有去实践,我们总是习惯于先写实现,写完之后再回过头来补测试. 其实有时候就会有一种想法,觉得测试是一个可有可无的东西,你写了更好,没写程序也不会出啥大的问题。就像是客户要求我们测试覆盖率90%以上,写测试就是为了完成客户的需求。

但是,TDD要求你重视测试,测试是一等公民, 你得先写测试再去写实现,你的测试得能表现你的业务,让别人一看你的测试,就知道你的业务是啥,这就倒了过来,变成了实现是小儿子,哈哈

因为在TDD看来,好的能完整表现业务的测试,至少不会让你漏了边边角角,而且这样写下来,理想情况下,测试的覆盖率应该是百分之一百的. 你会对你写的代码无比有信心,因为在需求范围内,你可以宣称你写的代码是百分之百的满足需求。

课程开始的时候,我们对TDD要求的 Test First是什么,是很明确的,就是先写测试后写实现,Task Driven Development 这个也是比较好理解的,但是后两个确难到我们了,测试怎么去驱动开发,怎么去驱动你的设计,你的设计是测试驱动出来的吗?以至于我们花了两节课的时间去讨论这些问题。下面我附上,我们讨论的结论

  1. 我们写测试之前,脑海里是有提前设计的,没有提前设计,你测试都写不了更不用说写实现。
  2. 测试并不能驱动你的设计,只会让你发现坏的设计(坏的设计测试很难写)

下面是我们TDD的实践步骤:

  1. 跟客户确认当前阶段需求,确认到什么程度呢?你觉得你能开始列Task了的时候,之后随时保持与客户的紧密沟通,需求有任何问题找客户沟通

  2. 选择视角(就是选择看待问题的视角,比如是用户视角还是停车场管理员视角),运用Tasking思维管理工具 列Task,Task是以业务场景为单位的,每一个Task都是要有交付价值,何为交付价值,就是客户拿来能用的功能(能跑起来的程序), 代码写了一半,跑都跑不起来的,没有任何价值. 先列简单场景的Task 后列复杂场景的.

  3. 根据Task列表,从前到后一个一个的实现,由于我们是采取Pair的编程方式,所以是一个人写测试,然后另一人写实现,之后轮换
    提前设计注意点:

    1. 写Task之前,是要有提前设计的
    2. 提前设计必须根据你当前已经做完和正要做的Task做提前设计,禁止根据全部的Task做提前设计
      写测试的注意点:
    3. 测试必须能表现你当前Task的业务
    4. 抽象关系可以体现在测试里
      写实现的注意点:
    5. 实现的代码是基于你的提前设计的 (不要做重复的无用功)
    6. 实现的代码要刚刚好满足你的业务,何为刚刚好?就是删除任意一行你的代码,你的测试就会挂掉, 反之,就不是刚刚好
    7. 看到不爽的代码就重构,什么是不爽的代码?请看 clean code 这本书
  4. 全部Task完成之后就是向客户交付产品了,由于我们的客户是袁老师,所以给他review了代码,保证所有的测试是绿的

TDD 这个东西,如果你单看字面,不去实践,是无法领会它的精髓的,我觉得初学者如果要去实践TDD, 可以不用去考虑它的后两个单词,只看Test First,先实践一下Test First, 然后再慢慢去加上后两个Driven,最终你会达到那种得心应手的境界,当然还可能是放弃,哈哈

据说如果熟练使用了TDD, 开发效率会比不使用TDD提升很多,这个我暂时也还没体会到,看来是实践的少了,之后会找机会多实践TDD

重构

重构我就不多介绍了(要介绍也只能贴贴各种代码示例),请大家移步 重构 这本书

我就只说说我的感受

  1. 当你看到不爽的点的时候,你就要重构你的代码
  2. 不爽的点应该是违背团队的代码约定的,而不是违背你自己的小癖好
  3. 最好通读一遍 clean code, 这样你说别人代码不好的时候也不至于词穷(可以指着书本骂他😊)
  4. 光看重构这本书,其实没多大用处,你看过就会忘,你必须结合它来一场说写就写的实践, clean code也一样
  5. clean code, 重构这两本书,请常备在桌面上,说不准啥时候就会用到,无论是指着书本骂人,还是适当的装一下逼😊

总结

OOBootcamp 培训给我的进步还是很大的,以前我虽说是用着面向对象的语言,确写着云里雾里,而这次培训下来,结合理论和实践,我深刻理解了面相对象的基本原则,简单设计原则,以及Tasking TDD等做法,而且也使我对敏捷有了更深刻的认知,确实是犹如醍醐灌顶,受用无穷。我相信这些知识最终也能带着我飞得更高。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容