注: 以下内容引自: https://blogs.msdn.microsoft.com/ericlippert/2004/06/14/reading-code-is-hard/

Reading Code Is Hard

★★★★★
★★★★
★★★
★★
 
Eric LippertJune 14, 200426


Escalation Engineer JeremyK asks in his blog this morning:

how do you teach people this “art” of digging deep very quickly into unfamilar code that you had no hand in writing? I myself, I come from a very traditional process of learning how to code, by sitting down and writing it. I am struggling with how to tailor a delivery to focus on reading vs. writing source code. To me the only way you can be truly efficient in this process is by having written code yourself.

No kidding Jeremy -- code is way easier to write than it is to read.

First off, I agree with you that there are very few people who can read code who cannot write code themselves.  It's not like written or spoken natural languages, where understanding what someone else says does not require understanding why they said it that way.  For example, if I were to say something like

"There are two recipes for producing code: a strict and detailed, and a vague and sloppy.  The first produces elegant, tiered wedding cakes, the second, spaghetti."

you would understand what I meant to get across, without having to understand that I'm using the literary techniques of "zero anaphora" and "parallel clauses" to produce a balanced, harmonious effect in the listener/reader.  Heck, you don't even have to know what a "verb" is to understand a sentence!  But with code, it is vitally important that the both intention of the code's author and howthe code produces the intended effect be clear from the code itself.

Therefore, I would turn the question around -- how do we WRITE code that is more easily read by people who need to get up to speed very quickly on the code, but who didn't write any part of it?

Here are some of the things I try to do when writing code so that it can be more easily read:

  • Make the code amenable to tools.  Object browsers and Intellisense are great, but I'll tell you, I'm old school.  If I can't find what I want via grep, I'm not happy.  What makes code greppable?

    • Variables with names like "i" are badness.  You can't easily search code without getting false positives.
    • Avoid making names that are prefixes of other names.  For example, we have a performance marker in our code called "perfExecuteManifest", and another called "perfExecuteManifestInitialize".  Drives me nuts every time I want to grep the source code for the former, I have to wade through all the instances of the latter.
    • Use the same name for “tramp data” in both places.  By tramp data, I mean those variables that you pass to a method only because they need to be passed on to another method.  The two variables are basically the same thing, so it helps if they have the same name.
    • Don't use macros that rename stuff.  If the method is called get_MousePosition then don't declare it with a macro likeGETTER(MousePosition)-- because then I can't grep for the actual function name.
    • Shadowing is evil.  Please don't do it.
  • Pick a consistent naming scheme.  If you're going to use Hungarian, use it consistently and universally, otherwise it becomes an impediment rather than a benefit.  Use Hungarian to document data semantics, not storage types.  Use Hungarian to documentuniversal truths, not temporary conditions.
  • Use assertionsto document preconditions and postconditions.
  • Don't abbreviate English words.  In particular, don't abbreviate them in really weird ways.  In the script engines, the structure that holds a variable name is called NME.  Drives me nuts!  It should be called VariableName.
  • The standard C runtime library is not a paragon of good library design.  Do not emulate it.
  • Don't write "clever" code; the maintenance programmers don't have time to figure out your cleverness when it turns out to be broken.
  • Use the features of the language do to what they were designed to do, not what they can do.  Don't use exceptions as a general flow control mechanism even though you can; use them to report errors.  Don't cast interface pointers to class pointers, even if you know it will work.  Etc.
  • Structure the source code tree in functional units, not in political units.  For example, on my team now the root subdirectories are "Frameworks" and "Integration", which are team names.  Unfortunately, the Frameworks team now owns the Adaptor subdirectory of the Integration directory, which is confusing.  Similarly, the various sub-trees have some subdirectories which are for client side components, some for server side components.  Some for managed components, some for unmanaged components.  Some for in-process components, some for out-of-proc components.  Some for retail components, some for internal testing tools. It's kind of a mess. Of all the possible ways to organize a source tree, the political structure is the least important to the maintenance programmer!

Of course, I haven't actually answered Jeremy's question at all -- how do I debug code that I didn't write?

It depends on what my aim is.  If I just want to dig into a very specific piece of code due to a bug, I'll concentrate on understanding data flow and control flow in the specific scenario I'm debugging.  I'll step through all the code in the debugger, writing down the tree of calls as I go, making notes on which methods are produces and which are consumers of particular data structures.  I'll also keep a watchful eye on the output window, looking for interesting messages going by.  I'll turn on exception trapping, because usually exceptions are where the interesting stuff is, and because they can screw up your stepping pretty fast.  I'll put breakpoints all the heck over the place.   I'll make notes of all the places where my suggestions above are violated, because those are the things that are likely to mislead me.

