Contents
  1. 1. 生活
    1. 1.1. 写作
    2. 1.2. 教育
    3. 1.3. 统筹方法
  2. 2. 编程
    1. 2.1. 定位错误
    2. 2.2. 任务拆分,估算
  3. 3. 总结

我一直都说,计算机和编程是用来解决问题。问题的分解肯定是非常重要的,也必须具备的能力。相比我在学习编程需要具备的基本能力 - 抽象谈的_抽象和具象_,大家应该能理解什么是问题分解的能力。不过上次也有人给我留言,说那篇文章说的就是分析和分解问题的能力。其实它们还是有点不同。

抽象和具象关注在理解事物的定义;问题分解关注在分析和理解事物的组成。有时候,问题分解能够辅助定义的理解,但有时候是理解定义后才更好帮助你拆解问题。比如前面说的递归,一开始学习这个概念的时候,你可能用抽象和具象来帮助你理解它是什么。等你掌握核心理念后,如果遇到一个你认为能用递归来解决的问题,你就需要拆解,找出什么是相似和重复处理的逻辑,什么是边界和基准条件。

因为这篇文章是给打算学习编程的人看,所以一开始讲一些生活中我们如何分解问题。后面再举一些编程内的例子。其实学会分解问题,无论是否学习编程都相当有益。

生活

写作

写作竟然也要分解问题?其实我读书时期是相当不喜欢写作的。反而现在编程后,越来越觉得写作和编程的关系是多么的紧密。编程其实就是写一篇逻辑严谨,简洁的文章。

话说回来,写作的时候,我们要怎么分解问题?首先,我们先明确分解问题的目的是什么?

写作的目的,是为了清楚表达你的观点。要清楚表达其实包含两方面,我们来分解一下。

  1. 从论述观点的角度
  • 我这次想表达的核心观点是什么?
  • 细分的子观点有哪些?
  • 每个观点有哪些论据可以使用?
  • 有没有反面观点?
  • 我的观点和反面的区别在什么地方?
  1. 从清楚表达的角度
  • 我的目标人群是谁?
  • 有没有贴合的事物可以类比?
  • 他们本来可能持有什么观点?
  • 为什么他们原来的观点可能不正确或者不完整?

我相信,如果我们在写作之前,至少按照上面的问题来分解,并解决了它们,整篇文章的骨架就基本成型了,剩下的就是填充细节,和打磨文字。

教育

我的儿子已经 7 岁了。可能因为他老爸是程序员吧,我喜欢买的玩具,都是拼图,乐高,棋类的东西。教他玩,学习和做事情的方式,都或多或少教他怎么通过分解问题来考虑。

比如玩拼图的时候,我就教他先按照颜色的相似度来分成几大堆,同时还把四个角,和四条边上的先找出来。拼出外围框架后,再围绕颜色突出的图案开始拼。还有,教他两位数加法的时候,比如 18 + 7,就把 18 分成 10 + 8,然后把 8 + 7 先算出来,得到 15 后,再和 10 去加。当然他自己也慢慢学会分解问题,他教我跳街舞的时候,就学会怎么把动作分拆成一步步教我。

统筹方法

可能很多人都听说过泡茶的统筹规划问题。进得了厨房的女士可能不自觉就应用了这项技能。比如,一顿简单的饭可能包含下面几个步骤。

  • 淘米
  • 下米煲饭
  • 浸泡青菜
  • 洗菜
  • 炒菜
  • 洗肉
  • 蒸肉

上面的步骤其实分了存在明显依赖关系的三大块:淘米 -> 下米煲饭浸泡青菜 -> 洗菜 -> 炒菜, 洗肉 -> 蒸肉。其实还有一些不明显的依赖关系:淘米 -> 浸泡青菜下米煲饭 10 分钟后 -> 蒸肉。因为用淘米水浸泡一下青菜可以节省一点水,还有我必须在恰当的时间放肉到电饭煲里面蒸,早了导致碟子积水太多,晚了肉可能蒸不熟。所以呢,我安排任务的顺序就是这样:淘米 -> 下米煲饭 -> 浸泡青菜 -> 洗肉 -> 洗菜 -> 蒸肉 -> 炒菜

