阅读更多

7顶
0踩

研发管理

转载新闻 代码不是文学作品

2014-04-18 11:42 by 副主编 WnouM 评论(4) 有7223人浏览
我在最近两个工作过的公司(Etsy和Twitter)成立过代码阅读小组,一些人向我征询关于阅读代码以及运作代码阅读小组的建议。想说的太多,一言以蔽之:不要成立代码阅读小组。你应该去成立小组但不是我稍后提到的那样,而在此之前,我要解释一下我是如何得出目前观点的。

作为一位曾读英语专业的业余作者,我以往总是被这样的想法所吸引:代码就像文学作品,我们应该像通过阅读优秀范文学写英文那样来学写代码。当然,持这种观点的不止我一个人。Donald Knuth(著名计算机科学家,译者注),除了致力开发TeX软件和编著《计算机程序设计艺术》,一直以来是被他称作“文学编程”的提倡者,并已经把他的几个大型程序出版成书。

另一方面,早在我加入Etsy并成立第一个代码阅读小组之前,手头上就已经有一些迹象本就表明:这是看待代码的一个错误方式。

首先,当我在编写关于与程序员访谈的《编程人生》(书中记录与15位世界级编程大师的对话,译者注)一书时,我几乎问了每个人关于阅读代码的问题。大部分人说阅读代码是重要的且程序员应该多读,然而当我问到他们最近读了哪些代码时,很少有人有好的答案。在他们还是年轻黑客时,其中有些人认真地读过一些代码,然而几乎没人保有阅读代码的习惯。Knuth作为伟大的计算机科学集大成者,阅读了大量的代码;Brad Fitzpatrick谈到出于恶作剧而阅读过一些开源代码片段。但他们俩是例外。

如果这还不够,那么在完成《编程人生》之后,我获得一次采访Hal Abelson的机会。Hal Abelson是麻省理工大学的著名教授,《计算机程序的构造和解释》的合著者。当我首次跟他谈论,问及之前那样的阅读代码问题时,他给出了普遍的答案:阅读代码是重要的且程序员应该多读。但他也没有说出任何最近读过的代码,除了不得不阅读的代码之外,包括在谷歌休公假时审查同事的代码以及给麻省理工学生评分时的代码。后来我问他关于这种矛盾:

引用
Seibel: 我对人们所说的和实际所做的之间的这种分裂很好奇。每个人说“程序员应该阅读代码”,但似乎少数人真正去做了。我会感到惊讶:如果我采访小说家们并问他们最近读了哪本小说,他们回答说“哦,自从读研究生后,我就没真正地去读一本小说了”。作家们实际上会读其他作者的书,但程序员不会真正得去读其他人的代码,尽管他们说应该去读。

Abelson: 是的。你是对的。但记住,很多时候,你增删查改一个程序最终使之能够运行并完成你需要它做的所有事情,所以就有很多与核心思想无关紧要的东西。

Seibel: 所以基本上你最终是说,大多数代码不值得一读?

Abelson: 或者说程序从一个初始计划或某种伪代码构建起来。书中的许多代码,是一些净化过的版本,不具备使程序运行起来的所有东西。

Seibel: 我想起了《计算机程序的构造和解释》的前言,里面写道“程序应该是为了供人读才写的,然后顺便让机器执行了一下。”然而正好你所描述的事实在实际中却是,大多数程序都是让机器来执行才写的,如果有的话,只顺便供人阅读。

Abelson: 嗯,我认为他们一开始是为了供人阅读的,因为里面包含着一些想法。你解释的东西,仅有一小部分存在我们的书中。书中有一些相当重要的程序。而且部分原因是我们认为解释它做什么的最简单方式就是表达在代码中。


然而即使明显知道大部分真正的代码实际上不是采用人容易读懂的方式去编写的,但这不足以让我在Etsy成立小组时放弃这种文学研讨班模式。由于大多数Etsy开发者熟悉Javascript以及我知道Jeremy Ashkenas对可读性代码的编写有浓厚兴趣,所以在第一次代码阅读小组会时,我选取了Jeremy的backbone.js。我仍计划了一些像文学研讨会一样的流程,但我发现许多人不会预习代码(嗯,这点跟文学研讨班倒是一样)。所以我决定在小组讨论环节之前演示要讨论的代码。

当准备我的演示文档时,我发现自己掉进了惯常模式:每当试图真正理解或心领神会一段代码时,我不得不从根本上重写它。为了更好理解,我将开始重命名一些名称,接着顺着我组织代码思路去移动一些语句。很快,我就已经开始深入代码抽象化(或具体化),并开始对更大程度地重组代码结构。一旦完成代码重写,我通常已很好地领悟了,甚至可以溯源并理解初始版本。我经常觉得这种阅读代码的方式不好,但它是迄今为止我理解代码的唯一方式。

