下载APP
关闭
讲堂
客户端下载
兑换中心
企业版
渠道合作
推荐作者

15 | 一起练习:手把手带你分解任务

2019-02-01 郑晔
10x程序员工作法
进入课程

讲述:郑晔

时长11:03大小10.14M

前面在讨论 TDD 的时候,我们说任务分解是 TDD 的关键。但这种认识依然是一种感性上的认识。今天,我们就来用一个更加具体的例子,让你看看任务分解到底可以做到什么程度。

这个例子就是最简单的用户登录。需求很简单,用户通过用户名密码登录。

我相信,实现这个功能对大家来说并不困难,估计在我给出这个题目的时候,很多人脑子里已经开始写代码了。今天主要就是为了带着大家体验一下任务分解的过程,看看怎样将一个待实现的需求一步步拆细,变成一个个具体可执行的任务。

要完成这个需求,最基本的任务是用户通过输入用户名和密码登录。

用户名和密码登录这个任务很简单,但我们在第一部分讲过沙盘推演,只要推演一下便不难发现,这不是一个完整的需求。

用户名和密码是哪来的呢?它们可能是用户设置的,也可能是由系统管理员设置的。这里我们就把它们简单设定成由用户设定。另外,有用户登录,一般情况下,还会有一个退出的功能。好了,这才是一个简单而完整的需求。我们就不做进一步的需求扩展。

所以,我们要完成的需求列表是下面这样的。


假设我们就是拿到这个需求列表的程序员,要进行开发。我们先要分析一下要做的事情有哪些,也就是任务分解。到这里,你可以先暂停一会,尝试自己分解任务,之后,再来对比我后面给出分解的结果,看看差异有多少。

好,我们继续。

我们先来决定一下技术方案,就用最简单的方式实现,在数据库里建一张表保存用户信息。一旦牵扯到数据库表,就会涉及到数据库迁移,所以,有了下面的任务。


这时,需要确定这两个任务自己是否知道怎么做。设计表,一般熟悉 SQL 的人都知道怎么做。数据库迁移,可能要牵扯到技术选型,不同的数据库迁移工具,写法上略有差别,我们就把还不完全明确的内容加到任务清单里。


数据库的内容准备好了,接下来,就轮到编写代码的准备上了。我们准备用常见的 REST 服务对外提供访问。这里就采用最常规的三层技术架构,所以,一般要编写下面几项内容。

  • 领域对象,这里就是用户。
  • 数据访问层,在不同的项目里面叫法不一,有人从 J2EE 年代继承下来叫 DAO(数据访问对象,Data Access Obejct),有人跟着 Mybatis 叫 mapper,我现在更倾向于使用领域驱动设计的术语,叫 repository。
  • 服务层,提供对外的应用服务,完成业务处理。
  • 资源层,提供 API 接口,包括外部请求的合法性检查。

根据这个结构,就可以进一步拆解我们的开发任务了。

不知道你有没有注意到,我的任务清单上列任务的顺序,是按照一个需求完整实现的过程。

比如,第一部分就是一个完整的用户注册过程,先写 User,然后是 UserRepository 的 save 方法,接着是 UserService 的 register 方法,最后是 UserResource 的 register 方法。等这个需求开发完了,才是 login 和 logout。

很多人可能更习惯一个类一个类的写,我要说,最好按照一个需求、一个需求的过程走,这样,任务是可以随时停下来的。

比如,同样是只有一半的时间,我至少交付了一个完整的注册过程,而按照类写的方法,结果是一个需求都没完成。这只是两种不同的安排任务的顺序,我更支持按照需求的方式。

我们继续任务分解的讨论。任务分解到这里,需要看一下这几个任务有哪个不好实现。register 只是一个在数据库中存储对象的过程,没问题,但 login 和 logout 呢?

考虑到我们在做的是一个 REST 服务,这个服务可能是分布到多台机器上,请求到任何一台都能提供同样的服务,我们需要把登录信息共享出去。

这里我们就采用最常见的解决方案:用 Redis 共享数据。登录成功的话,就需要把用户的 Session 信息放到 Redis 里面,退出的话,就是删除 Session 信息。在我们的任务列表里,并没有出现 Session,所以,需要引入 Session 的概念。任务调整如下。

如果采用 Redis,我们还需要决定一下在 Redis 里存储对象的方式,我们可以用原生的 Java 序列化,但一般在开发中,我们会选择一个文本化的方式,这样维护起来更容易。这里选择常见的 JSON,所以,任务就又增加了两项。

至此,最基本的登录退出功能已经实现了,但我们需要问一个问题,这就够了吗?之所以要登录,通常是要限定用户访问一些资源,所以,我们还需要一些访问控制的能力。

