Chapter1 Introduction

That is the art and talent involved in programming—reducing complexity to simplicity.

A “bad programmer” is just somebody who fails to reduce the complexity.

So, a “good programmer” should do everything in his power to make what he writes as simple as possible to other programmers. A good programmer creates things that are easy to understand, so that it’s really easy to shake out all the bugs.

The phrase “a computer program,” in the way that most people use it, has two verydistinct definitions:

1. A sequence of instructions given to the computer

2. The actions taken by a computer as the result of being given instructions

The  first definition  is what programmers see when  they are writing a program. The second definition is what users see when they are using a program. The programmer tells the computer, “Display a pig on the screen.” That’s definition 1, some instructions. The computer pushes around a  lot of electricity  that causes a pig  to appear on  the screen. That’s definition 2, the actions taken by the computer. Both the programmer and the user here would say that they are working with “a computer program,” but their experience of it is very different. Programmers work with the words and symbols, while users see only the end result—the actions taken.

感悟:程序员容易陷入自己的惯性思维中,要多站在用户的角度上思考问题,这样设计出的东西才更受欢迎。这里的两个定义非常形象的描述了程序员和用户看待同一程序的截然不同的两个角度。

CHAPTER 2 The Missing Science

Every programmer working on a software project is involved in design. The lead developer  is  in charge of designing  the overall architecture of  the entire program. The senior programmers are in charge of designing their own large areas. And the junior programmers are in charge of designing their parts of the program, even if they’re as simple as one part of one  file. There  is even a certain amount of design  involved  in writing a single line of code.

A designer  should always be willing  to  listen  to  suggestions and  feedback, because programmers are usually smart people who have good ideas. But after considering all the data, any given decision must be made by an individual, not by a group of people.

CHAPTER 3 The Driving Forces of Software Design

Well, there is in fact a single purpose for all software: To help people.

What about software that helps animals or plants? Well, its purpose is really to help people help animals or plants.

People who cannot conceive of helping another person will write bad software—that is, their software won’t help people very much.

In general, this purpose—to help people—is the most important thing to keep in mind when designing software, and defining it allows us now to create and understand a real science of software design.

The goals of a science of software design:

  • To allow us to write software that is as helpful as possible.
  • To allow our software to continue to be as helpful as possible.
  • To design systems that can be created and maintained as easily as possible by their programmers, so that they can be—and continue to be—as helpful as possible.

One thing that’s important to point out about this third goal is the phrase “as easily as possible.” The idea is to make our programs easy to create and maintain, not to make them difficult or complex.

CHAPTER 4 The Future

The primary question that faces software designers is, “How do I make decisions about my software?” When faced with many possible directions you could go in, which option is  the best?  It’s never a question of which decision would be absolutely right versus which decision would be absolutely wrong. Instead, what we want to know is, “Given many possible decisions, which of those decisions are better than others?” It’s a matter of ranking decisions, and then choosing the best decision out of all the possibilities.

The desirability of a change is directly proportional to the value now plus the future value, and inversely proportional to the effort of implementation plus the effort of maintenance.

Your software will have to compete and exist in the future, and the effort of maintenance and number of users will grow. When we ignore the fact that there is a future and make things that “just work” in the present, our software becomes hard to maintain in the future. When software is hard to maintain, it’s hard to make it continue to help people (one of our goals in software design). If you can’t add new features and you can’t fix problems, you eventually end up with “bad software.” It stops helping its users, and it’s full of bugs.

This leads us to the following rule:

The quality level of your design should be proportional to the length of future time in which your system will continue to help people.

The  future  is the most  important thing to consider  in making design decisions. But there is a difference between designing in a way that allows for future change and attempting to predict the future.

So yes, it’s important to remember that there will be a future. But that doesn’t mean you have to predict that future.

CHAPTER 5 Change

The longer your program exists, the more probable it is that any piece of it will have to change.

The point is, you don’t have to try to predict what will change; you just need to know that things will change. Write your software so that it’s as flexible as reasonably possible, and you’ll be able to adapt to whatever future changes do come along.

Don’t write code until you actually need it, and remove any code that isn’t being used.

Design based only on your  immediate, known requirements, without excluding  the possibility of future requirements. If you know for a fact that you need the system to do X, and just X, then just design it to do X, right now. It might do other things that aren’t X in the future, and you should keep that in mind, but for now the system should just do X.

Design based only on your  immediate, known requirements, without excluding  the possibility of future requirements. If you know for a fact that you need the system to do X, and just X, then just design it to do X, right now. It might do other things that aren’t X in the future, and you should keep that in mind, but for now the system should just do X.

This is actually a combination of two methos: one called “incremental development” and  another  called  “incremental  design.”  Incremental  development  is  a method  of building up a whole system by doing work in small pieces. In our list, each step that started with  “Implement” was part of  the  incremental development process.  Incremental design is similarly a method of creating and improving the system’s design in small increments. Each step that started with “Fix up the system’s design” or “Plan” was part of the incremental design process.

CHAPTER 6 Defects and Design

The chance of introducing a defect into your program is proportional to the size of the changes you make to it.

The best design is the one that allows for the most change in the environment with the least change in the software.