在代码阅读小组演示时,我以初始的backbone.js作为开始,然后在自己想法的指引下,一步一步演变使之更易懂。当我问大家是否应该转向小组讨论环节时,但似乎没有人很感兴趣。好在看到我的重构让组员对原始代码的底层结构有了与之前我通过重构获得的相同见解。

Etsy的第二次代码阅读小组会由Avi Bryant主持,展示了如何利用SmallTalk的代码浏览功能来查看一些代码。因为在Etsy少数工程师跟Smalltalk打过交道,所以我们对组员会预习代码这件事不抱任何希望。但这次演示,对组员来说是一次领略SmallTalk魅力的绝佳机会,也让有我有机会发难Avi关于Smalltalk和Lisp的区别。

当我来到Twitter,文学研讨会模式仍莫名其妙地盘旋在脑海中,尽管在Etsy的两次看起来备受青睐的小组会几乎没有遵循这种模式。当我发邮件邀请twitter的工程师参加代码阅读小组时,回应相当热情。再次,第一次小组会由Marius Eriksen演示了一段代码。在这个示例中,展示了Scala语言实现的Future包的内部构件。这个构件被用于Twitter的很多服务,其大部分由Eriksen本人编写。

在演示了一段时间后,我终于明白一个浅显的道理:代码不是文学作品。我们不去阅读代码,而是解译、审查它。一段代码不是文学片段,而是样本。当我问Knuth关于他自己阅读代码时,他回答的其实早就给我指明了这个方向:

引用
Knuth: 但建立在大脑的东西是真正有价值的。那么我怎么利用它的呢?曾经有台型号为Bunker Ramo 300的机器,有人告诉我这台机器的Fortran编译器真的是不可思议的快,但没有人知道它是怎么做到的。我得到了编译器源代码的副本。因为我没有机器的说明书,所以甚至连机器语言是什么都不知道。

但是我把它当成是一项有趣的挑战。我能搞清楚BEGIN,然后我就开始解码。这些指令码对应着双字指令助记符,所以我开始合计着“这个可能是装载指令,而这个可能是分支”。接着我知道它是Fortran编译器,所以到一定程度后,看着卡片的第七列就能分辨是不是注释。

三个小时后,我已经弄懂机器的一小部分。接着我碰到了重大问题——跳转表。因此这是一个难题,之后我坚持画了些图表,就像我在某安全局试图解译一个密码一样。但我知道它是个运行很快的Fortran编译器,在某种意义来说这不是加密而是有意地掩盖;因为弄不到机器的说明书,所以答案就藏在代码中。

最终我弄明白了为什么这个编译器如此快。不幸的是,它并不是因为使用了卓越的算法,仅仅是因为他们采用非结构化编程并且最大限度地优化了代码。

画图表、获取更多一点信息并作假设仅是你基本上解决某种难题的方法。通常,当我阅读技术文件时,是同样的挑战。我试图理解作者的思想,尝试搞懂这个概念是什么。我认为,你试着去读别人的东西越多,未来你更能创造属于自己的东西。


他没有在描述文学作品的阅读,而在描述一个科学性调查。所以现在我对人们应该如何一起从代码中获得深刻见解这个问题有了新答案,正如我向Twitter代码阅读小组解释的一样:

引用
在准备与一起编程的女儿们即将进行的对话时,我开始思考告诉她们一些关于代码阅读以及应该读什么代码的事情。我再次突然想到了那些所有口惠而实不至的代码阅读想法,绝大部分程序员不会真正地阅读大量代码,至少不是纯粹为了阅读代码而读。这有一个简单检验方法:说出一段你读过的代码并且肯定大部分优秀程序员会去读或者至少听说过。不多,对不对?可能一行都没有。

但我想到代码不是文学作品,我们不是读者。更确切地说,有趣的代码片段是样本,我们是博物学家。所以我认为更好的方式是:我们其中的一位扮演着一个刚从异国回来的19世纪博物学家在国内科学界引发关于他们所发现的一只新型昆虫的议论:“看这怪物的触须!这些触须看起来非常笨拙,然而该物种的雄性可利用它们杀死小青蛙,然后雌性将卵产在其尸体中”,而不是像一群学比较文学的研究生那样挑出一段代码并去阅读、讨论它。

这种演示的关键在于介绍者要选一段自己深刻理解的代码,并通过从进化碎屑层(亦为临时补救方案–指快速有效但丑陋的方案,译者注)中指出核心思想,有助于听众理解。一种合理的方式应该是展示真正的源码并剥离、重写关键部分,就像一个生物学家去染色样本,使不同特征更容易辨别一样。