简单的做法就是加入一个 filter,在请求到达真正的资源代码之前先做一层过滤,在这个 filter 里面,如果待访问的地址是需要登录访问的,我们就看看用户是否已经登录,现在一般的做法是用一个 Token,这个 Token 一般会从 HTTP 头里取出来。但这个 Token 是什么时候放进去的呢?答案显然是登录的时候。所以,我们继续调整任务列表。

至此,我们已经比较完整地实现了一个用户登录功能。当然,要在真实项目中应用,需求还是可以继续扩展的。比如:用户 Session 过期、用户名密码格式校验、密码加密保存以及刷新用户 Token 等等。

这里主要还是为了说明任务分解,相信如果需求继续扩展,根据上面的讨论,你是有能力进行后续分解的。

来看一下分解好的任务清单,你也可以拿出来自己的任务清单对比一下,看看差别有多大。


首先要说明的是,任务分解没有一个绝对的标准答案,分解的结果根据个人技术能力的不同,差异也会很大。

检验每个任务项是否拆分到位,就是看你是否知道它应该怎么做了。不过,即便你技术能力已经很强了,我依然建议你把任务分解到很细,观其大略人人行,细致入微见本事。

也许你会问我,我在写代码的时候,也会这么一项一项地把所有任务都写下来吗?实话说,我不会。因为任务分解我在之前已经训练过无数次,已经习惯怎么一步一步地把事情做完。换句话说,任务清单虽然我没写下来,但已经在我脑子里了。

不过,我会把想到的,但容易忽略的细节写下来,因为任务清单的主要作用是备忘录。一般情况下,主流程我们不会遗漏,但各种细节常常会遗漏,所以,想到了还是要记下来。

另外,对比我们在分解过程中的顺序,你会看到这个完整任务清单的顺序是调整过的,你可以按照这个列表中的内容一项一项地做,调整最基本的标准是,按照这些任务的依赖关系以及前面提到的“完整地实现一个需求”的原则。

最后,我要特别强调的一点,所有分解出来的任务,都是独立的。也就是说,每做完一个任务,代码都是可以提交的。只有这样,我们才可能做到真正意义上的小步提交。

如果今天的内容你只能记住一件事,那请记住:按照完整实现一个需求的顺序去安排分解出来的任务。

最后,我想请你分享一下,你的任务清单和我的任务清单有哪些差异呢?欢迎在留言区写下你的想法。

感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给你的朋友。

© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
上一篇
14 | 大师级程序员的工作秘笈
下一篇
16 | 为什么你的测试不够好?
 写留言