Never “fix” anything unless it’s a problem, and you have evidence showing that the problem really exists.

If you fix problems without evidence, you’re probably going to break things. You’re introducing change into your system, which is going to bring new defects along with it. And not  just  that, but you’re wasting your  time  and  adding  complexity  to your program for no reason.

Sometimes a user will report that there’s a bug, when actually it’s the program behaving exactly as you intended it to. In this case, it’s a matter of majority rules. If a significant number of users think that the behavior is a bug, it’s a bug. If only a tiny minority (like one or two) think it’s a bug, it’s not a bug.

The most famous error in this area is what we call “premature optimization.” That is,some developers seem to like to make things go fast, but they spend time optimizing their code before they know that it’s slow!

In any particular system, any piece of information should, ideally, exist only once.

CHAPTER 7 Simplicity

One way or another, you often have to take what you’ve created and make it simpler —you can’t rely on your initial design always being the right one. You have to redesign pieces of the system continuously as new situations and requirements arise.

You may have realized this, but this law tells us the most important thing we can do right now that will reduce the effort of maintenance in the Equation of Software Design —make our code simpler. We don’t have to predict the future to do that; we can just look at our code, see if it is complex, and make it less complex for ourselves right now.

Consistency is a big part of simplicity. If you do something one way in one place, do it that way in every place.

CHAPTER 8 Complexity

Complexity builds on complexity—it’s not just a linear thing. That is, you can’t make assumptions  like: “We have 10 features, so adding 1 more will only add 10 percent more time.” In fact, that one new feature will have to be coordinated with all 10 of your existing features. So, if it takes 10 hours of coding time to implement the feature itself, it may well take another 10 hours of coding time to make the 10 existing features all interact properly with the new feature.

There are other ways to add complexity than just adding features, too. The most common other ways are:

Expanding the purpose of the software

Adding programmers

Changing things that don’t need to be changed

Being locked into bad technologies

Misunderstanding

Poor design or no design

Reinventing the wheel

The basic purpose of any given system that you’re working on should be pretty simple. That helps keep the system as a whole as simple as it can realistically be. But if you start to add features that fulfill some other purpose, things get very complex very quickly.

Another common source of complexity is picking the wrong technology to use in your system—particularly one  that  ends up not holding up well  to  future  requirements

Often, if something is getting very complex, that means there is an error in the design somewhere far below the level where the complexity appears. For example, it’s very difficult to make a car drive fast if it has square wheels. Tuning the engine isn’t going to solve the problem—you need to redesign the car so that its wheels are round.

Any  time  there’s  an  “unsolvable  complexity”  in  your program,  it’s because  there’s something fundamentally wrong with the design. If the problem appears unsolvable at one level, back up and look at what might be underlying the problem.

If somebody comes up to you and says something like, “How do I make this pony fly to the moon?” the question you need to ask is, “What problem are you trying to solve?” You may find out that what this person really needs is to collect some gray rocks. Why he thought he had to fly to the moon, and use a pony to do it, only he may know. People do get confused like this. Ask them what problem they’re trying to solve, though, and a simple solution will start to present itself. For example, in this case, once we understand the problem fully, the solution becomes simple and obvious: he should just walk outside and find some gray rocks—no pony required. So, when things get complex, back up and take a look at the problem you’re trying to solve. Take a really big step back. You are allowed to question everything. Maybe you thought that adding two and two was the only way to get four, and you didn’t think about adding one and three instead, or skipping the addition entirely and just putting four there. The problem is, “How do I get the number four?” Any method of solving that problem is acceptable, so what you need to do is figure out what the best method would be for the situation that you’re in.

If some part of your system is too complex, there is a specific way to fix it—redesign the individual pieces, in small steps. Each fix should be as small as you can safely make it without  introducing further complexity. When you’re going through this process, the greatest danger  is  that you could possibly  introduce more complexity with your fixes. This is why so many redesigns or rewrites ultimately fail—they introduce more complexity than they fix, or they end up being just as complex as the original system was.

When you are working on simplifying your system, you may find that some complexity is hard to avoid,  like the complexity of the underlying hardware. If you run  into an unfixable complexity like this, your goal is to hide the complexity. Put a wrapper around it that is simple for other programmers to use and understand.

You should only rewrite if all of the following are true:

1. You have developed an accurate estimate that shows that rewriting the system will be a more efficient use of  time  than  redesigning  the existing system. Don’t  just guess—do actual experiments with redesigning the existing system to see how it goes. It can be very hard to confront the existing complexity and resolve some piece of  it, but you must actually attempt  this a  few  times before you can know how much effort fixing all of it will require.

2. You have a tremendous amount of time to spend on creating a new system.

3. You are somehow a better designer than the original designer of the system or, if you are  the original designer, your design skills have  improved drastically since you designed the original system.

4. You fully intend to design this new system in a series of simple steps and have users who can give you feedback for each step along the way.

5. You have the resources available to both maintain the existing system and design a new system at the same time. Never stop maintaining a system that is currently in use so that the programmers can rewrite it. Systems must always be maintained if they are in use. And remember that your personal attention is also a resource”that must be taken into account here—do you have enough time available in each day to be a designer on both the new system and the old system simultaneously, if you are going to work on both?