虽然这个例子和编程八杆子也搭不上,但是统筹方法在计算机领域相当常见。什么事情可以同时处理(并行计算),什么时候一定要按顺序处理(串行计算),什么东西一定要前面完成,或者放最后。这样的决定,必须依靠把问题分解成尽量独立的小块,才能做出正确的判断。比如,做前端的要考虑页面哪些部分是首屏,也就是用户第一眼就看到的东西,需要优先加载;做数据报表的,要考虑 ETL (Extract-Transform-Load) 涉及从哪些地方抽取数据,依赖关系如何,什么数据转换任务可以同时做,要经过多少时间转换和生成报表。

编程

我之前写过一篇有经验和没有经验的程序员的区别,里面说的很多都和问题分解有关系。所以这里就简单带一下,详细的可以参看那篇文章。

定位错误

学习编程的新手,经常会碰到各种莫名奇怪的问题,也最怕碰到问题。这也是很多人感到重大挫折而中途放弃的原因。我想说的是,老手也会碰到莫名奇怪的问题,只是我们懂得如何分析和分解问题,然后定位错误。

任务拆分,估算

现在很多人学习 Web 编程,基本都是学习如何搭建一个网站,或者论坛。但是很多人,要么觉得系统太庞大,不知道如何入手。要么以为很简单,低估问题的难度,一开始信心满满,后面遇到各种小问题冒出来,就迷失方向,抓不到重点了。

假设我要做一个类似电商类网站,我可以怎么分解呢?

  1. 用户模块:包括用户注册,登录,个人信息。用户还要分普通用户,商家。
  2. 商品模块:商家产品上架,下架。
  3. 订单模块:用户购物车,下订单,支付,取消订单。
  4. 物流模块:产品库存管理,发货。

上面几大模块,往横向分析的话,相互之间还有依赖关系和交互,比如没有库存就不能下订单,发货后就不能取消订单等。纵向深入分析的话,比如注册要手机还是邮件验证,还是用社交帐号登录,支付要接入微信,银联还是支付宝等。当你把系统分解完,就可以找出哪些是核心和必不可少的部分,然后决定 MVP 应该包含什么。

还有,上次有人和我说,他是做股票分析的,想学习一点编程,然后帮助他筛选出股票。他想做的东西比如是拿今天所有的股票,看有多少站到五日均线以上。那我就帮他分析,和拆解他要面对的问题是什么。

  1. 你如何获取股票数据?有现成的,还是要学如何写爬虫,自己抓取?
  2. 什么叫做站到五日均线以上,获取的数据里面就有,还是自己算?
  3. 要自己算的话,你有学过基本的数据统计分析知识吗?

这样一路下来,你就可以针对自己要做的事情,把每一个点逐一拆解,直至基本无法更细的程度。最后,重点要关注什么地方,什么地方花钱可以搞定,什么地方是自己必须自己学习和重点掌握的,就比较清晰了。

总结

问题分解可以说无论什么领域都适合也应该使用。计算机和编程的不断发展,其实也越来越往专业领域拆分。现在涌现出来的各种 PaaS, SaaS 云平台,包括网络主机供应商,静态资源图片存储和加速,网络安全防护,认证登录系统,网络数据库等都是把以前的搭建,部署和维护系统整件事,拆解成各个小问题,然后抽象出共性来作为一种服务提供。

Contents
  1. 1. 生活
    1. 1.1. 写作
    2. 1.2. 教育
    3. 1.3. 统筹方法
  2. 2. 编程
    1. 2.1. 定位错误
    2. 2.2. 任务拆分,估算
  3. 3. 总结