阅读更多

1顶
0踩

研发管理

原创新闻 软件开发中的快与慢

2013-07-25 13:56 by 副主编 mengyidan1988 评论(3) 有8316人浏览

本文作者Michael Dubakov从事软件开发方面的工作,他在读了Daniel Kahneman的《思考,快与慢》后,思考了软件开发中的快与慢,并且把书中的一些思想应用到实际的软件开发中。下面是笔者对原文的翻译:

最近,我在阅读Daniel Kahneman的《思考,快与慢》,这本书非常令人着迷。里面拥有大量的真知灼见,给读者带来一场思维之旅。目前,我在一家软件公司工作,书中所学到的部分自然而然地可以应用到我们的工作中。下面,我将分享自己从这本书的所感、所知。

系统1和系统2

这本书包括两个部分,系统1和系统2。在书中,卡尼曼会带领我们体验一次思维的终极之旅。他认为,我们的大脑有快与慢两种作决定的方式。常用的无意识的“系统1”依赖情感、记忆和经验迅速作出判断,它见闻广博,使我们能够迅速对眼前的情况作出反应。但系统1也很容易上当,它固守“眼见即为事实”的原则,任由损失厌恶和乐观偏见之类的错觉引导我们作出错误的选择。有意识的“系统2”通过调动注意力来分析和解决问题,并作出决定,它比较慢,不容易出错,但它很懒惰,经常走捷径,直接采纳系统1的直觉型判断结果。

如果你是一名软件工程师,你会快速抓住系统1和系统2的特质。系统1相当于缓存,而系统2则相当于业务层。缓存是廉价和快速的,而业务操作则比较慢和昂贵。

下面我将会用书中的一些概念来理解软件开发中遇到的一些实例。

眼见为实(WYSIATI)

通常,人们不会怀疑他们所看到的事情(从广义上来讲)。而如果你有一些信息,你很有可能会产生质疑,并且去查证。人们往往会基于现有地事实和有限的证据来做出决定。这样很有可能会导致一个偏差:

在软件开发中,估算并不是件容易的事,我们有可能一直在犯错,估算就是一个分布。

过分自信

软件估算是过度挥舞自信的产物。

如果你问“我们需要整合Twitter,需要显示特定标签下的所有推文,完成这些需要多久?”开发人员不会问其他额外的问题,通常都会直截了当的给出答案,2天。这明显是系统1里的心理反应。而答案也非绝对正确,尽管缺乏信息,但这并不影响估算。开发人员应该聪明点和自信点,但他们也应该摆脱WYSIATI,并且认真仔细地思考一些未知数。

框架效应

描述问题的措辞很重要,同一个问题,用不同的语言描述,很有可能会产生不同的解决方案和反应,看下面这两个问题:

你认为,我们需要一个非常有经验的开发人员来解决这么简单的问题吗?

你认为,我们需要一个非常有经验的开发人员来解决这么复杂的问题吗?

问题好像被设置了框架一样。第一个问题,你很难去回答Yes,相反,第二个却很容易回答Yes。

忽视基础概率

有些事件可能会比其他的更容易些。然而,人们并不具备好的直觉和数据统计。

比方说,你的产品被1000家公司采用,你接收到一封客户的邮件,该客户认为他们的想法很棒,而且必须马上实施。存在这样的争论是很好的,而且非常有意义。你感受到了客户的痛苦,并且集中全力快速启动新功能的开发。好吧,你可能错过了什么,那就是,你有想过其他999位客户是否需要吗?或许他们就不需要这样的解决方案呢。你忘记了产品要基于更大的客户群,而对于单个请求是否要进行重新审查。

在平时开发中,这种错误很常见,并且我会反复提醒自己。现在,我会非常认真仔细地考虑每一个请求。而不是冲动。

回答一个简单的问题

当我们对一个复杂的问题难以回答时,我们通常都会用简单的思维来替代复杂,其实书中系统1就可以处理,大家来看下面这个例子。

你常常会听到这样的问题:“该项目在3个月内会有哪些进展?”对于这个问题,你可以这样理解:“这个项目会有哪些进展?”。

通过做这样的替换,你无需用系统2的思维来回答,直接使用系统1的就可以了。有趣地事,我们并未意识到替代,并且会很好地回答这个问题。

情绪启发式

人们的情绪往往会对决定产生很大的影响。例如,如果你喜欢Node.js,那么你会很乐意采用它来开发新的Web应用程序,而如果你不喜欢Node.js,你会列出许多反对的理由,并且支持使用另一门语言来开发。