If all of the above points are true, you may be in a situation where it is acceptable to rewrite. Otherwise, the correct thing to do is to handle the complexity of the existing system without a rewrite, by improving the system’s design in a series of simple steps.

CHAPTER 9 Testing

The more recently you’ve tested your software, the more likely it is that it still works. The more environments you’ve tested it in, the more certain you can be that it works in those circumstances. This is part of what we mean when we talk about the “degree” of testing—how many aspects of the software you’ve tested, how recently, and in how many different environments. In general, you could simply say:

Unless you’ve tried it, you don’t know that it works.

Saying “it works”  is actually quite vague,  though—what do you mean by “works”? What you really know when you test is that your software behaves as you intended it to. Thus, you have to know what behavior you intended. That may sound stupid and obvious, but  it’s a critical fact  in testing. You must ask a very precise question with every test, and get a very specific answer. The question could be something like, “What happens when a user presses this button as the first thing he does after the application starts, when the application has never been started before?” And you should be looking for some specific answer, such as, “The application displays a window that says ‘Hello, World!’”

Code Simplicity–The Science of Software Development 书摘的更多相关文章

  1. Software development skills for data scientists

    Software development skills for data scientists Data scientists often come from diverse backgrounds ...

  2. Software Development Engineer - Database Services

    http://stackoverflow.com/jobs/116486/software-development-engineer-database-services-amazon?med=clc& ...

  3. 微软职位内部推荐-Software Development Engineer

    微软近期Open的职位: Job Title: Software Development Engineer Work Location: Suzhou, China The Office 365 Co ...

  4. 敏捷软件工程(agile software development) VS传统软件工程(traditional software development)

    敏捷软件工程(agile software development) VS传统软件工程(traditional software development)      Agile principle  ...

  5. [software development] 需求分析checklist

    [software development] 需求分析checklist // */ // ]]>   [software development] 需求分析checklist Table of ...

  6. 关于敏捷开发方法(Agile Software Development)的阅读笔记

    对“敏捷开发”(Agile Software Development)这个词,我是在这学期邹欣老师<现代程序设计>课上第一次听到的,刚听到时并不知道其具体指什么,只是从字面上直觉其意思应该 ...

  7. FBX Software Development Kit

    FBX Software Development Kit The FBX Software Development Kit (FBX SDK) allows software developers t ...

  8. 微软职位内部推荐-Software Development Engineering II

    微软近期Open的职位: Job Title: Software Development Engineering II Work Location: Suzhou, China Enterprise ...

  9. 微软职位内部推荐-Software Development Engineer 2

    微软近期Open的职位: SDE II Organization Summary: Engineering, Customer interactions & Online (ECO) is l ...

随机推荐

  1. JS的URL编码

    背景 URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号,这是网络标准: 只有字母和数字[-9a-zA-Z].一些特殊符号"$-_.+!*'(),"[不包括双 ...

  2. bootstrap入门-1.可视化布局

    下载地址:http://v3.bootcss.com/getting-started/#download   HTML模板: <!DOCTYPE html> <html> &l ...

  3. C#实现执行多条SQl语句,实现数据库事务

    C#实现执行多条SQl语句,实现数据库事务 在数据库中使用事务的好处,相信大家都有听过银行存款的交易作为事务的一个例子.事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的 ...

  4. 本地json文件的编辑器,node-webkit开发的exe程序

    首发:个人博客,更新&纠错&回复 在昨天的dota契合度计算器中,用到了dota英雄数据和dota玩家数据这两个数据库,为了便于网页应用使用,这两个数据库的存储格式是json,即her ...

  5. C#委托,事件最初浅的和最易看懂的学习笔记

    对于委托和事件,看了不少博文,当时好像都理解了,过了一段时间,又忘记的差不多了.每每如此,感觉自己很笨,记性差,其实是没有深入理解透切,没有按照自己的语言表达出来,当然容易忘记.今天又花了一些时间,好 ...

  6. Ugly Number

    public class Solution { public bool IsUgly(int num) { ) return false; ) return true; *==num){ num = ...

  7. lua 操作中文字符串之截取和长度竖排显示

    前言 在游戏中,我们经常会遇到汉字的多行显示,比如名字竖行显示等.如下图: 为了实现上面的效果,lua实现分行是通过  \n  实现的,所以我们需要取出汉字,然后插入 \n 实现分行效果.还有一种就是 ...

  8. AsyncTask的缺陷和注意事项

    1. AsyncTask 主要是用来处理后台耗时操作,并将数据更新到主线程的一个工具类. AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就 ...

  9. .getClass();

    Java的每个类都带有一个运行时类对象,该Class对象中保存了创建对象所需的所有信息.可以用.class返回此 Object 的运行时类Class对象,也可以用getClass()获得.获得此对象后 ...

  10. AC自动机——Uva 11468 子串

    题目链接:http://vjudge.net/contest/142513#problem/A 题意:给出一些字符和各自对应的选择概率,随机选择L次后将得到一个长度为L的随机字符串S.给出K个模版串, ...