典型的演示应面向所有程序员,或男或女,或聪明或一般,但必须对与代码出处有关的任何特定知识不作要求。为了让组员理解代码,演示文档应该提供足够的上下文,解释对一般水平程序员而言比较晦涩的实现语言的任何细节。


由于我的顿悟,我们采用新模式,已成功举行了几次代码阅读小组会议,现在被称为Twitter的旨在提高编码知识的英国皇家学会。我们仍在摸索讲演代码的最佳方法,尽管目前方法感觉很不错。另外,我不再觉得我这种解剖式阅读代码的方式是糟糕的。

至今最大的教训是,代码是非常稠密的。半小时的报告只够用来呈现大约十二行耐人寻味的代码和一个主要思想。几乎可以肯定的是:报告人必须真正深入某段代码,要比任何人有更深的理解。除此之外,一个优秀的演示至少可让组员接触到的核心思想,对于决定自己去阅读代码的人们来说,可能是一个好的开端。

原文链接: Peter Seibel   翻译: 伯乐在线 - heloowird
译文链接: http://blog.jobbole.com/64548/
来自: 伯乐在线
7
0
评论 共 4 条 请登录后发表评论
4 楼 JamesQian 2014-04-22 14:01
程序应该是为了供人读才写的,然后顺便让机器执行了一下。”然而正好你所描述的事实在实际中却是,大多数程序都是让机器来执行才写的,如果有的话,只顺便供人阅读.
3 楼 tmartin 2014-04-18 22:22
dohkoos 写道
因为很多大师认为阅读代码很重要,但是他们没时间去读或不想去读,所以就在书里写上这么一笔。说阅读代码很重要,程序员应该去读。这就是“强调的就是缺失的”体现。

支持
2 楼 麦田的设计者 2014-04-18 18:34
Teacher always encourage us to read or copy the codes which have been defined right
1 楼 dohkoos 2014-04-18 15:59
因为很多大师认为阅读代码很重要,但是他们没时间去读或不想去读,所以就在书里写上这么一笔。说阅读代码很重要,程序员应该去读。这就是“强调的就是缺失的”体现。

发表评论

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