If I want to understand a piece of code enough to modify it, I'll usually start with the headers, or I'll search for the public methods.  I want to know what does this class implement, what does it extend, what is it for, how does it fit into the larger whole?   I'll try to understand that stuff before I understand how the specific parts are implemented. That takes a lot longer, but you've got to do that due diligence if you're going to be making changes to complex code.

Reading Code Is Hard的更多相关文章

  1. Tips for newbie to read source code

    This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...

  2. Code is not literature

    http://www.gigamonkeys.com/code-reading/ I have started code reading groups at the last two companie ...

  3. Clean Code – Chapter 3: Functions

    Small Blocks and Indenting The blocks within if statements, else statements, while statements, and s ...

  4. 一个简单的 Web 服务器 [未完成]

    最近学习C++,linux和网络编程,想做个小(mini)项目.  就去搜索引擎, 开源中国, Sourceforge上找http server的项目. 好吧,也去了知乎.    知乎上程序员氛围好, ...

  5. [COPY] How to become a hacker

    Engish version copied from here Why This Document? As editor of the Jargon File and author of a few ...

  6. RFID 读写器 Reader Writer Cloner

    RFID读写器的工作原理 RFID的数据采集以读写器为主导,RFID读写器是一种通过无线通信,实现对标签识别和内存数据的读出和写入操作的装置. 读写器又称为阅读器或读头(Reader).查询器(Int ...

  7. Functions

    Small The first rule of functions is that they should be small.The second rule of functions is that ...

  8. fw:学好Python必读的几篇文章

    学好Python必读的几篇文章 from:http://blog.csdn.net/hzxhan/article/details/8555602 分类: python2013-01-30 11:52  ...

  9. 【译】C++工程师需要掌握的10个C++11特性

    原文标题:Ten C++11 Features Every C++ Developer Should Use 原文作者:Marius Bancila 原文地址:codeproject 备注:非直译,带 ...

随机推荐

  1. Zeroc Ice开发环境搭建

    搭建Ice环境 1. Linux(推荐,更接近真实生产环境) 2. Windows(方便学习开发)     下载安装包:https://zeroc.com/downloads (百度网盘链接:http ...

  2. IOS常见的加密方法,常用的MD5和Base64

    iOS代码加密常用加密方式 iOS代码加密常用加密方式,常见的iOS代码加密常用加密方式算法包括MD5加密.AES加密.BASE64加密,三大算法iOS代码加密是如何进行加密的,且看下文 MD5 iO ...

  3. 64位linux下安装ps模拟器ePSxe

    早就想在爱机上玩ps游戏,特别是彩京的1945一代和非常经典的实况足球2002版.在ubuntu64位下可以通过wine模拟的方式运行windows版的ePSxe,但是总觉得差些呢?非原生啊!网上搜了 ...

  4. aside元素

    aside元素用来表示当前页面或文章的附属信息部分,它可以包含与当前页面或主要内容相关的引用.侧边栏.广告.导航条,以及其他类似的有别于主要内容的部分. aside元素主要有以下两种使用方法: 1.包 ...

  5. java并发包分析之———Deque和LinkedBlockingDeque

    一.双向队列Deque   Queue除了前面介绍的实现外,还有一种双向的Queue实现Deque.这种队列允许在队列头和尾部进行入队出队操作,因此在功能上比Queue显然要更复杂.下图描述的是Deq ...

  6. Android 加载GIF图最佳实践

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/75578109 本文出自[赵彦军的博客] 起因 最近在项目中遇到需要在界面上显示一个 ...

  7. Angular5 宏观把控

    1.首先,Angular5相对于Angular4有了一些新的特性: (1)i18n国际化管道: (2)一个组件可以以多个名称导出: (3)使用httpClient: 相比于http,httpClien ...

  8. unity零基础开始学习做游戏(五)看看你的完成度,进度条了解一下?

    -------小基原创,转载请给我一个面子 上回书说道,英雄和魔王都做完了,子弹也能发射了,就是不知道啥时候能干死魔王.那小基得做个血条来展示一下,他离死不远了(•౪• ) 其实血条也可以看作是进度条 ...

  9. spring cloud 入门系列六:使用Zuul 实现API网关服务

    通过前面几次的分享,我们了解了微服务架构的几个核心设施,通过这些组件我们可以搭建简单的微服务架构系统.比如通过Spring Cloud Eureka搭建高可用的服务注册中心并实现服务的注册和发现: 通 ...

  10. SOFA 源码分析 — 泛化调用

    前言 通常 RPC 调用需要客户端使用服务端提供的接口,而具体的形式则是使用 jar 包,通过引用 jar 包获取接口的的具体信息,例如接口名称,方法名称,参数类型,返回值类型. 但也存在一些情况,例 ...