这种情绪化的启发式是很难克服的。虽然有时候是不合理的,甚至是不理智的。有时,这种基于直观喜好的选择并不是最好的。

我只是列举了一些表面例子,但很显然,在软件开发过程中,我们很容易基于这种情绪或某种偏见来做一些决定。

直觉 vs. 模型

事实上,在我们决定一些东西的时候,可以应用模型。 

Kano模型是一个非常好的例子,它可以帮助我们对新功能做出更加明智的决定。

模型似乎一直好于直觉。模型会迫使你去思考领域,问题的方方面面,以及从各个不同的角度看它——使用系统2思维。

这里有一些简单的问题:“下面,我们该从哪个功能做起?”,你可能会根据直觉回答说:“高级搜索”。但实际上,这个功能可能并不重要,而是有数十个更重要的功能。你可以构建一个简单的模型,并且进行评估。例如,在制作模型的时候,可以采用以下选项作为参数:

  • Kano模型(基础、delighter、性能)
  • 投票:客户的需求有多大。
  • 频率:客户使用的频率有多大。
  • 传播:有多少人会使用这个功能。
  • 成就:(S, M, L, XL, …)
  • 复杂性:它会增加使用的复杂性吗?

通过制作这样的模型,你会很容易做出决定。

模型除了可以应用在软件领域,它还可以应用在许多地方。实践告诉我们,直觉很少能带来正确的决定和很好地解决问题,除非你是史蒂夫·乔布斯。

英文原文:Software Development: Fast and Slow 

  • 大小: 30 KB
  • 大小: 24.1 KB
