Merc Release 2.1
Sunday 01 August 1993
Merc Release 2.1 星期日 01 八月 1993
Furey mec@shell.portal.com
Hatchet hatchet@uclink.berkeley.edu
Kahn michael@uclink.berkeley.edu
奥利弗 mec@shell.portal.com 霍奇赫特 hatchet@uclink.berkeley.edu 凯恩 michael@uclink.berkeley.edu
===
=== 我在运行一个 Mud 以便学习 C 编程!
Yeah, right. 嗯,是的。
The purpose of this document is to record some of our knowledge, experience and
philosophy. No matter what your level, we hope that this document will help
you become a better software engineer.
本文件的目的是记录我们的一些知识、经验和理念。无论你的水平如何,我们希望这份文件能帮助你成为一名更好的软件工程师。
Remember that engineering is work, and NO document will substitute for your
own thinking, learning and experimentation.
请记住,工程是工作,没有任何文档能替代你自己的思考、学习和实验。
=== How to Learn in the First Place
=== 如何开始学习
(1) Play with something.
(2) Read the documentation on it.
(3) Play with it some more.
(4) Read documentation again.
(5) Play with it some more.
(6) Read documentation again.
(7) Play with it some more.
(8) Read documentation again.
(9) Get the idea?
(1) 玩弄一些东西。 (2) 查看它的文档。 (3) 再玩弄一些。 (4) 再次查看文档。 (5) 再玩弄一些。 (6) 再次查看文档。 (7) 再玩弄一些。 (8) 再次查看文档。 (9) 你明白了吗?
The idea is that your mind can accept only so much
session. Playing with something doesn
does transform data in your head from the
category. Reading documentation doesn
refills your
想象一下,你的大脑在同一会话中只能接受一定量的“新数据”。玩某样东西并不会引入很多新数据,但它确实会将你头脑中的数据从“新”类别转换为“熟悉”类别。阅读文档并不会使任何东西变得“熟悉”,但它会补充你的“新”数据池。
Most people, if they even read documentation in the first place, never return
to it. They come to a certain minimum level of proficiency and then never
learn any more. But modern operating systems, languages, networks, and even
applications simply cannot be learned in a single session. You have to work
through the two-step learning cycle MANY times to master it.
大多数人,即使他们阅读了文档,也不会再回去查看。他们达到一定的熟练程度后就不再学习更多了。但现代操作系统、语言、网络,甚至应用程序是无法在一个会话中学会的。你必须多次经历这个两步学习循环才能掌握它们。
=== The Environment === 环境
Computer: the big or little box that you
from a _manufacturer_ and have a _model_ name. Here is a list of common
manufacturers and models that you
计算机:你用来运行 Merc 的大或小盒子。计算机来自一个“制造商”并有一个“型号”名称。以下是一些你可能会遇到的常见制造商和型号列表:
Manufacturer Model
------------ -----
制造商型号 ------------ -----
Sun Sun-2
Sun Sun-3
Sun Sun-4
DEC Vax 5000
DEC Vax 5900
IBM RS/6000
NeXT NextCube
Sequent Symmetry
Sequent Balance
As far as hardware goes, Merc will run on any 32-bit hardware.
就硬件而言,Merc 可以运行在任何 32 位硬件上。
Operating system: the lowest level program running on your computer. Most
common computers run Unix or some variant of it, such as SunOS, Ultrix,
AIX, Mach, or Dynix. Notice that many of these variants end in
操作系统:计算机上运行的最低级程序。大多数常见的计算机运行 Unix 或其变体,如 SunOS、Ultrix、AIX、Mach 或 Dynix。请注意,许多这些变体以
The two major
illustrious University of California, Berkeley) and System 5 Unix
(developed by Bell Laboratories, the progenitors of Unix).
Unix 的两大“家族”是伯克利 Unix(由著名的加利福尼亚大学伯克利分校开发)和 System 5 Unix(由贝尔实验室开发,贝尔实验室是 Unix 的先驱)。
The most common non-Unix operating system is VMS (a proprietary operating
system from DEC for their VAX computers). In the personal computer world,
you
Macintosh
最常见的非 Unix 操作系统是 VMS(DEC 为他们的 VAX 计算机开发的专有操作系统)。在个人电脑领域,你会发现 MS-DOS、OS/2(用于 IBM PC 及其兼容机)和 MacOS(用于苹果 Macintosh)。
GET THIS STRAIGHT:
family of computers from DEC. There are plenty of Vax
there are even more Vax
running Unix have a lot more in common with other machines running
Unix than they have with Vax
注意:VAX 不是一个操作系统。它是 DEC 开发的一系列计算机的名字。运行 VMS 的 Vax 有很多,而运行伯克利 Unix 或 Ultrix 的 Vax 则更多。运行 Unix 的 Vax 与运行 VMS 的 Vax 相比,与运行 Unix 的其他机器有更多的共同点。
As far as operating systems go, Merc will run on Unix or Unix variants with
TCP/IP networking compatible with Berkeley Unix. It will also run, in
single-user mode only, on MS-DOS. With a reasonable amount of work, Merc
can be ported to any operating system that provides TCP service for telnet
connections.
就操作系统而言,Merc 可以在兼容伯克利 Unix 的 Unix 或 Unix 变体上运行,这些变体具有 TCP/IP 网络。它还可以在单用户模式下运行在 MS-DOS 上。通过合理的努力,Merc 可以移植到任何提供 telnet 连接 TCP 服务的操作系统上。
Languages: Merc is written in C. ANSI (the American National Standards
Institute) has a specification for the C language, and Merc is written in
Ansi Standard C.
语言:Merc 是用 C 语言编写的。美国国家标准学会(ANSI)为 C 语言制定了规范,Merc 是用 ANSI 标准 C 编写的。
The most popular compiler for Ansi Standard C is the Gnu
produced by the Free Software Foundation. It
ftp from prep.ai.mit.edu. Merc compiles just fine with Gcc 1.38, so
you can probably use 1.42 and skip the much larger 2.X versions.
最流行的 ANSI 标准 C 编译器是自由软件基金会(Free Software Foundation)生产的 Gnu
You don
come with an Ansi C compiler already. So do NeXT machines (the standard
work.
你不需要使用 gcc。运行 AIX 操作系统的 IBM RS/6000 机器和 NeXT 机器都自带 ANSI C 编译器(NeXT 的标准
Unfortunately, there are still many machines out there without an Ansi
standard C compiler. (Sun is the worst offender in this regard). You
can attempt to compile Merc with a non-Ansi (traditional) C compiler by
using the
不幸的是,仍然有很多机器没有 ANSI 标准 C 编译器。(Sun 在这方面是最糟糕的)。你可以尝试使用非 ANSI(传统)C 编译器通过使用
If you don
as its operating system, and whether the C compiler is Ansi or non-Ansi, then
you need to find out.
如果不知道你的电脑制造商、型号、操作系统,以及 C 编译器是 ANSI 还是非 ANSI 的,那么你需要查一查。
=== Basic Unix Tools === 基本的 Unix 工具
but learn the hell out of it
you should know EVERY command in your editor
allows you to goto functions by name in any source file
get someone to show you, or dig it out of
These are the basic day-in day-out development tools. Developing without
knowing how to use ALL of these well is like driving a car without knowing how
to change gears.
这些是基本的日常开发工具。不了解如何很好地使用这些工具就像开车时不换挡一样。
=== Debugging: Theory === 调试:理论
Debugging is a science. You formulate a hypothesis, make predictions based on
the hypothesis, run the program and provide it experimental input, observe its
behavior, and confirm or refute the hypothesis.
调试是一门科学。你提出一个假设,根据假设做出预测,运行程序并提供实验输入,观察其行为,然后验证或反驳假设。
A good hypothesis is one which makes surprising predictions which then come
true; predictions that other hypotheses don
一个好的假设是那些做出令人惊讶的预测,而其他假设没有做出的预测。
The first step in debugging is not to write bugs in the first place. This
sounds obvious, but sadly, is all too often ignored.
调试的第一步不是一开始就写入错误。这听起来显而易见,但不幸的是,往往被忽视。
If you build a program, and you get ANY errors or ANY warnings, you should fix
them before continuing. C was designed so that many buggy ways of writing code
are legal, but will draw warnings from a suitably smart compiler (such as
with the
and to fix the code that generates them, but it takes hours to find bugs
otherwise.
如果你编写了一个程序,并且得到了任何错误或任何警告,你应该在继续之前修复它们。C 语言的设计使得许多错误的代码编写方式是合法的,但会被一个足够智能的编译器(例如启用了
should desk check your code before even compiling it, and desk-check it again
periodically to keep it fresh in mind and find new errors. If you have someone
in your group whose ONLY job it is to desk-check other people
person will find and fix more bugs than everyone else combined.
在 1993 年,"桌面检查"(代码校对)几乎是一种失传的艺术。太糟糕了。你应该在编译代码之前对其进行桌面检查,并定期再次进行桌面检查以保持记忆并发现新的错误。如果你团队中有一个人的唯一工作就是对其他人的代码进行桌面检查,那么这个人发现并修复的错误会比其他人加起来还要多。
One can desk-check several hundred lines of code per hour. A top-flight
software engineer will write, roughly, 99% accurate code on the first pass,
which still means one bug per hundred lines. And you are not top flight.
So ... you will find several bugs per hour by desk checking. This is a very
rapid bug fixing technique. Compare that to all the hours you spend screwing
around with broken programs trying to find ONE bug at a time.
一个人每小时可以检查几百行代码。顶级的软件工程师在第一次编写时大约会写出 99%准确的代码,这意味着每一百行代码中大约有一个错误。而你并不顶级。因此……你通过代码检查每小时会发现几个错误。这是一种非常快速的错误修复技术。将其与你花费在尝试一次找到一个错误的损坏程序上的所有时间相比。
The next technique beyond desk-checking is the time-honored technique of
inserting
values. Within Merc code, you can call
interesting values at interesting times. Where and when to dump these values
is an art, which you will learn only with practice.
代码检查之后的下一个技术是历史悠久的在代码中插入
If you don
is the time to learn. On Unix, type the command
about the
from
如果你还不知道如何在操作系统中重定向输出,现在是学习的时候了。在 Unix 中,输入命令
Ultimately, you cannot fix a program unless you understand how it
in the first place. Powerful debugging tools will help you collect data, but
they can
can do that.
从根本上说,除非你首先了解程序是如何运行的,否则你无法修复它。强大的调试工具可以帮助你收集数据,但它们无法解释这些数据,也无法解决根本问题。只有你能做到这一点。
When you find a bug ... your first impulse will be to change the code, kill the
manifestation of the bug, and declare it fixed. Not so fast! The bug you
observe is often just the symptom of a deeper bug. You should keep pursuing
the bug, all the way down. You should grok the bug and cherish it in fullness
before causing its discorporation.
当你发现一个错误时……你的第一反应可能是修改代码,消灭错误的表现形式,并宣布问题已经解决。等等!你观察到的错误通常是更深层次错误的症状。你应该继续追踪这个错误,直到找到根本原因。你应该彻底理解这个错误,并在消除它之前珍惜它。
Also, when finding a bug, ask yourself two questions:
programming habits led to the introduction of the bug in the first place?
And:
this?
当发现错误时,问自己两个问题:‘是什么设计和编程习惯导致了这个错误的引入?’以及:‘有哪些习惯可以系统地防止这种错误的引入?’
=== Debugging: Tools === 调试:工具
When a Unix process accesses an invalid memory location, or (more rarely)
executes an illegal instruction, or (even more rarely) something else goes
wrong, the Unix operating system takes control. The process is incapable of
further execution and must be killed. Before killing the process, however, the
operating system does something for you: it opens a file named
writes the entire data space of the process into it.
当一个 Unix 进程访问无效的内存位置,或者(更罕见地)执行非法指令,或者(更罕见地)其他事情出错时,Unix 操作系统会接管。该进程无法继续执行并必须被终止。然而,在终止进程之前,操作系统会为你做一件事:它会打开一个名为
Thus,
It
have rendered your process unable to continue.
因此,“dump 核心”并不是问题的原因,甚至也不是问题的结果。这是操作系统为了帮助你找出导致进程无法继续的致命问题而做的事情。
One reads a
Unix are
one starts a debugger like this:
人们用调试器读取“core”文件。在 Unix 中最常用的两个调试器是“adb”和“gdb”,偶尔也会用到“dbx”。通常启动调试器的方式是:‘adb merc’ 或 ‘gdb merc core’。
The first thing, and often the only thing, you need to do inside the debugger
is take a stack trace. In
the command is
program was in when it crashed, and what functions were calling it. The
debugger will also list the arguments to these functions. Interpreting these
arguments, and using more advanced debugger features, requires a fair amount of
knowledge about assembly language programming.
调试器中你通常需要做的第一件事,也是唯一一件事,就是获取堆栈跟踪。在
If you have access to a program named
如果你可以使用一个名为
=== Profiling === 代码剖析
Here is how to profile a program:
这是如何剖析一个程序:
(1) Remove all the .o files and the
删除所有的.o 文件和
rm *.o
(2) Edit your makefile, and change the PROF= line:
(2) 编辑你的 Makefile,并将 PROF=行改为:
PROF = -p
(3) Remake merc: (3) 重制 merc:
make
(4) Run merc as usual. Shutdown the game with shutdown when you have run long
enough to get a good profiling base. If you crash the game, or kill the
process externally, you won
(4) 正常运行 merc。使用 shutdown 命令关闭游戏,以获得良好的性能基线数据。如果你在游戏中遇到崩溃,或者外部杀进程,将无法获得性能信息。
(5) Run the
(5) 运行
prof merc > prof.out
(6) Read prof.out. Run
(6) 阅读 prof.out。运行
For advanced profiling, you can use
which lists exactly how many times any function calls any other function. This
information is valuable for debugging as well as performance analysis.
对于高级性能分析,您可以在步骤 (2) 中使用
Availability of
Unix system has
=== Schedule versus Features versus Quality
=== 计划 versus 功能 versus 质量
Now for a few words on project management.
现在让我们谈谈项目管理。
Sooner or later, almost any project faces a trade-off between schedule,
features, and quality. Consider a student writing a term paper on the last
night. He has three unpalatable choices: he can turn it in late (miss the
schedule). He can turn in a shorter paper that doesn
(reduce the features). Or he can churn out gibberish (lower the quality).
在任何时候,几乎任何项目都会面临计划、功能和质量之间的权衡。考虑一个学生在最后一天写一篇学期论文。他有三个不愉快的选择:他可以推迟提交(错过计划)。他可以提交一篇较短的论文,不涵盖所有内容(减少功能)。或者他可以产出一堆胡言乱语(降低质量)。
Similarly in a software project, one often has a choice between making the
release date, or dropping features, or shipping everything on time and
hoping that it works (it usually doesn
同样,在软件项目中,人们往往可以在按时发布、减少功能或希望一切都能正常工作(通常不会)之间做出选择。
The most important thing to realize about this decision is that it IS a
decision. One can
If you don
decision.
关于这个决定,最重要的是它确实是一个决定。不能通过希望奇迹发生来逃避它。如果你不主动做出反应,外部环境将会决定这个决定。
Ok, so suppose you are faced with the trade-off and go for a schedule slip.
Don
wish you had taken just a little more time later. If you say
need another day, so I
that what you
to slip a large block of time once then to slip day-by-day or hour-by-hour
repeatedly.
好的,所以假设你面临时间表推迟的选择,那就推迟一个显著的时间段。如果你说“我只要解决这个问题,尽快完成”,那么很可能你会后悔没有多花一点时间。如果你说“我认为我需要多一天,所以推迟一周”,那么在一周结束时,你很可能已经完成了工作。一次性推迟一个大时间段比一天天或一小时小时地推迟要好。
If you go for dropping features, again, carve off a big hunk. Don
timid and pretend that you
little spare time.
lessened requirements for all the savings you can!
如果你选择减少功能,那就一次性砍掉一大块。不要胆小,假装你会在有空余时间时做那项工作。那个项目功能已经不存在了,利用减少的需求来节省尽可能多的时间!
I can
my last choice for what to drop on a project.
我无法提供很多关于如何降低质量的建议,因为这是我总是最后选择要舍弃的东西。
=== Sleeping === 睡觉
Simple and obvious, but true ... engineering takes an alert mind.
简单而显而易见,但却是事实……工程需要一个清醒的头脑。
It
problem. One can get into a
with the problem, and the work just pours out, hour after hour. Many
writers report that they watch a story take place, and just transcribe
what they see, pounding out page after page of text. Many software
engineers have experienced a similar feeling, where the code appears
to arise spontaneously as they watch themselves type.
很容易,也很有诱惑力,连续投入很多时间去解决一个问题。人们可能会进入一种“心流”状态,大脑被问题填满,工作一小时接一小时地进行。许多作家报告说,他们就像观看故事的发生,然后将其记录下来,一页接一页地敲出文字。许多软件工程师也有类似的感觉,他们看着自己打字,代码似乎自发地出现。
I believe most real work gets done in this state.
我认为大多数真正的工作就是在这种状态下完成的。
My experience, however, is that the
gradually. Without ever noticing a change, I notice that new work isn
flowing out of my hands anymore, that I
up mistakes I made just a few moments ago. Instead of ideas flashing
confidently through my mind, doubts and questions arise.
然而,我的经验是,‘流动’时期可以以一种微妙而渐进的方式结束。我甚至没有注意到任何变化,但我会发现新的工作不再从我的手中流出,我会花费大量时间去修正几分钟前犯下的错误。不再有自信的想法在我脑海中闪现,而是出现了疑虑和问题。
At this point there is a temptation to throw some more hours at the problem.
night until I figure this out?
这时,有一种倾向是投入更多的时间来解决这个问题。‘我已经在这里了,而且我之前做得很多,为什么我不再待一整夜直到解决这个问题呢?’这可是个陷阱!不要这么做!
Instead, I suggest: go home, eat, shower, sleep, put yourself back together
again. Resume the next day. While you sleep, your mind will work on the
problem anyways, and you
more done between 10:00 am and 2:00 pm the next day, then if you stayed up
between midnight and 10:00 am.
相反,我建议:回家,吃饭,洗澡,睡觉,让自己重新振作起来。第二天再继续。在你睡觉的时候,你的大脑仍然会继续思考这个问题,你可能会在第二天醒来时有了新的想法。第二天上午 10 点到下午 2 点之间,你会比在午夜到上午 10 点之间工作更有效率。
There is a problem with this strategy: remotivating yourself in the morning.
If the project is one of your choice, that
something you have to do but don
problem versus the very low productivity of working without sleep.
这种策略有一个问题:早上重新激励自己。如果项目是你选择的,通常这不是问题。如果这是一个你必须完成但又不喜欢的任务,你必须权衡重新激励自己与没有睡眠的非常低的生产力之间的关系。
=== Books for Serious Programmers
=== 严肃程序员的书籍
Out of all the thousands of books out there, three stand out:
在所有成千上万的书籍中,有三本脱颖而出:
Kernighan and Plaugher, _The Elements of Programming Style_.
肯尼高安和普拉格尔,《编程风格要素》。
Kernighan and Ritchie, _The C Programming Language_.
肯尼高安和里奇,《C 程序设计语言》。
Brooks, _The Mythical Man Month_
布鲁克斯,_人月神话_