相关推荐

  • 用户管理系统

    用EasyUi做的一个Web项目 后台代码采用java SpringMVC框架 前端采用了EasyUi框架 注解简单,通俗易懂

  • 好友管理系统 Python

    friends = [] print("欢迎使用好友系统") print("1:添加好友") print("2;删除好友") print("3:备注好友") print("4;展示好友") print("5:退出") while True: num = int(input("请输入您的选项;")) if num == 1: add_frends = input("请输入要添加的好友:") friends.append(add_frends) p

  • Python用面向对象实现人类之间交朋友的功能

    # 人类:一个父类 class human(object): nation = "china" def __init__(self,name,gender,phone): self.name = name self.gender = gender self.phone = phone # 将个人信息存储在列表中,并返回这...

  • 面向对象的通讯录系统C++

    今天复习c++,想起来自己努力写了那么久的通讯录系统居然没发过博客,虽然写的不好,但还是想发上来留个纪念。 //温馨的通讯录系统 #include<iostream> #include<fstream> #include<cstdio> #include<iomanip> #include<cmath> #include<cstring> #include<string> #include<algorithm>

  • 项目四小型信息管理系统的设计与实现

    1)设计一个简单的学生信息管理的程序,教学管理人员能够使用该程序对学生基本信息、课程信息进行管理,包括数据的添加、修改删除和浏览;能够对学生选课进行管理,包括添加学生选课信息、录入成绩;能使用查询功能,快速查看到指定学生的选课信息;能够对学生选课情况进行简单的统计,包括所选的总的课程数、总学分数及平均成绩。

  • 计算机软件技术实习(实验准备)——小型信息管理系统的设计与实现

    ②承办订票业务:根据客户提出的要求(日期、航班号、订票数额)查询该航班票额情况,若尚有余额,则为客户办理订票手续,输出座位号;选课报名: 该功能将允许学生搜索课程并查看机构提供的关于该课程的信息,并可以选择报名。查看课程资料: 该功能将允许教师查看他们教授的课程和选课学生的资料。查看课程资料: 该功能将允许学生查看他们已报名参加的课程资料。课程资料的管理: 该功能将实现对课程资料的增删改查。学生资料的管理: 该功能将实现对学生资料的增删改查。教师资料的管理: 该功能将实现对教师资料的增删改查。

  • java面向对象管理系统_java面向对象员工管理系统

    员工管理系统面向对象--基本类javapublic class Emp {//员工基本属性private int no;//工号private String name;//姓名private String sex;//性别private String major;//职位private double salary;//薪水//默认构造器public Emp() {}//含有参数的构造器public...

  • 面向对象案例:学生管理系统

    软件开发的大致流程 产品经理:将用户的需求,写成产品规格说明文档 程序员:需求分析–>架构设计(概要设计/详细设计)–>编码–>单元(类/函数)测试 测试员:自动化测试 上线/维护 面向对象案例:学生管理系统 目的:通过案例熟悉面向对象的设计思想,掌握Python面向对象编程的语法 需求:实现对学生信息的增加、删除、修改和查询。 架构设计: 界面...

  • Java项目客户信息管理系统——面向对象

    前言 最近重温了面向对象的知识后利用学的知识,写了这个小项目供大家交流。 项目功能 客户管理系统提供了客户信息录入,客户信息修改,客户信息查询,客户信息显示,退出系统等四个模块 信息录入模块 信息查看模块 信息删除模块 信息修改模块 退出系统模块 源代码 utility类 package projectscondexer; import java.util.Scanner; public class Utility { Scanner scan=new Scanner(Syst

  • 开发实例(一)

    概述 为了更好的开始项目的开发,在本节我们将通过一个简单的实例对本次项目中的主要技术进行认识和理解。 任务1.1:建立用户表 任务描述 (1)建立用户表 任务实施 第一步、启动MySQL客户端Navicat(任何客户端软件),添加MySQL数据库: 第二步、连接数据库服务在默认数据库test中新建sys_user表; 任务1.2:创建Spring Boot 项目 任务描述 (1)创建项目 任务实施 第一步、浏览器访问:https://start.spring.io 配置顺序: (1)项目构建工具是

  • 简单的面向对象的学生管理系统

    面向对象的学生管理系统 老师:对学生的增删改查 学生:只能查看自己 进行数据持久化,并将学生的信息导出到excel表格中 做出的目录大致是是如下图所示: 一定要导jar包 Student.java package com.nebula.bean; import java.io.Serializable; //学生类 public class Student implements Serializable{ private static final long serialVersionUID

  • 项目名称:用户信息管理系统的开发与实现

    曲阜师范大学软件学院 [姓名:张忠远] [学号:2014416719] [问题定义]通过java项目连接数据库,建立一个可以代替在数据库操作的用户信息管理系统。 [开发工具]用户信息管理系统是用Eclipse开发工具中开发完成的,基于Java开发语言。它是在Windows系统下,以Oracle数据库为开发平台的数据库可视化信息系统。 [设计过程] 需求分析:随着计算机的迅速发展和信息...

  • 【面向对象】利用python实现的简单学员管理系统

    【面向对象】利用python实现的简单学员管理系统功能描述程序设计类的抽象相关方法的实现主程序框架利用pandas实现csv读取和储存。源代码 功能描述 1.读取合适的csv文件 2.添加学员信息 3.删除学员信息 4.利用姓名查找学员 5.修改某位学员信息 6.打印全部学员信息 7.将修改后的信息存到csv文件中 程序设计 类的抽象 简单分析需求。 程序当中应有一个学员类,其中含姓名、性别和学号属性。 # -*- coding:utf-8 -*- class Students: def __in

  • 面向对象课程设计——类与对象——人员信息管理系统

    人员信息管理系统: 以一个小型公司的人员管理为例,说明类及成员函数的设计。提示: 类的设计: 某小型公司,需要存储雇员的编号、级别、月薪,并显示全部信息。根据这些需求,设计一个类employee,在该类中,包括的数据成员有: 编号(int individualEmpNo) 级别(int grade) 月薪(float accumPay) 成员函数有: 设置编号(void setEmpNo(int...

  • 学习面向对象和面向接口编程的经典教程

    s

  • 实战面向对象_工资管理系统

    /* Employee.h文件 */ # include using namespace std; class Employee { protected: string m_name; int m_time; public: Employee(string name, int time) //构造函数 : m_name(name), m_time(time) { } st

  • 管理平台前端实现

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>管理平台</title> <link rel="stylesheet" href=.

  • 学生信息管理系统(面向对象版本)V3.0

    版本 面向对象版本的学生信息管理系统 第一版: import os # 面向对象的方式分析学生管理管理系统 # 1. 添加学生的功能 # 2. 修改学生的功能 # 3. 删除学生的功能 # 4. 查询学生的功能 # 定义类 # 1. 学生管理系统类 # 2. 学生类 # 分析学生管理系统类的成员 # 1. 属性: 学生列表属性 # 2. 方法:增删改查的行为方法 # 分析学生类的成员 ...

Global site tag (gtag.js) - Google Analytics