来自: csdn
1
0
评论 共 3 条 请登录后发表评论
3 楼 zhuchao_ko 2013-09-18 09:59
对于已有的产品和特定的客户采用定制功能的方法解决。
2 楼 freezingsky 2013-07-27 17:55
我个人觉得,在一个系统没有正式开发之前,对于最终效果的预测,都是很悬的。
1 楼 kentkwan 2013-07-26 10:39
不错的文章

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • sighold,sigset,sigrelse,sigpause,sigignore

    signal() 功能:信号管理功能 语法:#include void(*signal(sig,disp))(int) intsig; void(*disp)(int); void(*sigset(sig,disp))(int) ...

  • 多进程编程知识汇总,附代码例子!

    进程是指正在运行的程序,它拥有独立的内存空间和系统资源,不同进程之间的数据不共享。进程是资源分配的基本单位。线程是进程内的执行单元,它与同一进程内的其他线程共享进程的内存空间和系统资源。线程是调度的基本单位。操作系统根据不同的场景提供了不同的方式,消息队列、共享内存、UNIX域套接字、管道、信号量。内核中的一个优先级队列,多个进程通过访问同一个队列,在队列当中添加或者获取节点来实现进程间通信。

  • C语言玩转多进程

    文章目录 文章目录文章目录多进程退出程序析构函数暂停调用系统命令设置当前目录顺序执行命令并发执行命令进程标识进程PID进程句柄多进程总结 多进程 在一个项目中并发执行任务时多数情况下都会选择多线程,但有时候也会选择多进程,例如可以同时运行n个记事本编辑不同文本,由一个命令跳转到另外一个命令,或者使用不同进程进行协作。在学习多进程之前我们必须了解一个进程如何获取进程,进程如何结束,如何调用外部进程等操作。 退出程序 自ANSI C开始就支持退出程序和析构,无论在任何时候调用exit()都会直接退出程序,ex

  • Linux的system()和popen()差异

    Linux的system()和popen()差异1. system()和popen()简介在linux中我们可以通过system()来执行一个shell命令,popen()也是执行shell命令并且通过管道和shell命令进行通信。 system()、popen()给我们处理了fork、exec、waitpid等一系列的处理流程,让我们只需要关注最后的返回结果(函数的返回值)即可。2. syste

  • C++ Webserver从零开始:基础知识(七)——多进程编程

    在学习操作系统时,我们知道现代计算机往往都是多进程多线程的,多进程和多线程技术能大大提高了CPU的利用率,因此在web服务器的设计中,不可避免地要涉及到多进程多线程技术。这一章将简要讲解web服务器中的多进程编程,本文不会很详细,也不会在原理性的知识上多费笔墨。如果读者有什么不理解的地方,建议学习一下操作系统的基础知识。

  • Unix 多进程

    深刻理解Linux进程间通信(IPC) 转载于:https://www.cnblogs.com/gjianw217/p/3287949.html

  • 深入浅出--UNIX多进程编程之fork()函数

    0前言 上周都在看都在学习unix环境高级编程的第八章——进程控制。也就是这一章中,让我理解了unix中一些进程的原理。下面我就主要按照进程中最重要的三个函数来进行讲解。让大家通过阅读这一篇文章彻底明白进程这点事。希望对大家有所帮助。 1进程环境 在学习进程之前,一定要了解一下unix的进程环境。系统如何对进程终止,和一个程序启动终止,程序运行的原理等,这些都有助于你理解进程的...

  • Unix进程小结(一)

    一、进程的基本概念     1、进程与程序     程序是存储在磁盘上的文件,它是包含要执行的机器指令和数据的静态实体。     进程是一个正在运行的程序,一个程序可能包含多个进程(多任务、多进程),进程在操作系统中是一个执行任务的单位。          2、进程的分类     交互进程:需要用户输入数据,也会显示一些结果给用户看。     批处理进程:用来执行脚本的进程,例如Makefil。 ...

  • signal函数

    设置某一信号的对应动作 #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); 第一个参数signum:指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。   第二个参数handler:描述了与信号关联的动作,它可以取以下三种值:    1)SIG_IGN   这个符号表示忽略该..

  • 信号(初稿)

    废弃的接口: int sighold(int sig);int sigrelse(int sig);int sigignore(int sig); 新接口: 不能block SIGKILL or SIGSTOP。#include #include int kill(pid_t pid, int sig); pid大于0,发送给指定进程;pid为0,发送给当前进程所在

  • Linux C多进程编程基础

    关于进程概念相关的内容请打开链接,本文所介绍的是进程的POSIX标准。 进程的关系        Linux中的所有进程都是相互联系的,进程之间的的从属关系有父/子关系和兄/弟关系。        Linux内核创建了进程标号为0以及进程标号为1的进程。其中PID为1的进程是初始化进程init,Linux中的所有进程都是由其衍生而来的,在shell下执行程序启动的进程则是shell进程的子进...

  • C语言里的多进程(用fork函数实现)

    创建进程有两种方式,一是由操作系统创建;二是由父进程创建。操作系统创建的进程,它们之间是平等的,一般不存在资源继承关系。而由父进程创建的进程(子进程),它们和父进程存在隶属关系。子进程又可以创建进程,形成一个进程家族。       系统调用fork是创建一个新进程的唯一方法。进程调用fork函数就创建了一个子进程。       创建了一个子进程之后,父进程和子进程争夺CPU,抢到CPU者执

  • 多进程编程

    多进程编程 写在前面的话    本文主要根据本人在UNIX系统上的编程实践经验总结而成, 既做为自己在一个时期内编程实践的部分总结, 又可成为文章发表. 对UNIX程序员初学者来说是一个小小的经验, 仅供参考; 对UNIX老手来说则不值一哂, 请各位多多指教.一.多进程程序的特点    由于UNIX系统是分时多用户系统, CPU按时间片分配给各个用户使用, 而在实质上应该说CPU按时间片分配给各个

  • 非堵塞connect用法及常见错误

    在一个TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未完成;同时TCP的三路握手操作继续进行;在这之后,我们可以调用select来检查这个链接是否建立成功;非阻塞connec

  • 高级进程间通信

    1.基于STREAMS的管道 流管道是一个双向(全双工)管道。单个流管道就能向父、子进程提供双向的数据流     1).命名的STREAMS管道 我们可以用fattach函数来在文件系统给一个STREAMS管道一个名字 #include int fattach(int filedes, const char *path); //成功返回0,错误返回-1。 path参数

  • C++ 多进程编程

    需要注意的是,虽然 POSIX 标准只定义了两个用户自定义信号,但某些操作系统或特定的运行时库可能会提供更多的用户自定义信号,超出了 POSIX 标准的范围。这些信号的设计目的是为了给开发人员提供一种扩展的机制,可以在程序中使用自定义的信号进行特定的处理或通信。使用信号来通知子进程终止,并给子进程执行清理操作的机会,可以确保程序在退出时保持良好的状态。通过使用SIGTERM信号,父进程可以优雅地通知子进程要终止,并给子进程一个机会来清理资源和执行必要的关闭操作,避免了突然终止带来的资源泄漏问题。

  • C/C++使用信号实现超时功能

    若教眼底无离恨 不信人间有白头 Python可以通过装饰器实现函数的超时,C/C++就得想点别的办法了,可以借助一个操作系统的信号机制。 网上资料很多,这里我直接放代码,一看就懂,其实就调用了两个系统调用。 #include <signal.h> #include <cstdio> #include <unistd.h> void handle(int s...

Global site tag (gtag.js) - Google Analytics