精选留言(26)

  • desmond
    2019-02-01
    15
    这篇文章就值这套课程的价钱,赚了!
    展开

    作者回复: 把文章转发给给朋友同事,赚更多!

  • 你的笑犹如...
    2019-02-01
    5
    没有把事情想透,就直接进去开发。发现自己会踩很多坑。而且在开发的过程中会遇到各种各样的麻烦。
  • 2019-02-01
    3
    老师的一条回复我觉得很有启发啊:“不忙的时候你知道该怎么做吗?” 首先是意识问题,其次就是执行了。我自己的经历来看,之前在项目型软件公司,粗放式的工作惯了,后来经历了一家产品型公司的洗礼,刚开始格格不入,后来逐渐习惯了,现在想快也快不起来了。我经常跟我团队兄弟们说,想透了再动手,客户公司那些事我来搞定,我只要扎实的可交付的成果就行,拒绝返工!
    展开

    作者回复: 忙,是做事不动脑的借口。

  • 划时代
    2019-02-01
    3
    看了一些同学的评论,有感而发想表达一下自己的观点,并非是口诛笔伐。之前也听过一些如何做好软件开发的大牛讲座;有一部分听众反馈,项目周期很紧催促上线,哪有机会按照标准流程开发,保证高质量文档,保证高质量代码?这确实是客观的事实,是极端情况,然而很多时候仅仅是挂在嘴边的借口用来搪塞的,却忘了工程师本身的职责。我不太相信,一位工程师在一年的工作中,每一个项目,每一天的工作,都如十万火急一般,无法保证项目的质量。一年中有忙的时候,也有不忙的时候;一年中有急于上线的项目,也有井然有序的项目,往往不忙的时候多过忙的时候吧。在上升期很快的创业公司工作,也大概是这样子的。所以很多时候是考验个人执行力的问题,不断地实践和总结,掌握熟练之后得心应手。
    展开

    作者回复: 其实只要回答一个问题,当你不忙时,你知道该怎么做吗?

  • 北天魔狼
    2019-04-01
    2
    今天第二遍读这篇文章,实践过三次以上。感觉并没有因为做了分解而时间紧,事实上开发、调试更加顺畅,测试更加自信。也跟同事做了分享,我很激动,但是他们不激动
    展开

    作者回复: 靠讲道理,只能说明白想提高的人,我开专栏也是为了那些想提高的人服务。

  • 白目鱼
    2019-04-27
    1
    😂我上来先考虑了一堆有的没的:密码的规则啦,加密储存啦(直觉MD5之类的,一搜索这些方案也早就过时了),注册步骤,手机邮箱校验,……
    然后一对答案…… Hmm…… 我都在想啥
    展开

    作者回复: 02的段子在你这出现了。

  • One day
    2019-02-21
    1
    老师有个疑问,如果需要对即将要做的事情,没有经验,又不太了解的时候如何做任务分解呢,比如在限定的时间做一个之前没有接触的东西(我之前碰到过),麻烦解答,非常感谢
    展开

    作者回复: 赶紧补课,这个模块的答疑在不远处等着你。

  • shniu
    2019-02-02
    1
    想请问一下老师面对探索型的需求,调研型的需求如何做任务分解呢。大部分情况下,都会面临要做一些探索型的工作,一些新的架构,新的业务尝试,新的技术尝试,要面对很多自己并没有接触过的知识。举个实际的例子,最近在研究一些健值存储数据库,读了一些paper,一些设计实现,这可能都是要做的一些任务清单中的一些项,但是我想去实现一个kv存储的时候就会感觉有些无从下手,实际落地到代码层面和读paper读博客还是有很大差别的,落地代码更关注细节,关注写的每一行代码,在这方面老师能否给些建议
    展开

    作者回复: 答疑见!

  • qingsong
    2019-06-02
    豁然开朗,把确定下来的项目需求,把需求颗粒化分解,也就是14节讲到的每一个小的任务都可以提交代码,这样的话,整体思路比较清晰明了,同事可以方便的看出自己完成了那些功能需求,还有那些没有完成。这是一个循序渐进的过程。
  • butterfly
    2019-05-22
    老师,我想问下 任务分解的粒度问题. 我工作中会分解到接口的下一层, 从MVC+db的方式进行分解. 比如,要实现注册接口,需要
    1. 注册页面;2.model层(数据校验+逻辑处理),3.数据库表设计.
    如果细分到函数和类这一次是不是太细了?

    作者回复: 参考第14讲,再理解一下微操作。

  • kyo
    2019-05-09
    我把任务分解的颗粒度按是否能给出明确的实现时间判断. 这更有利于预估实现整个需求所需要的时间.
  • 了@事@牵
    2019-05-03
    最终的目的是拆分出最小可执行单元
    展开
  • 赫伯伯
    2019-03-27
    这就是程序员和工程师的区别
    展开
  • kevin
    2019-03-18
    任务拆分可以这么细,学习啦
    展开
  • lyning
    2019-03-17
    用流程图把存在依赖的任务清单可视化,好像可行😏
    展开

    作者回复: 嗯,可以。

  • 红糖白糖
    2019-03-10
    分解的粒度跟个人的熟悉程度有关。比如一个登陆注册你写了很多次,很熟悉,拿来就知道有哪些事情需要做。就可以粒度偏粗,如果是一个全新的需求/复杂的需求,此时就应该偏细
    展开
  • lester
    2019-02-20
    "来看一下分解好的任务清单"老师这里的分解好的任务清单有遗漏?
    展开

    作者回复: 分解的逻辑都在这里了,你自行判断吧!

  • Dawn
    2019-02-17
    建议:千万别上来就给表取名users。https://codewithoutrules.com/2018/09/21/users-considered-harmful/?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website
    展开

    作者回复: 这个观点我同意,这里是为了叙述方便。在沟通反馈部分,我会讲到写代码时,要区分概念。

  • Dawn
    2019-02-17
    "郑老师的拆分更精细,非常值得学习。补充一点我自己的习惯,可以每做一个feature时就拉一个分支,feature进一步拆成更细的任务。由于多数编辑器都有本地历史,所以不常做git add。任务完成并且测试通过后再一把提交。整个feature完成再合并分支" -- 怎么看这个问题?发现好多公司采用这种形式。

    作者回复: 主开发分支开发是更好的选择,但多分支是很多公司的现状,可以对比着主开发分支模型思考一下,怎么改进。

  • 爱吃彩虹糖...
    2019-02-16
    以前,一开始写代码的时候,上来就是一顿猛敲,然后过段时间又得重写。自从跟着老师学习之后,视野开拓很多,也学习了很多有用的方法,比如以终为始,事前推演,编写测试用例,按需求拆分任务等。跟着老师,继续开拓我的视野~

    作者回复: 有改变就是好的

收藏