├── .gitignore
├── LANGS.md
├── README.md
├── en
├── 1-Beginner
│ ├── Personal-Skills
│ │ ├── 01-Learn To Debug.md
│ │ ├── 02-How to Debug by Splitting the Problem Space.md
│ │ ├── 03-How to Remove an Error.md
│ │ ├── 04-How to Debug Using a Log.md
│ │ ├── 05-How to Understand Performance Problems.md
│ │ ├── 06-How to Fix Performance Problems.md
│ │ ├── 07-How to Optimize Loops.md
│ │ ├── 08-How to Deal with IO Expense.md
│ │ ├── 09-How to Manage Memory.md
│ │ ├── 10-How to Deal with Intermittent Bugs.md
│ │ ├── 11-How to Learn Design Skills.md
│ │ └── 12-How to Conduct Experiments.md
│ ├── README.md
│ └── Team-Skills
│ │ ├── 01-Why Estimation is Important.md
│ │ ├── 02-How to Estimate Programming Time.md
│ │ ├── 03-How to Find Out Information.md
│ │ ├── 04-How to Utilize People as Information Sources.md
│ │ ├── 05-How to Document Wisely.md
│ │ ├── 06-How to Work with Poor Code.md
│ │ ├── 07-How to Use Source Code Control.md
│ │ ├── 08-How to Unit Test.md
│ │ ├── 09-Take Breaks when Stumped.md
│ │ ├── 10-How to Recognize When to Go Home.md
│ │ └── 11-How to Deal with Difficult People.md
├── 2-Intermediate
│ ├── Judgment
│ │ ├── 01-How to Tradeoff Quality Against Development Time.md
│ │ ├── 02-How to Manage Software System Dependence.md
│ │ ├── 03-How to Decide if Software is Too Immature.md
│ │ ├── 04-How to Make a Buy vs Build Decision.md
│ │ ├── 05-How to Grow Professionally.md
│ │ ├── 06-How to Evaluate Interviewees.md
│ │ ├── 07-How to Know When to Apply Fancy Computer Science.md
│ │ └── 08-How to Talk to Non-Engineers.md
│ ├── Personal-Skills
│ │ ├── 01-How to Stay Motivated.md
│ │ ├── 02-How to be Widely Trusted.md
│ │ ├── 03-How to Tradeoff Time vs Space.md
│ │ ├── 04-How to Stress Test.md
│ │ ├── 05-How to Balance Brevity and Abstraction.md
│ │ ├── 06-How to Learn New Skills.md
│ │ ├── 07-Learn to Type.md
│ │ ├── 08-How to Do Integration Testing.md
│ │ ├── 09-Communication Languages.md
│ │ ├── 10-Heavy Tools.md
│ │ └── 11-How to analyze data.md
│ ├── README.md
│ └── Team-Skills
│ │ ├── 01-How to Manage Development Time.md
│ │ ├── 02-How to Manage Third-Party Software Risks.md
│ │ ├── 03-How to Manage Consultants.md
│ │ ├── 04-How to Communicate the Right Amount.md
│ │ └── 05-How to Disagree Honestly and Get Away with It.md
├── 3-Advanced
│ ├── Compromising-Wisely
│ │ ├── 01-How to Fight Schedule Pressure.md
│ │ ├── 02-How to Understand the User.md
│ │ └── 03-How to Get a Promotion.md
│ ├── README.md
│ ├── Serving-Your-Team
│ │ ├── 01-How to Develop Talent.md
│ │ ├── 02-How to Choose What to Work On.md
│ │ ├── 03-How to Get the Most From Your Teammates.md
│ │ ├── 04-How to Divide Problems Up.md
│ │ ├── 05-How to Handle Boring Tasks.md
│ │ ├── 06-How to Gather Support for a Project.md
│ │ ├── 07-How to Grow a System.md
│ │ ├── 08-How to Communicate Well.md
│ │ ├── 09-How to Tell People Things They Don't Want to Hear.md
│ │ ├── 10-How to Deal with Managerial Myths.md
│ │ └── 11-How to Deal with Organizational Chaos.md
│ └── Technical-Judgment
│ │ ├── 01-How to Tell the Hard From the Impossible.md
│ │ ├── 02-How to Utilize Embedded Languages.md
│ │ └── 03-Choosing Languages.md
├── 5-Bibliography.md
├── 6-History.md
├── 7-Contributions.md
├── GLOSSARY.md
├── LICENSE.md
├── README.md
└── SUMMARY.md
└── zh
├── 1-Beginner
├── Personal-Skills
│ ├── 01-Learn To Debug.md
│ ├── 02-How to Debug by Splitting the Problem Space.md
│ ├── 03-How to Remove an Error.md
│ ├── 04-How to Debug Using a Log.md
│ ├── 05-How to Understand Performance Problems.md
│ ├── 06-How to Fix Performance Problems.md
│ ├── 07-How to Optimize Loops.md
│ ├── 08-How to Deal with IO Expense.md
│ ├── 09-How to Manage Memory.md
│ ├── 10-How to Deal with Intermittent Bugs.md
│ ├── 11-How to Learn Design Skills.md
│ └── 12-How to Conduct Experiments.md
├── README.md
└── Team-Skills
│ ├── 01-Why Estimation is Important.md
│ ├── 02-How to Estimate Programming Time.md
│ ├── 03-How to Find Out Information.md
│ ├── 04-How to Utilize People as Information Sources.md
│ ├── 05-How to Document Wisely.md
│ ├── 06-How to Work with Poor Code.md
│ ├── 07-How to Use Source Code Control.md
│ ├── 08-How to Unit Test.md
│ ├── 09-Take Breaks when Stumped.md
│ ├── 10-How to Recognize When to Go Home.md
│ └── 11-How to Deal with Difficult People.md
├── 2-Intermediate
├── Judgment
│ ├── 01-How to Tradeoff Quality Against Development Time.md
│ ├── 02-How to Manage Software System Dependence.md
│ ├── 03-How to Decide if Software is Too Immature.md
│ ├── 04-How to Make a Buy vs Build Decision.md
│ ├── 05-How to Grow Professionally.md
│ ├── 06-How to Evaluate Interviewees.md
│ ├── 07-How to Know When to Apply Fancy Computer Science.md
│ └── 08-How to Talk to Non-Engineers.md
├── Personal-Skills
│ ├── 01-How to Stay Motivated.md
│ ├── 02-How to be Widely Trusted.md
│ ├── 03-How to Tradeoff Time vs Space.md
│ ├── 04-How to Stress Test.md
│ ├── 05-How to Balance Brevity and Abstraction.md
│ ├── 06-How to Learn New Skills.md
│ ├── 07-Learn to Type.md
│ ├── 08-How to Do Integration Testing.md
│ ├── 09-Communication Languages.md
│ ├── 10-Heavy Tools.md
│ └── 11-How to analyze data.md
├── README.md
└── Team-Skills
│ ├── 01-How to Manage Development Time.md
│ ├── 02-How to Manage Third-Party Software Risks.md
│ ├── 03-How to Manage Consultants.md
│ ├── 04-How to Communicate the Right Amount.md
│ └── 05-How to Disagree Honestly and Get Away with It.md
├── 3-Advanced
├── Compromising-Wisely
│ ├── 01-How to Fight Schedule Pressure.md
│ ├── 02-How to Understand the User.md
│ └── 03-How to Get a Promotion.md
├── README.md
├── Serving-Your-Team
│ ├── 01-How to Develop Talent.md
│ ├── 02-How to Choose What to Work On.md
│ ├── 03-How to Get the Most From Your Teammates.md
│ ├── 04-How to Divide Problems Up.md
│ ├── 05-How to Handle Boring Tasks.md
│ ├── 06-How to Gather Support for a Project.md
│ ├── 07-How to Grow a System.md
│ ├── 08-How to Communicate Well.md
│ ├── 09-How to Tell People Things They Don't Want to Hear.md
│ ├── 10-How to Deal with Managerial Myths.md
│ └── 11-How to Deal with Organizational Chaos.md
└── Technical-Judgment
│ ├── 01-How to Tell the Hard From the Impossible.md
│ ├── 02-How to Utilize Embedded Languages.md
│ └── 03-Choosing Languages.md
├── 4-Glossary.md
├── 5-Bibliography.md
├── 6-History.md
├── 7-Contributions.md
├── LICENSE.md
├── README.md
└── SUMMARY.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node rules:
2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
3 | .grunt
4 |
5 | ## Dependency directory
6 | ## Commenting this out is preferred by some people, see
7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
8 | node_modules
9 |
10 | # Book build output
11 | _book
12 |
13 | # eBook build output
14 | *.epub
15 | *.mobi
16 | *.pdf
17 |
--------------------------------------------------------------------------------
/LANGS.md:
--------------------------------------------------------------------------------
1 | * [English](en/)
2 | * [Chinese](zh/)
3 | [//]: # (Version:1.0.0)
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/01-Learn To Debug.md:
--------------------------------------------------------------------------------
1 | # Learn to Debug
2 | [//]: # (Version:1.0.0)
3 | Debugging is the cornerstone of being a programmer. The first meaning of the verb "debug" is to remove errors, but the meaning that really matters is to see into the execution of a program by examining it. A programmer that cannot debug effectively is blind.
4 |
5 | Idealists, those who think design, analysis, complexity theory, and the like are more fundamental than debugging, are not working programmers. The working programmer does not live in an ideal world. Even if you are perfect, you are surrounded by and must interact with code written by major software companies, organizations like GNU, and your colleagues. Most of this code is imperfect and imperfectly documented. Without the ability to gain visibility into the execution of this code, the slightest bump will throw you permanently. Often this visibility can be gained only by experimentation: that is, debugging.
6 |
7 | Debugging is about the running of programs, not programs themselves. If you buy something from a major software company, you usually don't get to see the program. But there will still arise places where the code does not conform to the documentation (crashing your entire machine is a common and spectacular example), or where the documentation is mute. More commonly, you create an error, examine the code you wrote, and have no clue how the error can be occurring. Inevitably, this means some assumption you are making is not quite correct or some condition arises that you did not anticipate. Sometimes, the magic trick of staring into the source code works. When it doesn't, you must debug.
8 |
9 | To get visibility into the execution of a program you must be able to execute the code and observe something about it. Sometimes this is visible, like what is being displayed on a screen, or the delay between two events. In many other cases, it involves things that are not meant to be visible, like the state of some variables inside the code, which lines of code are actually being executed, or whether certain assertions hold across a complicated data structure. These hidden things must be revealed.
10 |
11 | The common ways of looking into the ‘innards’ of an executing program can be categorized as:
12 |
13 | - Using a debugging tool,
14 | - Printlining - Making a temporary modification to the program, typically adding lines that print information out, and
15 | - Logging - Creating a permanent window into the programs execution in the form of a log.
16 |
17 | Debugging tools are wonderful when they are stable and available, but printlining and logging are even more important. Debugging tools often lag behind language development, so at any point in time they may not be available. In addition, because the debugging tool may subtly change the way the program executes it may not always be practical. Finally, there are some kinds of debugging, such as checking an assertion against a large data structure, that require writing code and changing the execution of the program. It is good to know how to use debugging tools when they are stable, but it is critical to be able to employ the other two methods.
18 |
19 | Some beginners fear debugging when it requires modifying code. This is understandable - it is a little like exploratory surgery. But you have to learn to poke at the code and make it jump; you have to learn to experiment on it and understand that nothing that you temporarily do to it will make it worse. If you feel this fear, seek out a mentor - we lose a lot of good programmers at the delicate onset of their learning to this fear.
20 |
21 | Next [How to Debug by Splitting the Problem Space](02-How to Debug by Splitting the Problem Space.md)
22 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/02-How to Debug by Splitting the Problem Space.md:
--------------------------------------------------------------------------------
1 | # How to Debug by Splitting the Problem Space
2 | [//]: # (Version:1.0.0)
3 | Debugging is fun, because it begins with a mystery. You think it should do something, but instead it does something else. It is not always quite so simple---any examples I can give will be contrived compared to what sometimes happens in practice. Debugging requires creativity and ingenuity. If there is a single key to debugging it is to use the divide and conquer technique on the mystery.
4 |
5 | Suppose, for example, you created a program that should do ten things in a sequence. When you run it, it crashes. Since you didn't program it to crash, you now have a mystery. When you look at the output, you see that the first seven things in the sequence were run successfully. The last three are not visible from the output, so now your mystery is smaller: ‘It crashed on thing #8, #9, or #10.’
6 |
7 | Can you design an experiment to see which thing it crashed on? Sure. You can use a debugger or we can add printline statements (or the equivalent in whatever language you are working in) after #8 and #9. When we run it again, our mystery will be smaller, such as ‘It crashed on thing #9.’ I find that bearing in mind exactly what the mystery is at any point in time helps keep one focused. When several people are working together under pressure on a problem it is easy to forget what the most important mystery is.
8 |
9 | The key to divide and conquer as a debugging technique is the same as it is for algorithm design: as long as you do a good job splitting the mystery in the middle, you won't have to split it too many times, and you will be debugging quickly. But what is the middle of a mystery? This is where true creativity and experience comes in.
10 |
11 | To a true beginner, the space of all possible errors looks like every line in the source code. You don't have the vision you will later develop to see the other dimensions of the program, such as the space of executed lines, the data structure, the memory management, the interaction with foreign code, the code that is risky, and the code that is simple. For the experienced programmer, these other dimensions form an imperfect but very useful mental model of all the things that can go wrong. Having that mental model is what helps one find the middle of the mystery effectively.
12 |
13 | Once you have evenly subdivided the space of all that can go wrong, you must try to decide in which space the error lies. In the simple case where the mystery is: ‘Which single unknown line makes my program crash?’, you can ask yourself: ‘Is the unknown line executed before or after this line that I judge to be executed in the middle of the running program?’ Usually you will not be so lucky as to know that the error exists in a single line, or even a single block. Often the mystery will be more like: ‘Either there is a pointer in that graph that points to the wrong node, or my algorithm that adds up the variables in that graph doesn't work.’ In that case you may have to write a small program to check that the pointers in the graph are all correct in order to decide which part of the subdivided mystery can be eliminated.
14 |
15 | Next [How to Remove an Error](03-How to Remove an Error.md)
16 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/03-How to Remove an Error.md:
--------------------------------------------------------------------------------
1 | # How to Remove an Error
2 | [//]: # (Version:1.0.0)
3 | I've intentionally separated the act of examining a program's execution from the act of fixing an error. But of course, debugging does also mean removing the bug. Ideally you will have perfect understanding of the code and will reach an ‘A-Ha!’ moment where you perfectly see the error and how to fix it. But since your program will often use insufficiently documented systems into which you have no visibility, this is not always possible. In other cases the code is so complicated that your understanding cannot be perfect.
4 |
5 | In fixing a bug, you want to make the smallest change that fixes the bug. You may see other things that need improvement; but don't fix those at the same time. Attempt to employ the scientific method of changing one thing and only one thing at a time. The best process for this is to be able to easily reproduce the bug, then put your fix in place, and then rerun the program and observe that the bug no longer exists. Of course, sometimes more than one line must be changed, but you should still conceptually apply a single atomic change to fix the bug.
6 |
7 | Sometimes, there are really several bugs that look like one. It is up to you to define the bugs and fix them one at a time. Sometimes it is unclear what the program should do or what the original author intended. In this case, you must exercise your experience and judgment and assign your own meaning to the code. Decide what it should do, and comment it or clarify it in some way and then make the code conform to your meaning. This is an intermediate or advanced skill that is sometimes harder than writing the original function in the first place, but the real world is often messy. You may have to fix a system you cannot rewrite.
8 |
9 | Next [How to Debug Using a Log](04-How to Debug Using a Log.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/04-How to Debug Using a Log.md:
--------------------------------------------------------------------------------
1 | # How to Debug Using a Log
2 | [//]: # (Version:1.0.0)
3 | *Logging* is the practice of writing a system so that it produces a sequence of informative records, called a log. *Printlining* is just producing a simple, usually temporary, log. Absolute beginners must understand and use logs because their knowledge of programming is limited; system architects must understand and use logs because of the complexity of the system. The amount of information that is provided by the log should be configurable, ideally while the program is running. In general, logs offer three basic advantages:
4 |
5 | - Logs can provide useful information about bugs that are hard to reproduce (such as those that occur in the production environment but that cannot be reproduced in the test environment).
6 | - Logs can provide statistics and data relevant to performance, such as the time passing between statements.
7 | - When configurable, logs allow general information to be captured in order to debug unanticipated specific problems without having to modify and/or redeploy the code just to deal with those specific problems.
8 |
9 | The amount to output into the log is always a compromise between information and brevity. Too much information makes the log expensive and produces *scroll blindness*, making it hard to find the information you need. Too little information and it may not contain what you need. For this reason, making what is output configurable is very useful. Typically, each record in the log will identify its position in the source code, the thread that executed it if applicable, the precise time of execution, and, commonly, an additional useful piece of information, such as the value of some variable, the amount of free memory, the number of data objects, etc. These log statements are sprinkled throughout the source code, particularly at major functionality points and around risky code. Each statement can be assigned a level and will only output a record if the system is currently configured to output that level. You should design the log statements to address problems that you anticipate. Anticipate the need to measure performance.
10 |
11 | If you have a permanent log, printlining can now be done in terms of the log records, and some of the debugging statements will probably be permanently added to the logging system.
12 |
13 | Next [How to Understand Performance Problems](05-How to Understand Performance Problems.md)
14 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/05-How to Understand Performance Problems.md:
--------------------------------------------------------------------------------
1 | # How to Understand Performance Problems
2 | [//]: # (Version:1.0.0)
3 | Learning to understand the performance of a running system is unavoidable for the same reason that learning debugging is. Even if you understand perfectly precisely the cost of the code you write, your code will make calls into other software systems that you have little control over or visibility into. However, in practice performance problems are a little different and a little easier than debugging in general.
4 |
5 | Suppose that you or your customers consider a system or a subsystem to be too slow. Before you try to make it faster, you must build a mental model of why it is slow. To do this you can use a profiling tool or a good log to figure out where the time or other resources are really being spent. There is a famous dictum that 90% of the time will be spent in 10% of the code. I would add to that the importance of input/output expense (I/O) to performance issues. Often most of the time is spent in I/O in one way or another. Finding the expensive I/O and the expensive 10% of the code is a good first step to building your mental model.
6 |
7 | There are many dimensions to the performance of a computer system, and many resources consumed. The first resource to measure is *wall-clock time*, the total time that passes for the computation. Logging *wall-clock time* is particularly valuable because it can inform about unpredictable circumstances that arise in situations where other profiling is impractical. However, this may not always represent the whole picture. Sometimes something that takes a little longer but doesn't burn up so many processor seconds will be much better in the computing environment you actually have to deal with. Similarly, memory, network bandwidth, database or other server accesses may, in the end, be far more expensive than processor seconds.
8 |
9 | Contention for shared resources that are synchronized can cause deadlock and starvation. Deadlock is the inability to proceed because of improper synchronization or resource demands. Starvation is the failure to schedule a component properly. If it can be at all anticipated, it is best to have a way of measuring this contention from the start of your project. Even if this contention does not occur, it is very helpful to be able to assert that with confidence.
10 |
11 | Next [How to Fix Performance Problems](06-How to Fix Performance Problems.md)
12 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/06-How to Fix Performance Problems.md:
--------------------------------------------------------------------------------
1 | # How to Fix Performance Problems
2 | [//]: # (Version:1.0.0)
3 | Most software projects can be made with relatively little effort 10 to 100 times faster than they are at the time they are first released. Under time-to-market pressure, it is both wise and effective to choose a solution that gets the job done simply and quickly, but less efficiently than some other solution. However, performance is a part of usability, and often it must eventually be considered more carefully.
4 |
5 | The key to improving the performance of a very complicated system is to analyse it well enough to find the *bottlenecks*, or places where most of the resources are consumed. There is not much sense in optimizing a function that accounts for only 1% of the computation time. As a rule of thumb you should think carefully before doing anything unless you think it is going to make the system or a significant part of it at least twice as fast. There is usually a way to do this. Consider the test and quality assurance effort that your change will require. Each change brings a test burden with it, so it is much better to have a few big changes.
6 |
7 | After you've made a two-fold improvement in something, you need to at least rethink and perhaps reanalyze to discover the next-most-expensive bottleneck in the system, and attack that to get another two-fold improvement.
8 |
9 | Often, the bottlenecks in performance will be an example of counting cows by counting legs and dividing by four, instead of counting heads. For example, I've made errors such as failing to provide a relational database system with a proper index on a column I look up a lot, which probably made it at least 20 times slower. Other examples include doing unnecessary I/O in inner loops, leaving in debugging statements that are no longer needed, unnecessary memory allocation, and, in particular, inexpert use of libraries and other subsystems that are often poorly documented with respect to performance. This kind of improvement is sometimes called *low-hanging fruit*, meaning that it can be easily picked to provide some benefit.
10 |
11 | What do you do when you start to run out of low-hanging fruit? Well, you can reach higher, or chop the tree down. You can continue making small improvements or you can seriously redesign a system or a subsystem. (This is a great opportunity to use your skills as a good programmer, not only in the new design but also in convincing your boss that this is a good idea.) However, before you argue for the redesign of a subsystem, you should ask yourself whether or not your proposal will make it five to ten time better.
12 |
13 | Next [How to Optimize Loops](07-How to Optimize Loops.md)
14 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/07-How to Optimize Loops.md:
--------------------------------------------------------------------------------
1 | # How to Optimize Loops
2 | [//]: # (Version:1.0.0)
3 | Sometimes you'll encounter loops, or recursive functions, that take a long time to execute and are bottlenecks in your product. Before you try to make the loop a little faster, spend a few minutes considering if there is a way to remove it entirely. Would a different algorithm do? Could you compute that while computing something else? If you can't find a way around it, then you can optimize the loop. This is simple; move stuff out. In the end, this will require not only ingenuity but also an understanding of the expense of each kind of statement and expression. Here are some suggestions:
4 |
5 | - Remove floating point operations.
6 | - Don't allocate new memory blocks unnecessarily.
7 | - Fold constants together.
8 | - Move I/O into a buffer.
9 | - Try not to divide.
10 | - Try not to do expensive typecasts.
11 | - Move a pointer rather than recomputing indices.
12 |
13 | The cost of each of these operations depends on your specific system. On some systems compilers and hardware do these things for you. Clear, efficient code is better than code that requires an understanding of a particular platform.
14 |
15 | Next [How to Deal with I/O Expense](08-How to Deal with IO Expense.md)
16 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/08-How to Deal with IO Expense.md:
--------------------------------------------------------------------------------
1 | # How to Deal with I/O Expense
2 | [//]: # (Version:1.0.0)
3 | For a lot of problems, processors are fast compared to the cost of communicating with a hardware device. This cost is usually abbreviated I/O, and can include network cost, disk I/O, database queries, file I/O, and other use of some hardware not very close to the processor. Therefore building a fast system is often more a question of improving I/O than improving the code in some tight loop, or even improving an algorithm.
4 |
5 | There are two very fundamental techniques to improving I/O: caching and representation. Caching is avoiding I/O (generally avoiding the reading of some abstract value) by storing a copy of that value locally so no I/O is performed to get the value. The first key to caching is to make it crystal clear which data is the master and which are copies. There is only one master - period. Caching brings with it the danger that the copy sometimes can't reflect changes to the master instantaneously.
6 |
7 | Representation is the approach of making I/O cheaper by representing data more efficiently. This is often in tension with other demands, like human readability and portability.
8 |
9 | Representations can often be improved by a factor of two or three from their first implementation. Techniques for doing this include using a binary representation instead of one that is human readable, transmitting a dictionary of symbols along with the data so that long symbols don't have to be encoded, and, at the extreme, things like Huffman encoding.
10 |
11 | A third technique that is sometimes possible is to improve the locality of reference by pushing the computation closer to the data. For instance, if you are reading some data from a database and computing something simple from it, such as a summation, try to get the database server to do it for you. This is highly dependent on the kind of system you're working with, but you should explore it.
12 |
13 | Next [How to Manage Memory](09-How to Manage Memory.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/09-How to Manage Memory.md:
--------------------------------------------------------------------------------
1 | # How to Manage Memory
2 | [//]: # (Version:1.0.0)
3 | Memory is a precious resource that you can't afford to run out of. You can ignore it for a while but eventually you will have to decide how to manage memory.
4 |
5 | Space that needs to persist beyond the scope of a single subroutine is often called *heap allocated*. A chunk of memory is useless, hence *garbage*, when nothing refers to it. Depending on the system you use, you may have to explicitly deallocate memory yourself when it is about to become garbage. More often you may be able to use a system that provides a *garbage collector*. A garbage collector notices garbage and frees its space without any action required by the programmer. Garbage collection is wonderful: it lessens errors and increases code brevity and concision cheaply. Use it when you can.
6 |
7 | But even with garbage collection, you can fill up all memory with garbage. A classic mistake is to use a hash table as a cache and forget to remove the references in the hash table. Since the reference remains, the referent is non-collectable but useless. This is called a *memory leak*. You should look for and fix memory leaks early. If you have long running systems memory may never be exhausted in testing but will be exhausted by the user.
8 |
9 | The creation of new objects is moderately expensive on any system. Memory allocated directly in the local variables of a subroutine, however, is usually cheap because the policy for freeing it can be very simple. You should avoid unnecessary object creation.
10 |
11 | An important case occurs when you can define an upper bound on the number of objects you will need at one time. If these objects all take up the same amount of memory, you may be able to allocate a single block of memory, or a buffer, to hold them all. The objects you need can be allocated and released inside this buffer in a set rotation pattern, so it is sometimes called a ring buffer. This is usually faster than heap allocation.
12 |
13 | Sometimes you have to explicitly free allocated space so it can be reallocated rather than rely on garbage collection. Then you must apply careful intelligence to each chunk of allocated memory and design a way for it to be deallocated at the appropriate time. The method may differ for each kind of object you create. You must make sure that every execution of a memory allocating operation is matched by a memory deallocating operation eventually. This is so difficult that programmers often simply implement a rudimentary form of garbage collection, such as reference counting, to do this for them.
14 |
15 | Next [How to Deal with Intermittent Bugs](10-How to Deal with Intermittent Bugs.md)
16 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/10-How to Deal with Intermittent Bugs.md:
--------------------------------------------------------------------------------
1 | # How to Deal with Intermittent Bugs
2 | [//]: # (Version:1.0.0)
3 | The intermittent bug is a cousin of the 50-foot-invisible-scorpion-from-outer-space kind of bug. This nightmare occurs so rarely that it is hard to observe, yet often enough that it can't be ignored. You can't debug because you can't find it.
4 |
5 | Although after 8 hours you will start to doubt it, the intermittent bug has to obey the same laws of logic everything else does. What makes it hard is that it occurs only under unknown conditions. Try to record the circumstances under which the bug does occur, so that you can guess what the variability really is. The condition may be related to data values, such as ‘This only happens when we enter *Wyoming* as a value.’ If that is not the source of variability, the next suspect should be improperly synchronized concurrency.
6 |
7 | Try, try, try to reproduce the bug in a controlled way. If you can't reproduce it, set a trap for it by building a logging system, a special one if you have to, that can log what you guess you need when it really does occur. Resign yourself to that if the bug only occurs in production and not at your whim, this may be a long process. The hints that you get from the log may not provide the solution but may give you enough information to improve the logging. The improved logging system may take a long time to be put into production. Then, you have to wait for the bug to reoccur to get more information. This cycle can go on for some time.
8 |
9 | The stupidest intermittent bug I ever created was in a multi-threaded implementation of a functional programming language for a class project. I had very carefully ensured correct concurrent evaluation of the functional program, good utilization of all the CPUs available (eight, in this case). I simply forgot to synchronize the garbage collector. The system could run a long time, often finishing whatever task I began, before anything noticeable went wrong. I'm ashamed to admit I had begun to question the hardware before my mistake dawned on me.
10 |
11 | At work we recently had an intermittent bug that took us several weeks to find. We have multi-threaded application servers in Java™ behind Apache™ web servers. To maintain fast page turns, we do all I/O in small set of four separate threads that are different than the page-turning threads. Every once in a while these would apparently get ‘stuck’ and cease doing anything useful, so far as our logging allowed us to tell, for hours. Since we had four threads, this was not in itself a giant problem - unless all four got stuck. Then the queues emptied by these threads would quickly fill up all available memory and crash our server. It took us about a week to figure this much out, and we still didn't know what caused it, when it would happen, or even what the threads where doing when they got ‘stuck’.
12 |
13 | This illustrates some risk associated with third-party software. We were using a licensed piece of code that removed HTML tags from text. Although we had the source code (thank goodness!) we had not studied it carefully until by turning up the logging on our servers we finally realized that the email threads were getting stuck in this problematic licensed code.
14 |
15 | The program performed well except on some long and unusual kinds of texts. On these texts, the code was quadratic or worse. This means that the processing time was proportional to the square of the length of the text. Had these texts occurred commonly, we would have found the bug right away. If they had never occurred at all, we would never have had a problem. As it happens, it took us weeks to finally understand and resolve the problem.
16 |
17 | Next [How to Learn Design Skills](11-How to Learn Design Skills.md)
18 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/11-How to Learn Design Skills.md:
--------------------------------------------------------------------------------
1 | # How to Learn Design Skills
2 | [//]: # (Version:1.0.0)
3 | To learn how to design software, study the action of a mentor by being physically present when they are designing. Then study well-written pieces of software. After that, you can read some books on the latest design techniques.
4 |
5 | Then you must do it yourself. Start with a small project. When you are finally done, consider how the design failed or succeeded and how you diverged from your original conception. Then move on to larger projects, hopefully in conjunction with other people. Design is a matter of judgement that takes years to acquire. A smart programmer can learn the basics adequately in two months and can improve from there.
6 |
7 | It is natural and helpful to develop your own style, but remember that design is an art, not a science. People who write books on the subject have a vested interest in making it seem scientific. Don't become dogmatic about particular design styles.
8 |
9 | Next [How to Conduct Experiments](12-How to Conduct Experiments.md)
10 |
--------------------------------------------------------------------------------
/en/1-Beginner/Personal-Skills/12-How to Conduct Experiments.md:
--------------------------------------------------------------------------------
1 | # How to Conduct Experiments
2 | [//]: # (Version:1.0.0)
3 | The late, great Edsger Dijkstra has eloquently explained that Computer Science is not an experimental science[ExpCS] and doesn't depend on electronic computers. As he puts it referring to the 1960s [Knife],
4 |
5 | > ...the harm was done: the topic became known as “computer science” - which, actually, is like referring to surgery as “knife science” - and it was firmly implanted in people's minds that computing science is about machines and their peripheral equipment.
6 |
7 | Programming ought not to be an experimental science, but most working programmers do not have the luxury of engaging in what Dijkstra means by computing science. We must work in the realm of experimentation, just as some, but not all, physicists do. If thirty years from now programming can be performed without experimentation, it will be a great accomplishment of Computer Science.
8 |
9 | The kinds of experiments you will have to perform include:
10 |
11 | - Testing systems with small examples to verify that they conform to the documentation or to understand their response when there is no documentation,
12 | - Testing small code changes to see if they actually fix a bug,
13 | - Measuring the performance of a system under two different conditions due to imperfect knowledge of their performance characteristics,
14 | - Checking the integrity of data, and
15 | - Collecting statistics that may hint at the solution to difficult or hard-to-repeat bugs.
16 |
17 | I don't think in this essay I can explain the design of experiments; you will have to study and practice. However, I can offer two bits of advice.
18 |
19 | First, try to be very clear about your hypothesis, or the assertion that you are trying to test. It also helps to write the hypothesis down, especially if you find yourself confused or are working with others.
20 |
21 | You will often find yourself having to design a series of experiments, each of which is based on the knowledge gained from the last experiment. Therefore, you should design your experiments to provide the most information possible. Unfortunately, this is in tension with keeping each experiment simple - you will have to develop this judgement through experience.
22 |
23 | Next [Team Skills - Why Estimation is Important](../Team-Skills/01-Why Estimation is Important.md)
24 |
--------------------------------------------------------------------------------
/en/1-Beginner/README.md:
--------------------------------------------------------------------------------
1 | # 1. Beginner
2 | [//]: # (Version:1.0.0)
3 | - Personal Skills
4 | - [Learn to Debug](Personal-Skills/01-Learn To Debug.md)
5 | - [How to Debug by Splitting the Problem Space](Personal-Skills/02-How to Debug by Splitting the Problem Space.md)
6 | - [How to Remove an Error](Personal-Skills/03-How to Remove an Error.md)
7 | - [How to Debug Using a Log](Personal-Skills/04-How to Debug Using a Log.md)
8 | - [How to Understand Performance Problems](Personal-Skills/05-How to Understand Performance Problems.md)
9 | - [How to Fix Performance Problems](Personal-Skills/06-How to Fix Performance Problems.md)
10 | - [How to Optimize Loops](Personal-Skills/07-How to Optimize Loops.md)
11 | - [How to Deal with I/O Expense](Personal-Skills/08-How to Deal with IO Expense.md)
12 | - [How to Manage Memory](Personal-Skills/09-How to Manage Memory.md)
13 | - [How to Deal with Intermittent Bugs](Personal-Skills/10-How to Deal with Intermittent Bugs.md)
14 | - [How to Learn Design Skills](Personal-Skills/11-How to Learn Design Skills.md)
15 | - [How to Conduct Experiments](Personal-Skills/12-How to Conduct Experiments.md)
16 | - Team Skills
17 | - [Why Estimation is Important](Team-Skills/01-Why Estimation is Important.md)
18 | - [How to Estimate Programming Time](Team-Skills/02-How to Estimate Programming Time.md)
19 | - [How to Find Out Information](Team-Skills/03-How to Find Out Information.md)
20 | - [How to Utilize People as Information Sources](Team-Skills/04-How to Utilize People as Information Sources.md)
21 | - [How to Document Wisely](Team-Skills/05-How to Document Wisely.md)
22 | - [How to Work with Poor Code](Team-Skills/06-How to Work with Poor Code.md)
23 | - [How to Use Source Code Control](Team-Skills/07-How to Use Source Code Control.md)
24 | - [How to Unit Test](Team-Skills/08-How to Unit Test.md)
25 | - [Take Breaks when Stumped](Team-Skills/09-Take Breaks when Stumped.md)
26 | - [How to Recognize When to Go Home](Team-Skills/10-How to Recognize When to Go Home.md)
27 | - [How to Deal with Difficult People](Team-Skills/11-How to Deal with Difficult People.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/01-Why Estimation is Important.md:
--------------------------------------------------------------------------------
1 | # Why Estimation is Important
2 | [//]: # (Version:1.0.0)
3 | To get a working software system in active use as quickly as possible requires not only planning the development, but also planning the documentation, deployment, and marketing. In a commercial project it also requires sales and finance. Without predictability of the development time, it is impossible to plan these effectively.
4 |
5 | Good estimation provides predictability. Managers love it, as well they should. The fact that it is impossible, both theoretically and practically, to predict accurately how long it will take to develop software is often lost on managers. We are asked to do this impossible thing all the time, and we must face up to it honestly. However, it would be dishonest not to admit the impossibility of this task, and when necessary, explain it. There is a lot of room for miscommunication about estimates, as people have a startling tendency to think wishfully that the sentence:
6 |
7 | > I estimate that, if I really understand the problem, it is about 50% likely that we will be done in five weeks (if no one bothers us during that time).
8 |
9 | really means:
10 |
11 | > I promise to have it all done five weeks from now.
12 |
13 | This common interpretation problem requires that you explicitly discuss what the estimate means with your boss or customer as if they were a simpleton. Restate your assumptions, no matter how obvious they seem to you.
14 |
15 | Next [How to Estimate Programming Time](02-How to Estimate Programming Time.md)
16 |
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/02-How to Estimate Programming Time.md:
--------------------------------------------------------------------------------
1 | # How to Estimate Programming Time
2 | [//]: # (Version:1.0.0)
3 | Estimation takes practice. It also takes labour. It takes so much labour it may be a good idea to estimate the time it will take to make the estimate, especially if you are asked to estimate something big.
4 |
5 | When asked to provide an estimate of something big, the most honest thing to do is to stall. Most engineers are enthusiastic and eager to please, and stalling certainly will displease the stalled. But an on-the-spot estimate probably won't be accurate and honest.
6 |
7 | While stalling, it may be possible to consider doing or prototyping the task. If political pressure permits, this is the most accurate way of producing the estimate, and it makes real progress.
8 |
9 | When not possible to take the time for some investigation, you should first establish the meaning of the estimate very clearly. Restate that meaning as the first and last part of your written estimate. Prepare a written estimate by de-constructing the task into progressively smaller subtasks until each small task is no more than a day; ideally at most in length. The most important thing is not to leave anything out. For instance, documentation, testing, time for planning, time for communicating with other groups, and vacation time are all very important. If you spend part of each day dealing with knuckleheads, put a line item for that in the estimate. This gives your boss visibility into what is using up your time at a minimum, and might get you more time.
10 |
11 | I know good engineers who pad estimates implicitly, but I recommend that you do not. One of the results of padding is trust in you may be depleted. For instance, an engineer might estimate three days for a task that she truly thinks will take one day. The engineer may plan to spend two days documenting it, or two days working on some other useful project. But it will be detectable that the task was done in only one day (if it turns out that way), and the appearance of slacking or overestimating is born. It's far better to give proper visibility into what you are actually doing. If documentation takes twice as long as coding and the estimate says so, tremendous advantage is gained by making this visible to the manager.
12 |
13 | Pad explicitly instead. If a task will probably take one day - but might take ten days if your approach doesn't work - note this somehow in the estimate if you can; if not, at least do an average weighted by your estimates of the probabilities. Any risk factor that you can identify and assign an estimate to, should go into the schedule. One person is unlikely to be sick in any given week. But a large project with many engineers will have some sick time; likewise vacation time. And what is the probability of a mandatory company-wide training seminar? If it can be estimated, stick it in. There are of course, unknown unknowns, or *unk-unks*. Unk-unks by definition cannot be estimated individually. You can try to create a global line item for all unk-unks, or handle them in some other way that you communicate to your boss. You cannot, however, let your boss forget that they exist, and it is devilishly easy for an estimate to become a schedule without the unk-unks considered.
14 |
15 | In a team environment, you should try to have the people who will do the work do the estimate, and you should try to have team-wide consensus on estimates. People vary widely in skill, experience, preparedness, and confidence. Calamity strikes when a strong programmer estimates for herself and then weak programmers are held to this estimate. The act of having the whole team agree on a line-by-line basis to the estimate clarifies the team understanding, as well as allowing the opportunity for tactical reassignment of resources (for instance, shifting burden away from weaker team members to stronger).
16 |
17 | If there are big risks that cannot be evaluated, it is your duty to state so forcefully enough that your manager does not commit to them and then become embarrassed when the risk occurs. Hopefully in such a case whatever is needed will be done to decrease the risk.
18 |
19 | If you can convince your company to use *Extreme Programming*, you will only have to estimate relatively small things, and this is both more fun and more productive.
20 |
21 | Next [How to Find Out Information](03-How to Find Out Information.md)
22 |
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/03-How to Find Out Information.md:
--------------------------------------------------------------------------------
1 | # How to Find Out Information
2 | [//]: # (Version:1.0.0)
3 | The nature of what you need to know determines how you should find it.
4 |
5 | If you need information *about concrete things* that are objective and easy to verify, for example the latest patch level of a software product, ask a large number of people politely by searching the internet for it or by posting on a discussion group. Don't search on the internet for anything that smacks of either opinion or subjective interpretation: the ratio of drivel to truth is too high.
6 |
7 | If you need *general knowledge about something subjective* the history of what people have thought about it, go to the library (the physical building in which books are stored). For example, to learn about math or mushrooms or mysticism, go to the library.
8 |
9 | If you need to know *how to do something that is not trivial* get two or three books on the subject and read them. You might learn how to do something trivial, like install a software package, from the Internet. You can even learn important things, like good programming technique, but you can easily spend more time searching and sorting the results and attempting to divine the authority of the results than it would take to read the pertinent part of a solid book.
10 |
11 | If you need *information that no one else could be expected to know* for example, ‘does this software that is brand new work on gigantic data sets?’, you must still search the internet and the library. After those options are completely exhausted, you may design an experiment to ascertain it.
12 |
13 | If you want an opinion or a value judgement that takes into account some unique circumstance, talk to an expert. For instance, if you want to know whether or not it is a good idea to build a modern database management system in LISP, you should talk to a LISP expert and a database expert.
14 |
15 | If you want to know *how likely it is* that a faster algorithm for a particular application exists that has not yet been published, talk to someone working in that field.
16 |
17 | If you want to make a *personal decision that only you can make* like whether or not you should start a business, try putting into writing a list of arguments for and against the idea. If that fails, consider divination. Suppose you have studied the idea from all angles, have done all your homework, and worked out all the consequences and pros and cons in your mind, and yet still remain indecisive. You now must follow your heart and tell your brain to shut up. The multitude of available divination techniques are very useful for determining your own semi-conscious desires, as they each present a complete ambiguous and random pattern that your own subconscious will assign meaning to.
18 |
19 | Next [How to Utilize People as Information Sources](04-How to Utilize People as Information Sources.md)
20 |
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/04-How to Utilize People as Information Sources.md:
--------------------------------------------------------------------------------
1 | # How to Utilize People as Information Sources
2 | [//]: # (Version:1.0.0)
3 | Respect every person's time and balance it against your own. Asking someone a question accomplishes far more than just receiving the answer. The person learns about you, both by enjoying your presence and hearing the particular question. You learn about the person in the same way, and you may learn the answer you seek. This is usually far more important than your question.
4 |
5 | However, the value of this diminishes the more you do it. You are, after all, using the most precious commodity a person has: their time. The benefits of communication must be weighed against the costs. Furthermore, the particular costs and benefits derived differ from person to person. I strongly believe that an executive of 100 people should spend five minutes a month talking to each person in her organization, which would be about 5% of their time. But ten minutes might be too much, and five minutes is too much if they have one thousand employees. The amount of time you spend talking to each person in your organization depends on their role (more than their position). You should talk to your boss more than your boss's boss, but you should talk to your boss's boss a little. It may be uncomfortable, but I believe you have a duty to talk a little bit to all your superiors, each month, no matter what.
6 |
7 | The basic rule is that everyone benefits from talking to you a little bit, and the more they talk to you, the less benefit they derive. It is your job to provide them this benefit, and to get the benefit of communicating with them, keeping the benefit in balance with the time spent.
8 |
9 | It is important to respect your own time. If talking to someone, even if it will cost them time, will save you a great deal of time, then you should do it unless you think their time is more valuable than yours, to the tribe, by that factor.
10 |
11 | A strange example of this is the summer intern. A summer intern in a highly technical position can't be expected to accomplish too much; they can be expected to pester the hell out of everybody there. So why is this tolerated? Because the pestered are receiving something important from the intern. They get a chance to show-off a little. They get a chance to hear some new ideas, maybe; they get a chance to see things from a different perspective. They may also be trying to recruit the intern, but even if this is not the case there is much to gain.
12 |
13 | You should ask people for a little bit of their wisdom and judgement whenever you honestly believe they have something to say. This flatters them and you will learn something and teach them something. A good programmer does not often need the advice of a Vice President of Sales, but if you ever do, you be sure to ask for it. I once asked to listen in on a few sales calls to better understand the job of our sales staff. This took no more than 30 minutes but I think that small effort made an impression on the sales force.
14 |
15 | Next [How to Document Wisely](05-How to Document Wisely.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/05-How to Document Wisely.md:
--------------------------------------------------------------------------------
1 | # How to Document Wisely
2 | [//]: # (Version:1.0.0)
3 | Life is too short to write crap nobody will read; if you write crap, nobody will read it. Therefore a little good documentation is best. Managers often don't understand this, because even bad documentation gives them a false sense of security that they are not dependent on their programmers. If someone absolutely insists that you write truly useless documentation, say 'yes' and quietly begin looking for a better job.
4 |
5 | There's nothing quite as effective as putting an accurate estimate of the amount of time it will take to produce good documentation into an estimate to slacken the demand for documentation. The truth is cold and hard: documentation, like testing, can take many times longer than developing code.
6 |
7 | Writing good documentation is, first of all, good writing. I suggest you find books on writing, study them, and practice. But even if you are a lousy writer or have poor command of the language in which you must document, the Golden Rule is all you really need: 'Do unto others as you would have them do unto you.' Take time to really think about who will be reading your documentation, what they need to get out of it, and how you can teach that to them. If you do that, you will be an above average documentation writer, and a good programmer.
8 |
9 | When it comes to actually documenting code itself, as opposed to producing documents that can actually be read by non-programmers, the best programmers I've ever known hold a universal sentiment: write self-explanatory code and only document code in the places that you cannot make it clear by writing the code itself. There are two good reasons for this. First, anyone who needs to see code-level documentation will in most cases be able to and prefer to read the code anyway. Admittedly, this seems easier to the experienced programmer than to the beginner. More importantly however, is that the code and the documentation cannot be inconsistent if there is no documentation. The source code can at worst be wrong and confusing. The documentation, if not written perfectly, can lie, and that is a thousand times worse.
10 |
11 | This does not make it easier on the responsible programmer. How does one write self-explanatory code? What does that even mean? It means:
12 |
13 | - Writing code knowing that someone will have to read it;
14 | - Applying the golden rule;
15 | - Choosing a solution that is straightforward, even if you could get by with another solution faster;
16 | - Sacrificing small optimizations that obfuscate the code;
17 | - Thinking about the reader and spending some of your precious time to make it easier on her; and
18 | - Not ever using a function name like `foo`,`bar`, or `doIt`!
19 |
20 | Next [How to Work with Poor Code](06-How to Work with Poor Code.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/06-How to Work with Poor Code.md:
--------------------------------------------------------------------------------
1 | # How to Work with Poor Code
2 | [//]: # (Version:1.0.0)
3 | It is very common to have to work with poor quality code that someone else has written. Don't think too poorly of them, however, until you have walked in their shoes. They may have been asked very consciously to get something done quickly to meet schedule pressure. Regardless, in order to work with unclear code you must understand it. To understand it takes learning time, and that time will have to come out of some schedule, somewhere, and you must insist on it. To understand it, you will have to read the source code. You will probably have to experiment with it.
4 |
5 | This is a good time to document, even if it is only for yourself, because the act of trying to document the code will force you to consider angles you might not have considered, and the resulting document may be useful. While you're doing this, consider what it would take to rewrite some or all of the code. Would it actually save time to rewrite some of it? Could you trust it better if you rewrote it? Be careful of arrogance here. If you rewrite it, it will be easier for you to deal with, but will it really be easier for the next person who has to read it? If you rewrite it, what will the test burden be? Will the need to re-test it outweigh any benefits that might be gained?
6 |
7 | In any estimate that you make for work against code you didn't write, the quality of that code should affect your perception of the risk of problems and unk-unks.
8 |
9 | It is important to remember that abstraction and encapsulation, two of a programmer's best tools, are particularly applicable to lousy code. You may not be able to redesign a large block of code, but if you can add a certain amount of abstraction to it you can obtain some of the benefits of a good design without reworking the whole mess. In particular, you can try to wall off the parts that are particularly bad so that they may be redesigned independently.
10 |
11 | Next [How to Use Source Code Control](07-How to Use Source Code Control.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/07-How to Use Source Code Control.md:
--------------------------------------------------------------------------------
1 | # How to Use Source Code Control
2 | [//]: # (Version:1.0.0)
3 | Source code control systems (also known as Version Control Systems) let you manage projects effectively. They're very useful for one person and essential for a group. They track all changes in different versions so that no code is ever lost and meaning can be assigned to changes. One can create throw-away and debugging code with confidence with a source code control system, since the code you modify is kept carefully separate from committed, official code that will be shared with the team or released.
4 |
5 | I was late to appreciate the benefits of source code control systems but now I wouldn't live without one even on a one-person project. Generally they are necessary when you have team working on the same code base. However, they have another great advantage: they encourage thinking about the code as a growing, organic system. Since each change is marked as a new revision with a new name or number, one begins to think of the software as a visibly progressive series of improvements. I think this is especially useful for beginners.
6 |
7 | A good technique for using a source code control system is to stay within a few days of being up-to-date at all time. Code that can't be finished in a few days is checked in, but in a way that it is inactive and will not be called, and therefore not create any problems for anybody else. Committing a mistake that slows down your team-mates is a serious error; it is often taboo.
8 |
9 | Next [How to Unit Test](08-How to Unit Test.md)
10 |
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/08-How to Unit Test.md:
--------------------------------------------------------------------------------
1 | # How to Unit Test
2 | [//]: # (Version:1.0.0)
3 | Unit testing, the testing of an individual piece of coded functionality by the team that wrote it, is a part of coding, not something different from it. Part of designing the code is designing how it will be tested. You should write down a test plan, even if it is only one sentence. Sometimes the test will be simple: 'Does the button look good?' Sometimes it will be complex: 'Did this matching algorithm return precisely the correct matches?'
4 |
5 | Use assertion checking and test drivers whenever possible. This not only catches bugs early, but is very useful later on and lets you eliminate mysteries that you would otherwise have to worry about.
6 |
7 | The Extreme Programming developers are writing extensively on unit testing effectively; I can do no better than to recommend their writings.
8 |
9 | Next [Take Breaks when Stumped](09-Take Breaks when Stumped.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/09-Take Breaks when Stumped.md:
--------------------------------------------------------------------------------
1 | # Take Breaks when Stumped
2 | [//]: # (Version:1.0.0)
3 | When stumped, take a break. I sometimes meditate for 15 minutes when stumped and the problem magically unravels when I come back to it. A night's sleep sometimes does the same thing on a larger scale. It's possible that temporarily switching to any other activity may work.
4 |
5 | Next [How to Recognize When to Go Home](10-How to Recognize When to Go Home.md)
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/10-How to Recognize When to Go Home.md:
--------------------------------------------------------------------------------
1 | # How to Recognize When to Go Home
2 | [//]: # (Version:1.0.0)
3 | Computer programming is an activity that is also a culture. The unfortunate fact is that it is not a culture that values mental or physical health very much. For both cultural/historical reasons (the need to work at night on unloaded computers, for example) and because of overwhelming time-to-market pressure and the scarcity of programmers, computer programmers are traditionally overworked. I don't think you can trust all the stories you hear, but I think 60 hours a week is common, and 50 is pretty much a minimum. This means that often much more than that is required. This is a serious problem for a good programmer, who is responsible not only for themselves but their team-mates as well. You have to recognize when to go home, and sometimes when to suggest that other people go home. There can't be any fixed rules for solving this problem, anymore than there can be fixed rules for raising a child, for the same reason---every human being is different.
4 |
5 | Beyond 60 hours a week is an extraordinary effort for me, which I can apply for short periods of time (about one week), and that is sometimes expected of me. I don't know if it is fair to expect 60 hours of work from a person; I don't even know if 40 is fair. I am sure, however, that it is stupid to work so much that you are getting little out of that extra hour you work. For me personally, that's any more than 60 hours a week. I personally think a programmer should exercise noblesse oblige and shoulder a heavy burden. However, it is not a programmer's duty to be a patsy. The sad fact is programmers *are* often asked to be patsies in order to put on a show for somebody, for example a manager trying to impress an executive. Programmers often succumb to this because they are eager to please and not very good at saying no. There are four defences against this:
6 |
7 | - Communicate as much as possible with everyone in the company so that no one can mislead the executives about what is going on,
8 | - Learn to estimate and schedule defensively and explicitly and give everyone visibility into what the schedule is and where it stands,
9 | - Learn to say no, and say no as a team when necessary, and
10 | - Quit if you have to.
11 |
12 | Most programmers are good programmers, and good programmers want to get a lot done. To do that, they have to manage their time effectively. There is a certain amount of mental inertia associated with getting warmed-up to a problem and deeply involved in it. Many programmers find they work best when they have long, uninterrupted blocks of time in which to get warmed-up and concentrate. However, people must sleep and perform other duties. Each person needs to find a way to satisfy both their human rhythm and their work rhythm. Each programmer needs to do whatever it takes to procure efficient work periods, such as reserving certain days in which you will attend only the most critical meetings.
13 |
14 | Since I have children, I try to spend evenings with them sometimes. The rhythm that works best for me is to work a very long day, sleep in the office or near the office (I have a long commute from home to work) then go home early enough the next day to spend time with my children before they go to bed. I am not comfortable with this, but it is the best compromise I have been able to work out. Go home if you have a contagious disease. You should go home if you are thinking suicidal thoughts. You should take a break or go home if you think homicidal thoughts for more than a few seconds. You should send someone home if they show serious mental malfunctioning or signs of mental illness beyond mild depression. If you are tempted to be dishonest or deceptive in a way that you normally are not due to fatigue, you should take a break. Don't use cocaine or amphetamines to combat fatigue. Don't abuse caffeine.
15 |
16 | Next [How to Deal with Difficult People](11-How to Deal with Difficult People.md)
17 |
--------------------------------------------------------------------------------
/en/1-Beginner/Team-Skills/11-How to Deal with Difficult People.md:
--------------------------------------------------------------------------------
1 | # How to Deal with Difficult People
2 | [//]: # (Version:1.0.0)
3 | You will probably have to deal with difficult people. You may even be a difficult person yourself. If you are the kind of person who has a lot of conflicts with co-workers and authority figures, you should cherish the independence this implies, but work on your interpersonal skills without sacrificing your intelligence or principles.
4 |
5 | This can be very disturbing to some programmers who have no experience in this sort of thing and whose previous life experience has taught them patterns of behaviour that are not useful in the workplace. Difficult people are often accustomed to disagreement and they are less affected by social pressure to compromise than others. The key is to respect them appropriately, which is more than you will want to but not as much as they might want.
6 |
7 | Programmers have to work together as a team. When disagreement arises, it must be resolved somehow, it cannot be ducked for long. Difficult people are often extremely intelligent and have something very useful to say. It is critical that you listen to and understand the difficult person without prejudice caused by the person. A failure to communicate is often the basis of disagreement but it can sometimes be removed with great patience. Try to keep this communication cool and cordial, and don't accept any baits for greater conflict that may be offered. After a reasonable period of trying to understand, make a decision.
8 |
9 | Don't let a bully force you to do something you don't agree with. If you are the leader, do what you think is best. Don't make a decision for any personal reasons, and be prepared to explain the reasons for your decision. If you are a team-mate with a difficult person, don't let the leader's decision have any personal impact. If it doesn't go your way, do it the other way whole-heartedly.
10 |
11 | Difficult people do change and improve. I've seen it with my own eyes, but it is very rare. However, everyone has transitory ups and downs.
12 |
13 | One of the challenges that every programmer but especially leaders face is keeping the difficult person fully engaged. They are more prone to duck work and resist passively than others.
14 |
15 | Next [Intermediate skills](../../2-Intermediate)
16 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/01-How to Tradeoff Quality Against Development Time.md:
--------------------------------------------------------------------------------
1 | # How to Tradeoff Quality Against Development Time
2 | [//]: # (Version:1.0.0)
3 | Software development is always a compromise between what the project does and getting the project done. But you may be asked to tradeoff quality to speed the deployment of a project in a way that offends your engineering or business sensibilities. For example, you may be asked to do something that is a poor software engineering practice and that will lead to a lot of maintenance problems.
4 |
5 | If this happens your first responsibility is to inform your team and to clearly explain the cost of the decrease in quality. After all, your understanding of it should be much better than your boss's understanding. Make it clear what is being lost and what is being gained, and at what cost the lost ground will be regained in the next cycle. In this, the visibility provided by a good project plan should be helpful. If the quality tradeoff affects the quality assurance effort, point that out (both to your boss and quality assurance people). If the quality tradeoff will lead to more bugs being reported after the quality assurance period, point that out.
6 |
7 | If she still insists, you should try to isolate the shoddiness into particular components that you can plan to rewrite or improve in the next cycle. Explain this to your team so that they can plan for it.
8 |
9 | NinjaProgrammer at Slashdot sent in this gem:
10 |
11 | > Remember that a good design will be resilient against poor code implementations. If good interfaces and abstractions exist throughout the code, then the eventual rewrites will be far more painless. If it is hard to write clear code that is hard to fix, consider what is wrong with the core design that is causing this.
12 |
13 | Next [How to Manage Software Dependence](02-How to Manage Software System Dependence.md)
14 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/02-How to Manage Software System Dependence.md:
--------------------------------------------------------------------------------
1 | # How to Manage Software System Dependence
2 | [//]: # (Version:1.0.0)
3 | Modern software systems tend to depend on a large number of components that may not be directly under your control. This increases productivity through synergy and reuse. However, each component brings with it some problems:
4 |
5 | - How will you fix bugs in the component?
6 | - Does the component restrict you to particular hardware or software systems?
7 | - What will you do if the component fails completely?
8 |
9 | It is always best to encapsulate the component in some way so that it is isolated and so that it can be swapped out. If the component proves to be completely unworkable, you may be able to get a different one, but you may have to write your own. Encapsulation is not portability, but it makes porting easier, which is almost as good.
10 |
11 | Having the source code for a component decreases the risk by a factor of four. With source code, you can evaluate it easier, debug it easier, find workarounds easier, and make fixes easier. If you make fixes, you should give them to the owner of the component and get the fixes incorporated into an official release; otherwise you will uncomfortably have to maintain an unofficial version.
12 |
13 | Next [How to Decide if Software is Too Immature](03-How to Decide if Software is Too Immature.md)
14 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/03-How to Decide if Software is Too Immature.md:
--------------------------------------------------------------------------------
1 | # How to Decide if Software is Too Immature
2 | [//]: # (Version:1.0.0)
3 | Using software other people wrote is one of the most effective ways to quickly build a solid system. It should not be discouraged, but the risks associated with it must be examined. One of the biggest risks is the period of bugginess and near inoperability that is often associated with software before it matures, through usage, into a usable product. Before you consider integrating with a software system, whether created in house or by a third party, it is very important to consider if it is really mature enough to be used. Here are ten questions you should ask yourself about it:
4 |
5 | 1. Is it vapour? (Promises are very immature).
6 | 2. Is there an accessible body of lore about the software?
7 | 3. Are you the first user?
8 | 4. Is there a strong incentive for continuation?
9 | 5. Has it had a maintenance effort?
10 | 6. Will it survive defection of the current maintainers?
11 | 7. Is there a seasoned alternative at least half as good?
12 | 8. Is it known to your tribe or company?
13 | 9. Is it desirable to your tribe or company?
14 | 10. Can you hire people to work on it even if it is bad?
15 |
16 | A little consideration of these criteria demonstrates the great value of well-established free software and open-source software in reducing risk to the entrepreneur.
17 |
18 | Next [How to Make a Buy vs. Build Decision](04-How to Make a Buy vs Build Decision.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/04-How to Make a Buy vs Build Decision.md:
--------------------------------------------------------------------------------
1 | # How to Make a Buy vs. Build Decision
2 | [//]: # (Version:1.0.0)
3 | An entrepreneurial company or project that is trying to accomplish something with software has to constantly make so-called *buy vs. build* decisions. This turn of phrase is unfortunate in two ways: it seems to ignore open-source and free software which is not necessarily *bought*. Even more importantly, it should perhaps be called an *obtain and integrate vs. build here and integrate* decision because the cost of integration must be considered. This requires a great combination of business, management, and engineering savvy.
4 |
5 | - How well do your needs match those for which it was designed?
6 | - What portion of what you buy will you need?
7 | - What is the cost of evaluating the integration?
8 | - What is the cost of integration?
9 | - Will buying increase or decrease long term maintenance costs?
10 | - Will building it put you in a business position you don't want to be in?
11 |
12 | You should think twice before building something that is big enough to serve as the basis for an entire other business. Such ideas are often proposed by bright and optimistic people that will have a lot to contribute to your team. If their idea is compelling, you may wish to change your business plan; but do not invest in a solution bigger than your own business without conscious thought.
13 |
14 | After considering these questions, you should perhaps prepare two draft project plans, one for building and one for buying. This will force you to consider the integration costs. You should also consider the long term maintenance costs of both solutions. To estimate the integration costs, you will have to do a thorough evaluation of the software before you buy it. If you can't evaluate it, you will assume an unreasonable risk in buying it and you should decide against buying that particular product. If there are several buy decisions under consideration, some energy will have to be spent evaluating each.
15 |
16 | Next [How to Grow Professionally](05-How to Grow Professionally.md)
17 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/05-How to Grow Professionally.md:
--------------------------------------------------------------------------------
1 | # How to Grow Professionally
2 | [//]: # (Version:1.0.0)
3 | Assume responsibility in excess of your authority. Play the role that you desire. Express appreciation for people's contribution to the success of the larger organization, as well as things as that help you personally.
4 |
5 | If you want to become a team leader, instigate the formation of consensus. If you want to become a manager, take responsibility for the schedule. You can usually do this comfortably while working with a leader or a manager, since this frees them up to take greater responsibility. If that is too much to try, do it a little at a time.
6 |
7 | Evaluate yourself. If you want to become a better programmer, ask someone you admire how you can become like them. You can also ask your boss, who will know less but have a greater impact on your career.
8 |
9 | Plan ways to learn new skills, both the trivial technical kind, like learning a new software system, and the hard social kind, like writing well, by integrating them into your work.
10 |
11 | Next [How to Evaluate Interviewees](06-How to Evaluate Interviewees.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/06-How to Evaluate Interviewees.md:
--------------------------------------------------------------------------------
1 | # How to Evaluate Interviewees
2 | [//]: # (Version:1.0.0)
3 | Evaluating potential employees is not given the energy it deserves. A bad hire, like a bad marriage, is terrible. A significant portion of everyone's energy should be devoted to recruitment, though this is rarely done.
4 |
5 | There are different interviewing styles. Some are torturous, designed to put the candidate under a great deal of stress. This serves a very valuable purpose of possibly revealing character flaws and weaknesses under stress. Candidates are no more honest with interviewers than they are with themselves, and the human capacity for self-deception is astonishing.
6 |
7 | You should, at a minimum, give the candidate the equivalent of an oral examination on the technical skills for two hours. With practice, you will be able to quickly cover what they know and quickly retract from what they don't know to mark out the boundary. Interviewees will respect this. I have several times heard interviewees say that the quality of the examination was one of their motivations for choosing a company. Good people want to be hired for their skills, not where they worked last or what school they went to or some other inessential characteristic.
8 |
9 | In doing this, you should also evaluate their ability to learn, which is far more important than what they know. You should also watch for the whiff of brimstone that is given off by difficult people. You may be able to recognize it by comparing notes after the interview, but in the heat of the interview it is hard to recognize. How well people communicate and work with people is more important than being up on the latest programming language.
10 |
11 | A reader has had good luck using a ‘take-home’ test for interviewees. This has the advantage that it can uncover the interviewee that can present themselves well but can't really code - and there are many such people. I personally have not tried this technique, but it sounds sensible.
12 |
13 | Finally, interviewing is also a process of selling. You should be selling your company or project to the candidate. However, you are talking to a programmer, so don't try to colour the truth. Start off with the bad stuff, then finish strong with the good stuff.
14 |
15 | Next [How to Know When to Apply Fancy Computer Science](07-How to Know When to Apply Fancy Computer Science.md)
16 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/07-How to Know When to Apply Fancy Computer Science.md:
--------------------------------------------------------------------------------
1 | # How to Know When to Apply Fancy Computer Science
2 | [//]: # (Version:1.0.0)
3 | There is a body of knowledge about algorithms, data structures, mathematics, and other gee-whiz stuff that most programmers know about but rarely use. In practice, this wonderful stuff is too complicated and generally unnecessary. There is no point in improving an algorithm when most of your time is spent making inefficient database calls, for instance. An unfortunate amount of programming consists of getting systems to talk to each other and using very simple data structures to build a nice user interface.
4 |
5 | When is high technology the appropriate technology? When should you crack a book to get something other than a run-of-the-mill algorithm? It is sometimes useful to do this but it should be evaluated carefully.
6 |
7 | The three most important considerations for the potential computer science technique are:
8 |
9 | - Is it well encapsulated so that the risk to other systems is low and the overall increase in complexity and maintenance cost is low?
10 | - Is the benefit startling (for example, a factor of two in a mature system or a factor of ten in a new system)?
11 | - Will you be able to test and evaluate it effectively?
12 |
13 | If a well-isolated algorithm that uses a slightly fancy algorithm can decrease hardware cost or increase performance by a factor of two across an entire system, then it would be criminal not to consider it. One of the keys to arguing for such an approach is to show that the risk is really quite low, since the proposed technology has probably been well studied, the only issue is the risk of integration. Here a programmer's experience and judgement can truly synergize with the fancy technology to make integration easy.
14 |
15 | Next [How to Talk to Non-Engineers](08-How to Talk to Non-Engineers.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Judgment/08-How to Talk to Non-Engineers.md:
--------------------------------------------------------------------------------
1 | # How to Talk to Non-Engineers
2 | [//]: # (Version:1.0.0)
3 | Engineers and programmers in particular are generally recognized by popular culture as being different from other people. This implies that other people are different from us. This is worth bearing in mind when communicating with non-engineers; you should always understand the audience.
4 |
5 | Non-engineers are smart, but not as grounded in creating technical things as we are. We make things. They sell things and handle things and count things and manage things, but they are not experts on making things. They are not as good at working together on teams as engineers are (there are no doubt exceptions.) Their social skills are generally as good as or better than engineers in non-team environments, but their work does not always demand that they practice the kind of intimate, precise communication and careful subdivisions of tasks that we do.
6 |
7 | Non-engineers may be too eager to please and they may be intimidated by you. Just like us, they may say ‘yes’ without really meaning it to please you or because they are a little scared of you, and then not stand behind their words.
8 |
9 | Non-programmers can understand technical things but they do not have the thing that is so hard even for us - technical judgement. They do understand how technology works, but they cannot understand why a certain approach would take three months and another one three days. (After all, programmers are anecdotally horrible at this kind of estimation as well.) This represents a great opportunity to synergize with them.
10 |
11 | When talking to your team you will, without thinking, use a sort of shorthand, an abbreviated language that is effective because you will have much shared experience about technology in general and your product in particular. It takes some effort not to use this shorthand with those that don't have that shared experience, especially when members of your own team are present. This vocabulary creates a wall between you and those that do not share it, and, even worse, wastes their time.
12 |
13 | With your team, the basic assumptions and goals do not need to be restated often, and most conversation focuses on the details. With outsiders, it must be the other way around. They may not understand things you take for granted. Since you take them for granted and don't repeat them, you can leave a conversation with an outsider thinking that you understand each other when really there is a large misunderstanding. You should assume that you will miscommunicate and watch carefully to find this miscommunication. Try to get them to summarize or paraphrase what you are saying to make sure they understand. If you have the opportunity to meet with them often, spend a little bit of time asking if you are communicating effectively, and how you can do it better. If there is a problem in communication, seek to alter your own practices before becoming frustrated with theirs.
14 |
15 | I love working with non-engineers. It provides great opportunities to learn and to teach. You can often lead by example, in terms of the clarity of your communication. Engineers are trained to bring order out of chaos, to bring clarity out of confusion, and non-engineers like this about us. Because we have technical judgement and can usually understand business issues, we can often find a simple solution to a problem.
16 |
17 | Often non-engineers propose solutions that they think will make it easier on us out of kindness and a desire to do the right thing, when in fact a much better overall solution exists which can only be seen by synergizing the outsider's view with your technical judgement. I personally like Extreme Programming because it addresses this inefficiency; by marrying the estimation quickly to the idea, it makes it easier to find the idea that is the best combination of cost and benefit.
18 |
19 | Next [Advanced skills](../../3-Advanced)
20 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/01-How to Stay Motivated.md:
--------------------------------------------------------------------------------
1 | # How to Stay Motivated
2 | [//]: # (Version:1.0.0)
3 | It is a wonderful and surprising fact that programmers are highly motivated by the desire to create artifacts that are beautiful, useful, or nifty. This desire is not unique to programmers nor universal but it is so strong and common among programmers that it separates them from others in other roles.
4 |
5 | This has practical and important consequences. If programmers are asked to do something that is not beautiful, useful, or nifty, they will have low morale. There's a lot of money to be made doing ugly, stupid, and boring stuff; but in the end, fun will make the most money for the company.
6 |
7 | Obviously, there are entire industries organized around motivational techniques some of which apply here. The things that are specific to programming that I can identify are:
8 |
9 | - Use the best language for the job.
10 | - Look for opportunities to apply new techniques, languages, and technologies.
11 | - Try to either learn or teach something, however small, in each project.
12 |
13 | Finally, if possible, measure the impact of your work in terms of something that will be personally motivating. For example, when fixing bugs, counting the number of bugs that I have fixed is not at all motivational to me, because it is independent of the number that may still exist, and it also affects the total value I'm adding to my company's customers in only the smallest possible way. Relating each bug to a happy customer, however, *is* personally motivating to me.
14 |
15 | Next [How to be Widely Trusted](02-How to be Widely Trusted.md)
16 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/02-How to be Widely Trusted.md:
--------------------------------------------------------------------------------
1 | # How to be Widely Trusted
2 | [//]: # (Version:1.0.0)
3 | To be trusted you must be trustworthy. You must also be visible. If no one knows about you, no trust will be invested in you. With those close to you, such as your teammates, this should not be an issue. You establish trust by being responsive and informative to those outside your department or team. Occasionally someone will abuse this trust, and ask for unreasonable favours. Don't be afraid of this, just explain what you would have to give up doing to perform the favour.
4 |
5 | Don't pretend to know something that you don't. With people that are not teammates, you may have to make a clear distinction between 'not knowing right off the top of my head' and 'not being able to figure it out, ever.'
6 |
7 | Next [How to Tradeoff Time vs. Space](03-How to Tradeoff Time vs Space.md)
8 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/03-How to Tradeoff Time vs Space.md:
--------------------------------------------------------------------------------
1 | # How to Tradeoff Time vs. Space
2 | [//]: # (Version:1.0.0)
3 | You can be a good programmer without going to college, but you can't be a good intermediate programmer without knowing basic computational complexity theory. You don't need to know 'big O' notation, but I personally think you should be able to understand the difference between 'constant-time','n log n' and 'n squared'. You might be able to intuit how to trade-off time against space without this knowledge, but in its absence you will not have a firm basis for communicating with your colleagues.
4 |
5 | In designing or understanding an algorithm, the amount of time it takes to run is sometimes a function of the size of the input. When that is true, we can say an algorithm's worst/expected/best-case running time is 'n log n' if it is proportional to the size ($n$) times the logarithm of the size. The notation and way of speaking can be also be applied to the space taken up by a data structure.
6 |
7 | To me, computational complexity theory is beautiful and as profound as physics - and a little bit goes a long way!
8 |
9 | Time (processor cycles) and space (memory) can be traded off against each other. Engineering is about compromise, and this is a fine example. It is not always systematic. In general, however, one can save space by encoding things more tightly, at the expense of more computation time when you have to decode them. You can save time by caching, that is, spending space to store a local copy of something, at the expense of having to maintain the consistency of the cache. You can sometimes save time by maintaining more information in a data structure. This usually costs a small amount of space, but may complicate the algorithm.
10 |
11 | Improving the space/time trade-off can often change one or the other dramatically. However, before you work on this you should ask yourself if what you are improving is really the thing that needs the most improvement. It's fun to work on an algorithm, but you can't let that blind you to the cold hard fact that improving something that is not a problem will not make any noticeable difference and will create a test burden.
12 |
13 | Memory on modern computers appears cheap, because unlike processor time, you can't see it being used until you hit the wall; but then failure is catastrophic. There are also other hidden costs to using memory, such as your effect on other programs that must be resident, and the time to allocate and deallocate it. Consider this carefully before you trade away space to gain speed.
14 |
15 | Next [How to Stress Test](04-How to Stress Test.md)
16 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/04-How to Stress Test.md:
--------------------------------------------------------------------------------
1 | # How to Stress Test
2 | [//]: # (Version:1.0.0)
3 | Stress testing is fun. At first it appears that the purpose of stress testing is to find out if the system works under a load. In reality, it is common that the system does work under a load but fails to work in some way when the load is heavy enough. I call this *hitting the wall* or *bonking*[1]. There may be some exceptions, but there is almost always a ‘wall’. The purpose of stress testing is to figure out where the wall is, and then figure out how to move the wall further out.
4 |
5 | A plan for stress testing should be developed early in the project, because it often helps to clarify exactly what is expected. Is two seconds for a web page request a miserable failure or a smashing success? Is 500 concurrent users enough? That, of course, depends, but one must know the answer when designing the system that answers the request. The stress test needs to model reality well enough to be useful. It isn't really possible to simulate 500 erratic and unpredictable humans using a system concurrently very easily, but one can at least create 500 simulations and try to model some part of what they might do.
6 |
7 | In stress testing, start out with a light load and load the system along some dimension - such as input rate or input size - until you hit the wall. If the wall is too close to satisfy your needs, figure out which resource is the bottleneck (there is usually a dominant one.) Is it memory, processor, I/O, network bandwidth, or data contention? Then figure out how you can move the wall. Note that moving the wall, that is, increasing the maximum load the system can handle, might not help or might actually hurt the performance of a lightly loaded system. Usually performance under heavy load is more important than performance under a light load.
8 |
9 | You may have to get visibility into several different dimensions to build up a mental model of it; no single technique is sufficient. For instance, logging often gives a good idea of the wall-clock time between two events in the system, but unless carefully constructed, doesn't give visibility into memory utilization or even data structure size. Similarly, in a modern system, a number of computers and many software systems may be cooperating. Particularly when you are hitting the wall (that is, the performance is non-linear in the size of the input) these other software systems may be a bottleneck. Visibility into these systems, even if only measuring the processor load on all participating machines, can be very helpful.
10 |
11 | Knowing where the wall is is essential not only to moving the wall, but also to providing predictability so that the business can be managed effectively.
12 |
13 | ---
14 |
15 | [1] "to hit"
16 |
17 | Next [How to Balance Brevity and Abstraction](05-How to Balance Brevity and Abstraction.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/05-How to Balance Brevity and Abstraction.md:
--------------------------------------------------------------------------------
1 | # How to Balance Brevity and Abstraction
2 | [//]: # (Version:1.0.0)
3 | Abstraction is key to programming. You should carefully choose how abstract you need to be. Beginning programmers in their enthusiasm often create more abstraction than is really useful. One sign of this is if you create classes that don't really contain any code and don't really do anything except serve to abstract something. The attraction of this is understandable but the value of code brevity must be measured against the value of abstraction. Occasionally, one sees a mistake made by enthusiastic idealists: at the start of the project a lot of classes are defined that seem wonderfully abstract and one may speculate that they will handle every eventuality that may arise. As the project progresses and fatigue sets in, the code itself becomes messy. Function bodies become longer than they should be. The empty classes are a burden to document that is ignored when under pressure. The final result would have been better if the energy spent on abstraction had been spent on keeping things short and simple. This is a form of *speculative programming*. I strongly recommend the article ['Succinctness is Power' by Paul Graham](http://www.paulgraham.com/power.html).
4 |
5 | There is a certain dogma associated with useful techniques such as *information hiding* and *object oriented programming* that are sometimes taken too far. These techniques let one code abstractly and anticipate change. I personally think, however, that you should not produce much speculative code. For example, it is an accepted style to hide an integer variable on an object behind mutators and accessors, so that the variable itself is not exposed, only the little interface to it. This does allow the implementation of that variable to be changed without affecting the calling code, and is perhaps appropriate to a library writer who must publish a very stable API. But I don't think the benefit of this outweighs the cost of the wordiness of it when my team owns the calling code and hence can recode the caller as easily as the called. Four or five extra lines of code is a heavy price to pay for this speculative benefit.
6 |
7 | Portability poses a similar problem. Should code be portable to a different computer, compiler, software system or platform, or simply easily ported? I think a non-portable, short-and-easily-ported piece of code is better than a long portable one. It is relatively easy and certainly a good idea to confine non-portable code to designated areas, such as a class that makes database queries that are specific to a given DBMS.
8 |
9 | Next [How to Learn New Skills](06-How to Learn New Skills.md)
10 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/06-How to Learn New Skills.md:
--------------------------------------------------------------------------------
1 | # How to Learn New Skills
2 | [//]: # (Version:1.0.0)
3 | Learning new skills, especially non-technical ones, is the greatest fun of all. Most companies would have better morale if they understood how much this motivates programmers.
4 |
5 | Humans learn by doing. Book-reading and class-taking are useful. But could you have any respect for a programmer who had never written a program? To learn any skill, you have to put yourself in a forgiving position where you can exercise that skill. When learning a new programming language, try to do a small project in it before you have to do a large project. When learning to manage a software project, try to manage a small one first.
6 |
7 | A good mentor is no replacement for doing things yourself, but is a lot better than a book. What can you offer a potential mentor in exchange for their knowledge? At a minimum, you should offer to study hard so their time won't be wasted.
8 |
9 | Try to get your boss to let you have formal training, but understand that it is often not much better than the same amount of time spent simply playing with the new skill you want to learn. It is, however, easier to ask for training than playtime in our imperfect world, even though a lot of formal training is just sleeping through lectures waiting for the dinner party.
10 |
11 | If you lead people, understand how they learn and assist them by assigning them projects that are the right size and that exercise skills they are interested in. Don't forget that the most important skills for a programmer are not the technical ones. Give your people a chance to play and practice courage, honesty, and communication.
12 |
13 | Next [Learn to Type](07-Learn to Type.md)
14 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/07-Learn to Type.md:
--------------------------------------------------------------------------------
1 | # Learn to Type
2 | [//]: # (Version:1.0.0)
3 | Learn to touch-type. This is an intermediate skill because writing code is so hard that the speed at which you can type is irrelevant and can't put much of a dent in the time it takes to write code, no matter how good you are. However, by the time you are an intermediate programmer you will probably spend a lot of time writing natural language to your colleagues and others. This is a fun test of your commitment; it takes dedicated time that is not much fun to learn something like that. Legend has it that when Michael Tiemann was at MCC people would stand outside his door to listen to the hum generated by his keystrokes which were so rapid as to be indistinguishable.
4 |
5 | Next [How to Do Integration Testing](08-How to Do Integration Testing.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/08-How to Do Integration Testing.md:
--------------------------------------------------------------------------------
1 | # How to Do Integration Testing
2 | [//]: # (Version:1.0.0)
3 | Integration testing is the testing of the integration of various components that have been unit tested. Integration is expensive and it comes out in the testing. You must include time for this in your estimates and your schedule.
4 |
5 | Ideally you should organize a project so that there is not a phase at the end where integration must explicitly take place. It is far better to gradually integrate things as they are completed over the course of the project. If it is unavoidable estimate it carefully.
6 |
7 | Next [Communication Languages](09-Communication Languages.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/09-Communication Languages.md:
--------------------------------------------------------------------------------
1 | # Communication Languages
2 | [//]: # (Version:1.0.0)
3 | There are some languages, that is, formally defined syntactic systems, that are not programming languages but *communication languages* - they are designed specifically to facilitate communication through standardization. In 2003 the most important of these are UML, XML, and SQL. You should have some familiarity with all of these so that you can communicate well and decide when to use them.
4 |
5 | UML is a rich formal system for making drawings that describe designs. Its beauty lies in that it is both visual and formal, capable of conveying a great deal of information if both the author and the audience know UML. You need to know about it because designs are sometimes communicated in it. There are very helpful tools for making UML drawings that look very professional. In a lot of cases UML is too formal, and I find myself using a simpler *boxes and arrows* style for design drawings. But I'm fairly sure UML is at least as good for you as studying Latin.
6 |
7 | XML is a standard for defining new standards. It is not a solution to data interchange problems, though you sometimes see it presented as if it was. Rather, it is a welcome automation of the most boring part of data interchange, namely, structuring the representation into a linear sequence and parsing back into a structure. It provides some nice type- and correctness-checking, though again only a fraction of what you are likely to need in practice.
8 |
9 | SQL is a very powerful and rich data query and manipulation language that is not quite a programming language. It has many variations, typically quite product-dependent, which are less important than the standardized core. SQL is the *lingua franca* of relational databases. You may or may not work in any field that can benefit from an understanding of relational databases, but you should have a basic understanding of them and the syntax and meaning of SQL.
10 |
11 | Next [Heavy Tools](10-Heavy Tools.md)
12 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/10-Heavy Tools.md:
--------------------------------------------------------------------------------
1 | # Heavy Tools
2 | [//]: # (Version:1.0.0)
3 | As our technological culture progresses, software technology moves from inconceivable, to research, to new products, to standardized products, to widely available and inexpensive products. These heavy tools can pull great loads, but can be intimidating and require a large investment in understanding. The intermediate programmer has to know how to manage them and when they should be used or considered.
4 |
5 | To my mind right now some of the best heavy tools are:
6 |
7 | - Relational Databases,
8 | - Full-text Search Engines,
9 | - Math libraries,
10 | - OpenGL,
11 | - XML parsers, and
12 | - Spreadsheets.
13 |
14 | Next [How to analyze data](11-How to analyze data.md)
15 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Personal-Skills/11-How to analyze data.md:
--------------------------------------------------------------------------------
1 | # How to analyze data
2 | [//]: # (Version:1.0.0)
3 | Data analysis is a process in the early stages of software development, when you examine a business activity and find the requirements to convert it into a software application. This is a formal definition, which may lead you to believe that data analysis is an action that you should better leave to the systems analysts, while you, the programmer, should focus on coding what somebody else has designed. If we follow strictly the software engineering paradigm, it may be correct. Experienced programmers become designers and the sharpest designers become business analysts, thus being entitled to think about all the data requirements and give you a well defined task to carry out. This is not entirely accurate, because data is the core value of every programming activity. Whatever you do in your programs, you are either moving around or modifying data. The business analyst is analysing the needs in a larger scale, and the software designer is further squeezing such scale so that, when the problem lands on your desk, it seems that all you need to do is to apply clever algorithms and start moving existing data.
4 |
5 | Not so.
6 |
7 | No matter at which stage you start looking at it, data is the main concern of a well designed application. If you look closely at how a business analyst gets the requirements out of the customer's requests, you'll realize that data plays a fundamental role. The analyst creates so called Data Flow Diagrams, where all data sources are identified and the flow of information is shaped. Having clearly defined which data should be part of the system, the designer will shape up the data sources, in terms of database relations, data exchange protocols, and file formats, so that the task is ready to be passed down to the programmer. However, the process is not over yet, because you (the programmer) even after this thorough process of data refinement, are required to analyze data to perform the task in the best possible way. The bottom line of your task is the core message of Niklaus Wirth, the father of several languages. "Algorithms + Data Structures = Programs." There is never an algorithm standing alone, doing something to itself. Every algorithm is supposed to do something to at least one piece of data.
8 |
9 | Therefore, since algorithms don't spin their wheels in a vacuum, you need to analyze both the data that somebody else has identified for you and the data that is necessary to write down your code. A trivial example will make the matter clearer. You are implementing a search routine for a library. According to your specifications, the user can select books by a combination of genre, author, title, publisher, printing year, and number of pages. The ultimate goal of your routine is to produce a legal SQL statement to search the back-end database. Based on these requirements, you have several choices: check each control in turn, using a "switch" statement, or several "if" ones; make an array of data controls, checking each element to see if it is set; create (or use) an abstract control object from which to inherit all your specific controls, and connect them to an event-driven engine. If your requirements include also tuning up the query performance, by making sure that the items are checked in a specific order, you may consider using a tree of components to build your SQL statement. As you can see, the choice of the algorithm depends on the data you decide to use, or to create. Such decisions can make all the difference between an efficient algorithm and a disastrous one. However, efficiency is not the only concern. You may use a dozen named variables in your code and make it as efficient as it can ever be. But such a piece of code might not be easily maintainable. Perhaps choosing an appropriate container for your variables could keep the same speed and in addition allow your colleagues to understand the code better when they look at it next year. Furthermore, choosing a well defined data structure may allow them to extend the functionality of your code without rewriting it. In the long run, your choices of data determines how long your code will survive after you are finished with it. Let me give you another example, just some more food for thought. Let's suppose that your task is to find all the words in a dictionary with more than three anagrams, where an anagram must be another word in the same dictionary. If you think of it as a computational task, you will end up with an endless effort, trying to work out all the combinations of each word and then comparing it to the other words in the list. However, if you analyze the data at hand, you'll realize that each word may be represented by a record containing the word itself and a sorted array of its letters as ID. Armed with such knowledge, finding anagrams means just sorting the list on the additional field and picking up the ones that share the same ID. The brute force algorithm may take several days to run, while the smart one is just a matter of a few seconds. Remember this example the next time you are facing an intractable problem.
10 |
11 | Next [Team Skills - How to Manage Development Time](../Team-Skills/01-How to Manage Development Time.md)
12 |
--------------------------------------------------------------------------------
/en/2-Intermediate/README.md:
--------------------------------------------------------------------------------
1 | # 2. Intermediate
2 | [//]: # (Version:1.0.0)
3 | - Personal Skills
4 | - [How to Stay Motivated](Personal-Skills/01-How to Stay Motivated.md)
5 | - [How to be Widely Trusted](Personal-Skills/02-How to be Widely Trusted.md)
6 | - [How to Tradeoff Time vs. Space](Personal-Skills/03-How to Tradeoff Time vs Space.md)
7 | - [How to Stress Test](Personal-Skills/04-How to Stress Test.md)
8 | - [How to Balance Brevity and Abstraction](Personal-Skills/05-How to Balance Brevity and Abstraction.md)
9 | - [How to Learn New Skills](Personal-Skills/06-How to Learn New Skills.md)
10 | - [Learn to Type](Personal-Skills/07-Learn to Type.md)
11 | - [How to Do Integration Testing](Personal-Skills/08-How to Do Integration Testing.md)
12 | - [Communication Languages](Personal-Skills/09-Communication Languages.md)
13 | - [Heavy Tools](Personal-Skills/10-Heavy Tools.md)
14 | - [How to analyze data](Personal-Skills/11-How to analyze data.md)
15 | - Team Skills
16 | - [How to Manage Development Time](Team-Skills/01-How to Manage Development Time.md)
17 | - [How to Manage Third-Party Software Risks](Team-Skills/02-How to Manage Third-Party Software Risks.md)
18 | - [How to Manage Consultants](Team-Skills/03-How to Manage Consultants.md)
19 | - [How to Communicate the Right Amount](Team-Skills/04-How to Communicate the Right Amount.md)
20 | - [How to Disagree Honestly and Get Away with It](Team-Skills/05-How to Disagree Honestly and Get Away with It.md)
21 | - Judgment
22 | - [How to Tradeoff Quality Against Development Time](Judgment/01-How to Tradeoff Quality Against Development Time.md)
23 | - [How to Manage Software System Dependence](Judgment/02-How to Manage Software System Dependence.md)
24 | - [How to Decide if Software is Too Immature](Judgment/03-How to Decide if Software is Too Immature.md)
25 | - [How to Make a Buy vs. Build Decision](Judgment/04-How to Make a Buy vs Build Decision.md)
26 | - [How to Grow Professionally](Judgment/05-How to Grow Professionally.md)
27 | - [How to Evaluate Interviewees](Judgment/06-How to Evaluate Interviewees.md)
28 | - [How to Know When to Apply Fancy Computer Science](Judgment/07-How to Know When to Apply Fancy Computer Science.md)
29 | - [How to Talk to Non-Engineers](Judgment/08-How to Talk to Non-Engineers.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Team-Skills/01-How to Manage Development Time.md:
--------------------------------------------------------------------------------
1 | # How to Manage Development Time
2 | [//]: # (Version:1.0.0)
3 | To manage development time, maintain a concise and up-to-date project plan. A project plan is an estimate, a schedule, a set of milestones for marking progress, and an assignment of your team or your own time to each task on the estimate. It should also include other things you have to remember to do, such as meeting with the quality assurance people, preparing documentation, or ordering equipment. If you are on a team, the project plan should be a consensual agreement, both at the start and as you go.
4 |
5 | The project plan exists to help make decisions, not to show how organized you are. If the project plan is either too long or not up-to-date, it will be useless for making decisions. In reality, these decisions are about individual persons. The plan and your judgement let you decide if you should shift tasks from one person to another. The milestones mark your progress. If you use a fancy project planning tool, do not be seduced into creating a Big Design Up Front (BDUF) for the project, but use it to maintain concision and up-to-dateness.
6 |
7 | If you miss a milestone, you should take immediate action such as informing your boss that the scheduled completion of that project has slipped by that amount. The estimate and schedule could never have been perfect to begin with; this creates the illusion that you might be able to make up the days you missed in the latter part of the project. You might. But it is just as likely that you have underestimated that part as that you have overestimated it. Therefore the scheduled completion of the project has already slipped, whether you like it or not.
8 |
9 | Make sure your plan includes time for: internal team meetings, demos, documentation, scheduled periodic activities, integration testing, dealing with outsiders, sickness, vacations, maintenance of existing products, and maintenance of the development environment. The project plan can serve as a way to give outsiders or your boss a view into what you or your team is doing. For this reason it should be short and up-to-date.
10 |
11 | Next [How to Manage Third-Party Software Risks](02-How to Manage Third-Party Software Risks.md)
12 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Team-Skills/02-How to Manage Third-Party Software Risks.md:
--------------------------------------------------------------------------------
1 | # How to Manage Third-Party Software Risks
2 | [//]: # (Version:1.0.0)
3 | A project often depends on software produced by organizations that it does not control. There are great risks associated with third party software that must be recognized by everyone involved.
4 |
5 | Never, ever, rest any hopes on *vapour*. Vapour is any alleged software that has been promised but is not yet available. This is the surest way to go out of business. It is unwise to be merely sceptical of a software company's promise to release a certain product with a certain feature at a certain date; it is far wiser to ignore it completely and forget you ever heard it. Never let it be written down in any documents used by your company.
6 |
7 | If third-party software is not vapour, it is still risky, but at least it is a risk that can be tackled. If you are considering using third-party software, you should devote energy early on to evaluating it. People might not like to hear that it will take two weeks or two months to evaluate each of three products for suitability, but it has to be done as early as possible. The cost of integrating cannot be accurately estimated without a proper evaluation.
8 |
9 | Understanding the suitability of existing third party software for a particular purpose is very tribal knowledge. It is very subjective and generally resides in experts. You can save a lot of time if you can find those experts. Often times a project will depend on a third-party software system so completely that if the integration fails the project will fail. Express risks like that clearly in writing in the schedule. Try to have a contingency plan, such as another system that can be used or the ability to write the functionality yourself if the risk can't be removed early. Never let a schedule depend on vapour.
10 |
11 | Next [How to Manage Consultants](03-How to Manage Consultants.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Team-Skills/03-How to Manage Consultants.md:
--------------------------------------------------------------------------------
1 | # How to Manage Consultants
2 | [//]: # (Version:1.0.0)
3 | Use consultants, but don't rely on them. They are wonderful people and deserve a great deal of respect. Since they get to see a lot of different projects, they often know more about specific technologies and even programming techniques than you will. The best way to use them is as educators in-house that can teach by example.
4 |
5 | However, they usually cannot become part of the team in the same sense that regular employees are, if only because you may not have enough time to learn their strengths and weaknesses. Their financial commitment is much lower. They can move more easily. They may have less to gain if the company does well. Some will be good, some will be average, and some will be bad, but hopefully your selection of consultants will not be as careful as your selection of employees, so you will get more bad ones.
6 |
7 | If consultants are going to write code, you must review it carefully as you go along. You cannot get to the end of the a project with the risk of a large block of code that has not been reviewed. This is true of all team members, really, but you will usually have more knowledge of the team members closer to you.
8 |
9 | Next [How to Communicate the Right Amount](04-How to Communicate the Right Amount.md)
--------------------------------------------------------------------------------
/en/2-Intermediate/Team-Skills/04-How to Communicate the Right Amount.md:
--------------------------------------------------------------------------------
1 | # How to Communicate the Right Amount
2 | [//]: # (Version:1.0.0)
3 | Carefully consider the cost of a meeting; it costs *its duration multiplied by the number of participants*. Meetings are sometimes necessary, but smaller is usually better. The quality of communication in small meetings is better, and less time overall is wasted. If any one person is bored at a meeting take this as a sign that the meeting should be smaller.
4 |
5 | Everything possible should be done to encourage informal communication. More useful work is done during lunches with colleagues than during any other time. It is a shame that more companies do not recognize nor support this fact.
6 |
7 | Next [How to Disagree Honestly and Get Away with It](05-How to Disagree Honestly and Get Away with It.md)
8 |
--------------------------------------------------------------------------------
/en/2-Intermediate/Team-Skills/05-How to Disagree Honestly and Get Away with It.md:
--------------------------------------------------------------------------------
1 | # How to Disagree Honestly and Get Away with It
2 | [//]: # (Version:1.0.0)
3 | Disagreement is a great opportunity to make a good decision, but it should be handled delicately. Hopefully you feel that you have expressed your thoughts adequately and been heard before the decision is made. In that case there is nothing more to say, and you should decide whether you will stand behind the decision even though you disagree with it. If you can support this decision even though you disagree, say so. This shows how valuable you are because you are independent and are not a yes-man, but respectful of the decision and a team player.
4 |
5 | Sometimes a decision that you disagree with will be made when the decision makers did not have the full benefit of your opinion. You should then evaluate whether to raise the issue on the basis of the benefit to the company or tribe. If it is a small mistake in your opinion, it may not be worth reconsidering. If it is a large mistake in your opinion, then of course you must present an argument.
6 |
7 | Usually, this is not a problem. In some stressful circumstances and with some personality types this can lead to things being taken personally. For instance, some very good programmers lack the confidence needed to challenge a decision even when they have good reason to believe it is wrong. In the worst of circumstances the decision maker is insecure and takes it as a personal challenge to their authority. It is best to remember that in such circumstances people react with the reptilian part of their brains. You should present your argument in private, and try to show how new knowledge changes the basis on which the decision was made.
8 |
9 | Whether the decision is reversed or not, you must remember that you will never be able to say ‘I told you so!’ since the alternate decision was fully explored.
10 |
11 | Next [Judgment - How to Tradeoff Quality Against Development Time](../Judgment/01-How to Tradeoff Quality Against Development Time.md)
12 |
--------------------------------------------------------------------------------
/en/3-Advanced/Compromising-Wisely/01-How to Fight Schedule Pressure.md:
--------------------------------------------------------------------------------
1 | # How to Fight Schedule Pressure
2 | [//]: # (Version:1.0.0)
3 | Time-to-market pressure is the pressure to deliver a good product quickly. It is good because it reflects a financial reality, and is healthy up to a point. Schedule pressure is the pressure to deliver something faster than it can be delivered and it is wasteful, unhealthy, and all too common.
4 |
5 | Schedule pressure exists for several reasons. The people who task programmers do not fully appreciate what a strong work ethic we have and how much fun it is to be a programmer. Perhaps because they project their own behaviour onto us, they believe that asking for it sooner will make us work harder to get it there sooner. This is probably actually true, but the effect is very small, and the damage is very great. Additionally, they have no visibility into what it really takes to produce software. Not being able to see it, and not be able to create it themselves, the only thing they can do is see time-to-market pressure and fuss at programmers about it.
6 |
7 | The key to fighting schedule pressure is simply to turn it into time-to-market pressure. The way to do this to give visibility into the relationship between the available labour and the product. Producing an honest, detailed, and most of all, understandable estimate of all the labour involved is the best way to do this. It has the added advantage of allowing good management decisions to be made about possible functionality trade-offs.
8 |
9 | The key insight that the estimate must make plain is that labour is an almost incompressible fluid. You can't pack more into a span of time anymore than you can pack more water into a container over and above that container's volume. In a sense, a programmer should never say ‘no’, but rather to say ‘What will you give up to get that thing you want?’ The effect of producing clear estimates will be to increase the respect for programmers. This is how other professionals behave. Programmers' hard work will be visible. Setting an unrealistic schedule will also be painfully obvious to everyone. Programmers cannot be hoodwinked. It is disrespectful and demoralizing to ask them to do something unrealistic. Extreme Programming amplifies this and builds a process around it; I hope that every reader will be lucky enough to use it.
10 |
11 | Next [How to Understand the User](02-How to Understand the User.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Compromising-Wisely/02-How to Understand the User.md:
--------------------------------------------------------------------------------
1 | # How to Understand the User
2 | [//]: # (Version:1.0.0)
3 | It is your duty to understand the user, and to help your boss understand the user. Because the user is not as intimately involved in the creation of your product as you are, they behave a little differently:
4 |
5 | - The user generally makes short pronouncements.
6 | - The user has their own job; they will mainly think of small improvements in your product, not big improvements.
7 | - The user can't have a vision that represents the complete body of your product users.
8 |
9 | It is your duty to give them what they really want, not what they say they want. It is however, better to propose it to them and get them to agree that your proposal is what they really want before you begin, but they may not have the vision to do this. Your confidence in your own ideas about this should vary. You must guard against both arrogance and false modesty in terms of knowing what the customer really wants. Programmers are trained to design and create. Market researchers are trained to figure out what people want. These two kinds of people, or two modes of thought in the same person, working harmoniously together give the best chance of formulating the correct vision.
10 |
11 | The more time you spend with users the better you will be able to understand what will really be successful. You should try to test your ideas against them as much as you can. You should eat and drink with them if you can.
12 |
13 | Guy Kawasaki [Rules] has emphasized the importance of *watching* what your users do in addition to listening to them.
14 |
15 | I believe contractors and consultants often have tremendous problems getting their clients to clarify in their own minds what they really want. If you intend to be a consultant, I suggest you choose your clients based on their clear-headedness as well as their pocketbooks.
16 |
17 | Next [How to Get a Promotion](03-How to Get a Promotion.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Compromising-Wisely/03-How to Get a Promotion.md:
--------------------------------------------------------------------------------
1 | # How to Get a Promotion
2 | [//]: # (Version:1.0.0)
3 | To be promoted to a role, act out that role first.
4 |
5 | To get promoted to a title, find out what is expected of that title and do that.
6 |
7 | To get a pay raise, negotiate armed with information.
8 |
9 | If you feel like you are past due for a promotion, talk to your boss about it. Ask them explicitly what you need to do to get promoted, and try to do it. This sounds trite, but often times your perception of what you need to do will differ considerably from your boss's. Also this will pin your boss down in some ways.
10 |
11 | Most programmers probably have an exaggerated sense of their relative abilities in some ways---after all, we can't all be in the top 10%! However, I have seen some people who were seriously unappreciated. One cannot expect everyone's evaluation to perfectly match reality at all times, but I think people are generally moderately fair, with one caveat: you cannot be appreciated without visibility into your work. Sometimes, due to happenstance or personal habits, someone will not be noticed much. Working from home a lot or being geographically separated from your team and boss makes this especially difficult.
12 |
13 | Next [Serving Your Team - How to Develop Talent](../Serving-Your-Team/01-How to Develop Talent.md)
14 |
--------------------------------------------------------------------------------
/en/3-Advanced/README.md:
--------------------------------------------------------------------------------
1 | # 3. Advanced
2 | [//]: # (Version:1.0.0)
3 | - Technological Judgment
4 | - [How to Tell the Hard From the Impossible](Technical-Judgment/01-How to Tell the Hard From the Impossible.md)
5 | - [How to Utilize Embedded Languages](Technical-Judgment/02-How to Utilize Embedded Languages.md)
6 | - [Choosing Languages](Technical-Judgment/03-Choosing Languages.md)
7 | - Compromising Wisely
8 | - [How to Fight Schedule Pressure](Compromising-Wisely/01-How to Fight Schedule Pressure.md)
9 | - [How to Understand the User](Compromising-Wisely/02-How to Understand the User.md)
10 | - [How to Get a Promotion](Compromising-Wisely/03-How to Get a Promotion.md)
11 | - Serving Your Team
12 | - [How to Develop Talent](Serving-Your-Team/01-How to Develop Talent.md)
13 | - [How to Choose What to Work On](Serving-Your-Team/02-How to Choose What to Work On.md)
14 | - [How to Get the Most From Your Team-mates](Serving-Your-Team/03-How to Get the Most From Your Teammates.md)
15 | - [How to Divide Problems Up](Serving-Your-Team/04-How to Divide Problems Up.md)
16 | - [How to Handle Boring Tasks](Serving-Your-Team/05-How to Handle Boring Tasks.md)
17 | - [How to Gather Support for a Project](Serving-Your-Team/06-How to Gather Support for a Project.md)
18 | - [How to Grow a System](Serving-Your-Team/07-How to Grow a System.md)
19 | - [How to Communicate Well](Serving-Your-Team/08-How to Communicate Well.md)
20 | - [How to Tell People Things They Don't Want to Hear](Serving-Your-Team/09-How to Tell People Things They Don't Want to Hear.md)
21 | - [How to Deal with Managerial Myths](Serving-Your-Team/10-How to Deal with Managerial Myths.md)
22 | - [How to Deal with Organizational Chaos](Serving-Your-Team/11-How to Deal with Organizational Chaos.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/01-How to Develop Talent.md:
--------------------------------------------------------------------------------
1 | # How to Develop Talent
2 |
3 | Nietschze exaggerated when he said [Stronger]:
4 |
5 | > What does not destroy me, makes me stronger.
6 |
7 | Your greatest responsibility is to your team. You should know each of them well. You should stretch your team, but not overburden them. You should usually talk to them about the way they are being stretched. If they buy in to it, they will be well motivated. On each project, or every other project, try to stretch them in both a way that they suggest and a way that you think will be good for them. Stretch them not by giving them more work, but by giving them a new skill or better yet a new role to play on the team.
8 |
9 | You should allow people (including yourself) to fail occasionally and should plan for some failure in your schedule. If there is never any failure, there can be no sense of adventure. If there are not occasional failures, you are not trying hard enough. When someone fails, you should be as gentle as you can with them while not treating them as though they had succeeded.
10 |
11 | Try to get each team member to buy in and be well motivated. Ask each of them explicitly what they need to be well-motivated if they are not. You may have to leave them dissatisfied, but you should know what everybody desires.
12 |
13 | You can't give up on someone who is intentionally not carrying their share of the load because of low morale or dissatisfaction and just let them be slack. You must try to get them well-motivated and productive. As long as you have the patience, keep this up. When your patience is exhausted, fire them. You cannot allow someone who is intentionally working below their level to remain on the team, since it is not fair to the team.
14 |
15 | Make it clear to the strong members of your team that you think they are strong by saying so in public. Praise should be public and criticism private.
16 |
17 | The strong members of the team will naturally have more difficult tasks than the weak members of the team. This is perfectly natural and nobody will be bothered by it as long as everyone works hard.
18 |
19 | It is an odd fact that is not reflected in salaries that a good programmer is more productive than 10 bad programmers. This creates a strange situation. It will often be true that you could move faster if your weak programmers would just get out of the way. If you did this you would in fact make more progress in the short term. However, your tribe would lose some important benefits, namely the training of the weaker members, the spreading of tribal knowledge, and the ability to recover from the loss of the strong members. The strong must be gentle in this regard and consider the issue from all angles.
20 |
21 | You can often give the stronger team members challenging, but carefully delineated, tasks.
22 |
23 | Next [How to Choose What to Work On](02-How to Choose What to Work On.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/02-How to Choose What to Work On.md:
--------------------------------------------------------------------------------
1 | # How to Choose What to Work On
2 |
3 | You balance your personal needs against the needs of the team in choosing what aspect of a project to work on. You should do what you are best at, but try to find a way to stretch yourself not by taking on more work but by exercising a new skill. Leadership and communication skills are more important than technical skills. If you are very strong, take on the hardest or riskiest task, and do it as early as possible in the project to decrease risk.
4 |
5 | Next [How to Get the Most From Your Team-mates](03-How to Get the Most From Your Teammates.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/03-How to Get the Most From Your Teammates.md:
--------------------------------------------------------------------------------
1 | # How to Get the Most From Your Team-mates
2 |
3 | To get the most from your team-mates, develop a good team spirit and try to keep every individual both personally challenged and personally engaged.
4 |
5 | To develop team spirit, corny stuff like logoized clothing and parties are good, but not as good as personal respect. If everyone respects everyone else, nobody will want to let anybody down. Team spirit is created when people make sacrifices for the team and think in terms of the good of the team before their own personal good. As a leader, you can't ask for more than you give yourself in this respect.
6 |
7 | One of the keys to team leadership is to facilitate consensus so that everyone has buy in. This occasionally means allowing your team-mates to be wrong. That is, if it does not harm the project too much, you must let some of your team do things their own way, based on consensus, even if you believe with great confidence it is the wrong thing to do. When this happens, don't agree, simply disagree openly and accept the consensus. Don't sound hurt, or like you're being forced into it, simply state that you disagree but think the consensus of the team is more important. This will often cause them to backtrack. Don't insist that they go through with their initial plan if they do backtrack.
8 |
9 | If there is an individual who will not consent after you have discussed the issues from all appropriate sides, simply assert that you have to make a decision and that is what your decision is. If there is a way to judge if your decision will be wrong or if it is later shown to be wrong, switch as quickly as you can and recognize the persons who were right.
10 |
11 | Ask your team, both as a group and individually, what they think would create team spirit and make for an effective team.
12 |
13 | Praise frequently rather than lavishly. Especially praise those who disagree with you when they are praiseworthy. Praise in public and criticize in private; with one exception: sometimes growth or the correction of a fault can't be praised without drawing embarrassing attention to the original fault, so that growth should be praised in private.
14 |
15 | Next [How to Divide Problems Up](04-How to Divide Problems Up.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/04-How to Divide Problems Up.md:
--------------------------------------------------------------------------------
1 | # How to Divide Problems Up
2 |
3 | It's fun to take a software project and divide it up into tasks that will be performed by individuals. This should be done early. Sometimes managers like to think that an estimate can be made without consideration of the individuals that will perform the work. This is impossible since the productivity of individuals varies so widely. Who has particular knowledge about a component also constantly changes and can have an order of magnitude effect on performance.
4 |
5 | Just as a composer considers the timbre of the instrument that will play a part or the coach of an athletic team considers the strengths of each player, the experienced team leader will not usually be able to separate the division of the project into tasks from the team members to which they will be assigned. This is part of the reason that a high-performing team should not be broken up.
6 |
7 | There is a certain danger in this given that people will become bored as they build upon their strengths and never improve their weaknesses or learn new skills. However, specialization is a very useful productivity tool when not overused.
8 |
9 | Next [How to Handle Boring Tasks](05-How to Handle Boring Tasks.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/05-How to Handle Boring Tasks.md:
--------------------------------------------------------------------------------
1 | # How to Handle Boring Tasks
2 |
3 | Sometimes it is not possible to avoid boring tasks that are critical to the success of the company or the project. These tasks can really hurt the morale of those that have to do them. The best technique for dealing with this is to invoke or promote Larry Wall's programmer's virtue of Laziness. Try to find some way to get the computer to do the task for you or to help your team-mates do this. Working for a week on a program to do a task that will take a week to do by hand has the great advantage of being more educational and sometimes more repeatable.
4 |
5 | If all else fails, apologize to those who have to do the boring task, but under no circumstances allow them to do it alone. At a minimum assign a team of two to do the work and promote healthy teamwork to get the task done.
6 |
7 | Next [How to Gather Support for a Project](06-How to Gather Support for a Project.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/06-How to Gather Support for a Project.md:
--------------------------------------------------------------------------------
1 | # How to Gather Support for a Project
2 |
3 | To gather support for a project, create and communicate a vision that demonstrates real value to the organization as a whole. Attempt to let others share in your vision creation. This gives them a reason to support you and gives you the benefit of their ideas. Individually recruit key supporters for your project. Wherever possible, show, don't tell. If possible, construct a prototype or a mock-up to demonstrate your ideas. A prototype is always powerful but in software it is far superior to any written description.
4 |
5 | Next [How to Grow a System](07-How to Grow a System.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/07-How to Grow a System.md:
--------------------------------------------------------------------------------
1 | # How to Grow a System
2 |
3 | The seed of a tree contains the idea of the adult but does not fully realize the form and potency of the adult. The embryo grows. It becomes larger. It looks more like the adult and has more of the uses. Eventually it bears fruit. Later, it dies and its body feeds other organisms.
4 |
5 | We have the luxury of treating software like that. A bridge is not like that; there is never a baby bridge, but merely an unfinished bridge. Bridges are a lot simpler than software.
6 |
7 | It is good to think of software as growing, because it allows us to make useful progress before we have a perfect mental image. We can get feedback from users and use that to correct the growth. Pruning off weak limbs is healthful.
8 |
9 | The programmer must design a finished system that can be delivered and used. But the advanced programmer must do more. You must design a growth path that ends in the finished system. It is your job to take a germ of an idea and build a path that takes it as smoothly as possible into a useful artefact.
10 |
11 | To do this, you must visualize the end result and communicate it in a way that the engineering team can get excited about. But you must also communicate to them a path that goes from wherever they are now to where they want to be with no large leaps. The tree must stay alive the whole time; it cannot be dead at one point and resurrected later.
12 |
13 | This approach is captured in spiral development. Milestones that are never too far apart are used to mark progress along the path. In the ultra-competitive environment of business, it is best if the milestones can be released and make money as early as possible, even if they are far away from a well-designed endpoint. One of the programmer's jobs is to balance the immediate pay-off against future pay-off by wisely choosing a growth path expressed in milestones.
14 |
15 | The advanced programmer has the triple responsibility of growing software, teams, and persons.
16 |
17 | A reader, Rob Hafernik, sent in this comment on this section that I can do no better than to quote in full:
18 |
19 | > I think you under-emphasize the importance here. It's not just systems, but algorithms, user interfaces, data models, and so on. It's absolutely *vital* as you work on a large system to have measurable progress toward intermediate goals. Nothing is as bad as the special horror of getting down to the end and discovering that the whole thing just isn't going to work (look at the recent debacle of the Voter News System). I would even go further and state it as a law of nature: no large, complex system can be implemented from scratch, it can only be evolved from a simple system to a complex system in a series of intentional steps.
20 |
21 | To which one can only reply *Fiat lux*!
22 |
23 | Next [How to Communicate Well](08-How to Communicate Well.md)
24 |
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/08-How to Communicate Well.md:
--------------------------------------------------------------------------------
1 | # How to Communicate Well
2 |
3 | To communicate well, you have to recognize how hard it is. It is a skill unto itself. It is made harder by the fact that the persons with whom you have to communicate are flawed. They do not work hard at understanding you. They speak poorly and write poorly. They are often overworked or bored, and, at a minimum, somewhat focused on their own work rather than the larger issues you may be addressing. One of the advantages of taking classes and practising writing, public speaking, and listening is that if you become good at it you can more readily see where problems lie and how to correct them.
4 |
5 | The programmer is a social animal whose survival depends on communication with her team. The advanced programmer is a social animal whose satisfaction depends on communication with people outside her team.
6 |
7 | The programmer brings order out of chaos. One interesting way to do this is to initiate a proposal of some kind outside the team. This can be done in a *strawman* or *white-paper* format or just verbally. This leadership has the tremendous advantage of setting the terms of the debate. It also exposes you to criticism, and worse, rejection and neglect. The advanced programmer must be prepared to accept this, because she has a unique power and therefore a unique responsibility. Entrepreneurs who are not programmers need programmers to provide leadership in some ways. Programmers are the part of the bridge between ideas and reality that rests on reality.
8 |
9 | I haven't mastered communicating well, but what I'm currently trying is what I think of as a four-pronged approach: After I have my ideas in order and am fully prepared, I try to speak verbally, hand people a white-paper (on real paper, as well as electronically) show them a demo, and then patiently repeat this process. I think a lot of times we are not patient enough in this kind of difficult communication. You should not be disheartened if your ideas are not immediately accepted. If you have invested energy in their preparation, no one will think poorly of you for it.
10 |
11 | Next [How to Tell People Things They Don't Want to Hear](09-How to Tell People Things They Don't Want to Hear.md)
12 |
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/09-How to Tell People Things They Don't Want to Hear.md:
--------------------------------------------------------------------------------
1 | # How to Tell People Things They Don't Want to Hear
2 |
3 | You will often have to tell people things that will make them uncomfortable. Remember that you are doing this for a reason. Even if nothing can be done about the problem, you are telling them as early as possible so they will be well-informed.
4 |
5 | The best way to tell someone about a problem is to offer a solution at the same time. The second best way is to appeal to them for help with the problem. If there is a danger that you won't be believed, you should gather some support for your assertion.
6 |
7 | One of the most unpleasant and common things you will have to say is, ‘The schedule will have to slip.’ The conscientious programmer hates to say this, but must say it as early as possible. There is nothing worse than postponing action when a milestone slips, even if the only action is to inform everyone. In doing this, it is better to do it as a team, at least in spirit, if not physically. You will want your team's input on both where you stand and what can be done about it, and the team will have to face the consequences with you.
8 |
9 | Next [How to Deal with Managerial Myths](10-How to Deal with Managerial Myths.md)
10 |
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/10-How to Deal with Managerial Myths.md:
--------------------------------------------------------------------------------
1 | # How to Deal with Managerial Myths
2 |
3 | The word *myth* sometimes means fiction. But it has a deeper connotation. It also means a story of religious significance that explains the universe and mankind's relationship to it. Managers tend to forget what they learned as programmers and believe in certain myths. It would be as rude and unsuccessful to try to convince them these myths are false as to try to disillusion a devoutly religious person of their beliefs. For that reason, you should recognize these beliefs as myths:
4 |
5 | - More documentation is always better. (They want it, but they don't want you to spend any time on it.)
6 | - Programmers can be equated. (Programmers vary by an order of magnitude.)
7 | - Resources can be added to a late project to speed it. (The cost of communication with the new persons is almost always more taxing than helpful.)
8 | - It is possible to estimate software development reliably. (It is not even theoretically possible.)
9 | - Programmers' productivity can be measured in terms of some simple metric, like lines of code. (If succinctness is power, lines of code are bad, not good.)
10 |
11 | If you have an opportunity, you can try to explain these things, but don't feel bad if you have no success and don't damage your reputation by confronting these myths belligerently. Each of these myths reinforces the manager's idea that they have some actual control over what is going on. The truth is that managers facilitate if they are good, and impede if they are bad.
12 |
13 | Next [How to Deal with Organizational Chaos](11-How to Deal with Organizational Chaos.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Serving-Your-Team/11-How to Deal with Organizational Chaos.md:
--------------------------------------------------------------------------------
1 | # How to Deal with Organizational Chaos
2 |
3 | There are often brief periods of great organizational chaos, such as lay-offs, buyouts, ipos, firings, new hirings, and so on. These are unsettling to everyone, but perhaps a little less unsettling to the programmer whose personal self-esteem is founded in capacity rather than in position. Organizational chaos is a great opportunity for programmers to exercise their magic power. I've saved this for last because it is a deep tribal secret. If you are not a programmer, please stop reading now.
4 |
5 | > Engineers have the power to create and sustain.
6 |
7 | Non-engineers can order people around but, in a typical software company, can create and sustain nothing without engineers, just as engineers typically cannot sell a product or manage a business effectively. This power is proof against almost all of the problems associated with temporary organizational mayhem. When you have it you should ignore the chaos completely and carry on as if nothing is happening. You may, of course, get fired, but if that happens you can probably get a new job because of the magic power. More commonly, some stressed-out person who does not have the magic power will come into your cube and tell you to do something stupid. If you are really sure that it is stupid, it is best to smile and nod until they go away and then carry on doing what you know is best for the company.
8 |
9 | If you are a leader, tell your people to do the same thing and tell them to ignore what anybody else tells them. This course of action is the best for you personally, and is the best for your company or project.
10 |
11 | Next [Glossary](../../GLOSSARY.md)
12 |
--------------------------------------------------------------------------------
/en/3-Advanced/Technical-Judgment/01-How to Tell the Hard From the Impossible.md:
--------------------------------------------------------------------------------
1 | # How to Tell the Hard From the Impossible
2 |
3 | It is our job to do the hard and discern the impossible. From the point of view of most working programmers, something is impossible if either it cannot be grown from a simple system or it cannot be estimated. By this definition what is called research is impossible. A large volume of mere work is hard, but not necessarily impossible.
4 |
5 | The distinction is not facetious because you may very well be asked to do what is practically impossible, either from a scientific point of view or a software engineering point of view. It then becomes your job to help the entrepreneur find a reasonable solution which is merely hard and gets most of what they wanted. A solution is merely hard when it can be confidently scheduled and the risks are understood.
6 |
7 | It is impossible to satisfy a vague requirement, such as ‘Build a system that will compute the most attractive hair style and colour for any person.’ If the requirement can be made more crisp, it will often become merely hard, such as ‘Build a system to compute an attractive hair style and colour for a person, allow them to preview it and make changes, and have the customer satisfaction based on the original styling be so great that we make a lot of money.’ If there is not crisp definition of success, you will not succeed.
8 |
9 | Next [How to Utilize Embedded Languages](02-How to Utilize Embedded Languages.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Technical-Judgment/02-How to Utilize Embedded Languages.md:
--------------------------------------------------------------------------------
1 | # How to Utilize Embedded Languages
2 |
3 | Embedding a programming language into a system has an almost erotic fascination to a programmer. It is one of the most creative acts that can be performed. It makes the system tremendously powerful. It allows you to exercise her most creative and Promethean skills. It makes the system into your friend.
4 |
5 | The best text editors in the world all have embedded languages. This can be used to the extent that the intended audience can master the language. Of course, use of the language can be made optional, as it is in text editors, so that initiates can use it and no one else has to.
6 |
7 | I and many other programmers have fallen into the trap of creating special purpose embedded languages. I fell into it twice. There already exist many languages designed specifically to be embedded languages. You should think twice before creating a new one.
8 |
9 | The real question to ask oneself before embedding a language is: Does this work with or against the culture of my audience? If you intended audience is exclusively non-programmers, how will it help? If your intended audience is exclusively programmers, would they prefer an applications programmers interface (API)? And what language will it be? Programmers don't want to learn a new language that is narrowly used; but if it meshes with their culture they will not have to spend much time learning it. It is a joy to create a new language. But we should not let that blind us to the needs of the user. Unless you have some truly original needs and ideas, why not use an existing language so that you can leverage the familiarity users already have with it?
10 |
11 | Next [Choosing Languages](03-Choosing Languages.md)
--------------------------------------------------------------------------------
/en/3-Advanced/Technical-Judgment/03-Choosing Languages.md:
--------------------------------------------------------------------------------
1 | # Choosing Languages
2 |
3 | The solitary programmer that loves his work (a hacker) can choose the best language for the task. Most working programmers have very little control of the language they will use. Generally, this issue is dictated by pointy-haired bosses who are making a political decision, rather than a technological decision, and lack the courage to promote an unconventional tool even when they know, often with first-hand knowledge, that the less accepted tool is best. In other cases the very real benefit of unity among the team, and to some extent with a larger community, precludes choice on the part of the individual. Often managers are driven by the need to be able to hire programmers with experience in a given language. No doubt they are serving what they perceive to be the best interests of the project or company, and must be respected for that. However, I personally believe this is the most wasteful and erroneous common practice you are likely to encounter.
4 |
5 | But of course, things are never one-dimensional. Even if a core language is mandated and beyond your control, it is often the case that tools and other programs can and should be written in a different language. If a language is to be embedded (and you should always consider it!) the choice of language will depend a lot on the culture of the users. One should take advantage of this to serve your company or project by using the best language for the job, and in so doing make work more interesting.
6 |
7 | Programming languages should really be called notations in that learning one is not at all as difficult as learning a natural language. To beginners and to some outsiders 'learning a new language' seems a daunting task; but after you have three under your belt it's really just a question of becoming familiar with the available libraries. One tends to think of a large system that has components in three or four languages as a messy hodgepodge; but I argue that such a system is in many cases stronger than a one-language system in several ways:
8 |
9 | - There is necessarily loose coupling between the components that are written in different notations (though maybe not clean interfaces),
10 | - You can evolve to a new language/platform easily by rewriting each component individually,
11 | - One language may not be a good fit for the overall system - having multiple languages for your modules allows you to pick the right tool for the job.
12 |
13 | Some of these effects may only be psychological; but psychology matters. In the end, the costs of language tyranny outweigh any advantage that it provides.
14 |
15 | Next [Compromising Wisely - How to Fight a Schedule Pressure](../Compromising-Wisely/01-How to Fight Schedule Pressure.md)
16 |
--------------------------------------------------------------------------------
/en/5-Bibliography.md:
--------------------------------------------------------------------------------
1 | # Appendix A - Bibliography/Websiteography
2 | [//]: # (Version:1.0.0)
3 | ## Books
4 |
5 | [Rules00] Guy Kawasaki, Michelle Moreno, and Gary Kawasaki. 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating and Marketing New Products and Services.
6 |
7 | [RDev96] Steve McConnell. 1996. Microsoft Press. Redmond, Wash. Rapid Development: Taming Wild Software Schedules.
8 |
9 | [CodeC93] Steve McConnell. 1993. Microsoft Press. Redmond, Wash. Code Complete.
10 |
11 | [XP99] Kent Beck. 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change.
12 |
13 | [PlanXP00] Kent Beck and Martin Fowler. 2000. 0201710919. Addison-Wesley. Planning Extreme Programming.
14 |
15 | [Prag99] Andrew Hunt, David Thomas, and Ward Cunningham. 1999. 020161622X. Addison-Wesley. The Pragmatic Programmer: From Journeyman to Master.
16 |
17 | [Stronger] Friedrich Nietzsche. 1889. Twilight of the Idols, "Maxims and Arrows", section 8..
18 |
19 | ## Web Sites
20 |
21 | [PGSite] Paul Graham. 2002. Articles on his website: [http://www.paulgraham.com/articles.html](http://www.paulgraham.com/articles.html). All of them, but especially "Beating the Averages".
22 |
23 | [Hacker] Eric S. Raymond. 2003. How to Become a Hacker. [http://www.catb.org/~esr/faqs/hacker-howto.html](http://www.catb.org/~esr/faqs/hacker-howto.html).
24 |
25 | [HackDict] Eric S. Raymond. 2003. The New Hacker Dictionary. [http://catb.org/esr/jargon/jargon.html](http://catb.org/esr/jargon/jargon.html).
26 |
27 | [ExpCS] Edsger W. Dijkstra. 1986. How Experimental is Computing Science?. [http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF](http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF).
28 |
29 | [Knife] Edsger W. Dijkstra. 1984. On a Cultural Gap. [http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF](http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF).
30 |
31 | Next [History](6-History.md)
--------------------------------------------------------------------------------
/en/6-History.md:
--------------------------------------------------------------------------------
1 | # Appendix B - History
2 | [//]: # (Version:1.0.0)
3 | ## Move to Github
4 |
5 | This essay has been created as a repository on Github so that it can be easily shared, updated and improved. It was copied from [http://samizdat.mines.edu/howto/HowToBeAProgrammer.htm](http://samizdat.mines.edu/howto/HowToBeAProgrammer.htm) by [Braydie Grove](https://github.com/braydie). It was moved to Github in January 2016.
6 |
7 | ## Request for Feedback or Extension
8 |
9 | Please send me any comments you may have on this essay. I consider all suggestions, many of which have already improved this essay.
10 |
11 | I have placed this essay under the GNU Free Documentation License. This license is not specifically designed for essays. Essays are usually intended to be coherent and convincing arguments that are written from a single point of view in a single voice. I hope this essay is a short and pleasant read.
12 |
13 | I also hope that it is instructive. Although not a textbook, it is broken into many small sections to which new sections can be freely added. If so inclined, you are encouraged to expand upon this essay as you see fit, subject to the provisions of the License.
14 |
15 | It may be arrogance to imagine that this document is worthy of extension; but hope springs eternal. I would be joyous if it were extended in the following ways:
16 |
17 | The addition of a comprehensive reading list to each section,
18 |
19 | The addition of more and better sections,
20 |
21 | Translation into other languages, even if only on a subsection-by-subsection basis, and/or
22 |
23 | Criticism or commentary in-lined into the text.
24 |
25 | The ability to build into different formats, such as palm formats and better HTML.
26 |
27 | If you inform me of your work, I will consider it and may include it in subsequent versions that I produce, subject to the provisions of the License. You may of course produce your own versions of this document without my knowledge, as explained in the License.
28 |
29 | Thank you.
30 |
31 | Robert L. Read
32 |
33 | ## Original Version
34 |
35 | The original version of this document was begun by Robert L. Read in the year 2000 and first published electronically at Samizdat Press(http://Samizdat.mines.edu) in 2002. It is dedicated to the programmers of Hire.com.
36 |
37 | After this article was mentioned on Slashdot in 2003, about 75 people sent me email with suggestions and errata. I appreciate them all. There was a lot of duplication, but the following people either made major suggestions or were the first to find a bug that I fixed: Morgan McGuire, David Mason, Tom Moertel, Ninja Programmer (145252) at Slashdot, Ben Vierck, Rob Hafernik, Mark Howe, Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Ioffe, Andrew Wu, David Jeschke, and Tom Corcoran.
38 |
39 | Finally I would like to thank Christina Vallery, whose editing and proofreading greatly improved the second draft, and Wayne Allen, who encouraged me to initiate this.
40 |
41 | ## Original Author's Bio
42 |
43 | Robert L. Read lives in Austin, Texas, with his wife and two children. He is currently a Principal Engineer at Hire.com, where he has worked for four years. Prior to that he founded 4R Technology, which made a scanner-based image analysis quality control tool for the paper industry.
44 |
45 | Rob received a PhD from the University of Texas at Austin in 1995 in Computer Science related to database theory. In 1987 he received a BA in Computer Science from Rice University. He has been a paid programmer since the age of 16.
46 |
47 | Next [License](LICENSE.md)
48 |
--------------------------------------------------------------------------------
/en/7-Contributions.md:
--------------------------------------------------------------------------------
1 | # Contributions
2 | [//]: # (Version:1.0.0)
3 | This repository aims to be a community driven project, and your involvement will ultimately help improve the quality of this guide.
4 |
5 | ## What can I do to contribute?
6 | There are a number of ways to contribute to "How to be a Programmer".
7 |
8 | - Ideas for new sections
9 | - Improvements to existing sections
10 | - Identifying typos or other issues in sections
11 | - Contributing additional links to resources for sections
12 | - General suggestions for improving the project
13 | - Provide translations of the guide
14 |
15 | ## Translations
16 |
17 | Currently this guide has been translated from English into the following languages:
18 |
19 | - Chinese by [ahangchen](https://github.com/ahangchen)
20 |
21 | **If you provide the initial translation of the guide into another language, you become legible to become a contributor on this project to help maintain and review changes made to the translation.**
22 |
23 | ## Contributors
24 |
25 | Github holds a list of all [contributors](https://github.com/braydie/HowToBeAProgrammer/graphs/contributors) to this project.
26 |
27 | ## Editorship and Move to GitHub
28 |
29 | [Braydie Grove](https://www.github.com/braydie) has agreed to serve as editor-in-chief.
30 |
31 | Braydie transposed the original essay into MarkDown and created the repository.
32 |
--------------------------------------------------------------------------------
/en/GLOSSARY.md:
--------------------------------------------------------------------------------
1 | # Glossary
2 | [//]: # (Version:1.0.0)
3 | This is a glossary of terms as used in this essay. These do not necessarily have a standardized meaning to other people. Eric S. Raymond has compiled a massive and informative glossary[HackerDict] that rather surprisingly can pleasurably be read cover-to-cover once you can appreciate a fraction of it.
4 |
5 | ### unk-unk
6 |
7 | Slang for unknown-unknown. Problems that cannot presently even be conceptualized that will steal time away from the project and wreck the schedule.
8 |
9 | ### printlining
10 |
11 | The insertion of statements into a program on a strictly temporary basis that output information about the execution of the program for the purpose of debugging.
12 |
13 | ### logging
14 |
15 | The practice of writing a program so that it can produce a configurable output log describing its execution.
16 |
17 | ### divide and conquer
18 |
19 | A technique of top-down design and, importantly, of debugging that is the subdivision of a problem or a mystery into progressively smaller problems or mysteries.
20 |
21 | ### vapour
22 |
23 | Illusionary and often deceptive promises of software that is not yet for sale and, as often as not, will never materialize into anything solid.
24 |
25 | ### boss
26 |
27 | The person who sets your tasks. In some cases, the user is the boss.
28 |
29 | ### tribe
30 |
31 | The people with whom you share loyalty to a common goal.
32 |
33 | ### low-hanging fruit
34 |
35 | Big improvements that cost little.
36 |
37 | ### Entrepreneur
38 |
39 | The initiator of projects.
40 |
41 | ### business
42 |
43 | A group of people organized for making money.
44 |
45 | ### company
46 |
47 | A group of people organized for making money.
48 |
49 | ### tribe
50 |
51 | A group of people you share cultural affinity and loyalty with.
52 |
53 | ### scroll blindness
54 |
55 | The effect of being unable to find information you need because it is buried in too much other, less interesting information.
56 |
57 | ### wall-clock
58 |
59 | Actually time as measured by a clock on a wall, as opposed to CPU time.
60 |
61 | ### bottleneck
62 |
63 | The most important limitation in the performance of a system. A constriction that limits performance.
64 |
65 | ### master
66 |
67 | A unique piece of information from which all cached copies are derived that serves as the official definition of that data.
68 |
69 | ### heap allocated
70 |
71 | Memory can be said to be heap allocated whenever the mechanism for freeing it is complicated.
72 |
73 | ### garbage
74 |
75 | Memory which is being taken up by objects your application no longer needs.
76 |
77 | ### garbage collector
78 |
79 | A system for recycling garbage.
80 |
81 | ### memory leak
82 |
83 | The unwanted collection of references to objects that prevents garbage collection (or a bug in the garbage collector or memory management system!) that causes the program to gradually increase its memory demands over time.
84 |
85 | ### Extreme Programming
86 |
87 | A style of programming emphasizing communication with the customer and automated testing.
88 |
89 | ### hitting the wall
90 |
91 | To run out of a specific resource causing performance to degrade sharply rather than gradually.
92 |
93 | ### speculative programming
94 |
95 | Producing a feature before it is really known if that feature will be useful.
96 |
97 | ### information hiding
98 |
99 | A design principle that seeks to keep things independent and decoupled by using interfaces that expose as little information as possible.
100 |
101 | ### object-oriented programming
102 |
103 | An programming style emphasizing the the management of state inside objects.
104 |
105 | ### communication languages
106 |
107 | A language designed primarily for standardization rather than execution.
108 |
109 | ### boxes and arrows
110 |
111 | A loose, informal style of making diagrams consisting of boxes and arrows drawn between those boxes to show the relationships. This contrast with formal diagram methodologies, such as UML.
112 |
113 | ### lingua franca
114 |
115 | A language so popular as to be a de facto standard for its field, as French was for international diplomacy at one time.
116 |
117 | ### buy vs. build
118 |
119 | An adjective describing a choice between spending money for software or writing it your self.
120 |
121 | ### mere work
122 |
123 | Work that requires little creativity and entails little risk. Mere work can be estimated easily.
124 |
125 | ### programming notation
126 |
127 | A synonym for programming language that emphasizes the mathematical nature of programming language and their relative simplicity compared to natural languages.
128 |
129 | ### strawman
130 |
131 | A document meant to be the starting point of a technical discussion. A strawman may lead to a stickman, tinman, woodman, ironman, etc.
132 |
133 | ### white-paper
134 |
135 | An informative document that is often meant to explain or sell a product or idea to an audience different than the programmers of that product or idea.
136 |
--------------------------------------------------------------------------------
/en/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | ## Creative Commons Attribution Share-Alike
3 |
4 | "How To Be A Programmer: Community Version" by Robert L. Read with Community is licensed under Creative Commons Attribution Share-Alike Internal v 4.0.
5 |
6 | At present this work will be edited by Braydie Grove and Robert L. Read.
7 |
8 | We will make reasonable attempts to maintain proper attributions of contributions in the section entittle "Contributions". If you make a pull-request with a significant contribution, please add a very brief description of your contribution to that section.
9 |
10 |
11 |
12 | 
How To Be A Programmer: Community Version by Robert L. Read with Community is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
13 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/01-Learn To Debug.md:
--------------------------------------------------------------------------------
1 | # 学会 Debug
2 | [//]: # (Version:1.0.0)
3 | 调试(Debug)是成为一个程序员的基石。调试这个词第一个含义即是移除错误,但真正有意义的含义是,通过检查来观察程序的运行。一个不会调试的程序员等同于瞎子。
4 |
5 | 理想主义者认为设计、分析、复杂的理论或其他东西,是更基本的东西,他们不是现实的程序员。现实的程序员不会活在理想的世界里。即使你是完美的,你也需要与在你周围的主要软件公司或组织 (比如 GNU ) 的代码,和你同事写的代码打交道。这里面大部分的代码以及它们的文档是不完美的。如果不能看透代码的具体执行过程,最轻微的颠簸都会把你永远地抛出去。通常这种可见性只能从实验获得,也就是,调试。
6 |
7 | 调试是一件与程序运行相关的事情,而非与程序本身相关。你从主要的软件公司购买一些产品,你通常不会看到(产品背后的)程序本身。但代码不遵循文档的情况(让你整台机器崩掉是一个常见又特殊的例子)或者文档没有说明的情况仍然会出现。更常见的是,你的程序出现了一个错误,当你检查你写的代码的时候,却不知道这个错误是怎么发生的。不可避免的,这意味着你做的一些假设并不对,或者一些你没有预料到的情况发生了。有时候,神奇的修改源代码的技巧可能会生效。当它无效时,你必须调试了。
8 |
9 | 为了获得一个程序执行过程的可见性,你必须能够执行代码并且从这个过程中观察到什么。有时候这是显而易见的,比如一些正在呈现在屏幕上的东西,或者两个事件之间的延迟。在许多其他的案例中,调试与一些不一定可见的东西相关,比如代码中一些变量的状态,哪一行代码正在被执行,或者一些断言是否持有了一个复杂的数据结构。这些隐藏的细节必须被显露出来。
10 |
11 |
12 | 观察一个正在执行程序的内部的方法通常可按如下分类:
13 |
14 | - 使用一个调试工具;
15 | - Printlining[(戳这里看释义)](../../4-Glossary.md) - 对程序做一个临时的修改,通常是加一些行去打印一些信息;
16 | - 日志 - 用日志的形式为在程序的运行中创建一个永久的视窗。
17 |
18 | 当调试工具稳定可用时,它们是非常美妙的,但 [Printlining](../../4-Glossary.md) 和写日志甚至是更加重要的。调试工具通常落后于编程语言的发展,所以在某些时候它们都可能是无效的。另外,调试工具可能轻微改变程序实际执行的方式。最后,调试有许多种,比如检查一个断言和一个巨大的数据结构,这需要写代码并改变程序的运行。当调试工具可用时,知道如何使用调试工具是一件好事,但学会使用其他两种方式也是至关重要的。
19 |
20 | 当调试需要修改代码的时候,一些初学者会感到害怕。这是可以理解的,这有点像探索型外科手术。但你需要学会打破代码,让它跳起来,你需要学会在它上面做实验,并且需要知道你临时对它做的任何事情都不会使它变得更糟。如果你感受到了这份恐惧,找一位导师 - 就是因为许多人在一开始面对这种恐惧的的时候表现的太脆弱,我们因此失去了很多本可以变成优秀程序员的人。
21 |
22 | Next [如何通过分离问题空间来 Debug](02-How to Debug by Splitting the Problem Space.md)
23 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/02-How to Debug by Splitting the Problem Space.md:
--------------------------------------------------------------------------------
1 | # 如何通过分割问题 Debug
2 | [//]: # (Version:1.0.0)
3 | 调试是有趣的,因为它一开始是个迷。你认为它应该这样做,但实际上它却那样做。很多时候并不仅是这么简单---我给出的任何例子都会被设计来与一些偶尔在现实中会发生的情况相比较。调试需要创造力与智谋。如果说调试有简单之道,那就是在这个谜题上使用分治法。
4 |
5 | 假如,你创建了一个程序,它会依次执行十件事情。当你运行它的时候,它却崩溃了。但你本来的目的并不是想让它崩溃,所以现在一个谜题扔给你了。当你查看输出时,你可以看到序列里前七件事情运行成功了。最后三件事情在输出里却看不到,所以你的谜题变小了:“它是在执行第8、9、10件事的时候崩溃的”。
6 |
7 | 你是否可以设计一个实验来观察它是在哪件事情上崩溃呢?当然,你可以用一个调试器或者我们可以在第8第9件事后面加一些[printlining](../../4-Glossary.md)的语句(或者你正在使用的任何语言里的等价的事情),当我们重新运行它的时候,我们的谜题会变得更小,比如“它是在做第九件事的时候崩溃的”。我发现,把谜题是怎样的一直清楚地记在心里能让我们保持注意力。当几个人在一个问题的压力下一起工作时,很容易忘记最重要的谜题是什么。
8 |
9 | 调试技术中分治的关键和算法设计里的分治是一样的。你只要从中间开始划分,就不用划分太多次,并且能快速地调试。但问题的中点在哪里?这就是真正需要创造力和经验的地方了。
10 |
11 | 对于一个真正的初学者来说,可能发生错误的地方好像在代码的每一行里都有。一开始,你看不到一些你稍后开发的时候才会看到的其它纬度,比如执行过的代码段,数据结构,内存管理,与外部代码的交互,一些有风险的代码,一些简单的代码。对于一个有经验的程序员,这些其他的维度为整个可能出错的事情展示了一个不完美但是有用的思维模型。拥有这样的思维模型能让一个人更高效地找到谜题的中点。
12 |
13 | 一旦你最终划分出了所有可能出错的地方,你必须试着判断错误躲在哪个地方。比如:这样一个谜题,哪一行未知的代码让我的程序崩溃了?你可以这样问自己,出错的代码是在我刚才执行的程序中间的那行代码的前面还是后面?通常你不会那么幸运就能知道错误在哪行代码甚至是哪个代码块。通常谜题更像这个样子的:“图中的一个指针指向了错误的结点还是我的算法里变量自增的代码没有生效?”,在这种情况下你需要写一个小程序去确认图中的指针是否都是对的,来决定分治后的哪个部分可以被排除。
14 |
15 | Next [如何移除错误](03-How to Remove an Error.md)
16 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/03-How to Remove an Error.md:
--------------------------------------------------------------------------------
1 | # 如何移除一个错误
2 | [//]: # (Version:1.0.0)
3 | 我曾有意把检查程序执行和修复错误分割开来,但是当然,调试也意味着移除 bug。理想状况下,当你完美的发现了错误以及它的修复方法时,你会对代码有完美的理解,并且有一种顿悟(啊哈!)的感觉。但由于你的程序会经常使用其他不具有可视性的、没有一致性注释的系统(比如第三方库),所以完美是不可能的。在其他情况下,可能代码是如此的复杂以至于你的理解可能并不完美。
4 |
5 | 在修复 bug 时,你可能想要做最小的改变来修复它。你可能看到一些其他需要改进的东西,但不会同时去改进他们。请使用科学的方法去改进一个东西,并且一次只改变一个东西。修复 bug 最好的方式是能够重现 bug,然后把你的修复替换进去,重新运行你的程序,观察,直到 bug 不再出现。当然,有时候不止一行代码需要修改,但你在逻辑上仍然需要使用一个独立原子(译者注:以前人们认为原子不可再分,所以用用原子来代表不可再分的东西)的改变来修复这个 bug。
6 |
7 | 有时候,可能实际上有几个 bug,但表现出来好像是一个。这取决于你怎么定义 bug,你需要一个一个地修复它们。有时候,程序应该做什么或者原始作者想要做什么是不清晰的。在这种情况下,你必须多加练习,增加经验,评判并为代码赋予你自己的认知。决定它应该做什么,并注释或用其他方式阐述清楚,然后修改代码以遵循你赋予的含义。这是一个进阶或高级的技能,有时甚至比一开始用原始的方式创建这些代码还难,但真实的世界经常是混乱的。你必须修复一个你不能重写的系统。
8 |
9 | Next [如何使用日志调试](04-How to Debug Using a Log.md)
10 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/04-How to Debug Using a Log.md:
--------------------------------------------------------------------------------
1 | # 如何使用日志调试
2 | [//]: # (Version:1.0.0)
3 | *Logging*(日志)是一种编写系统的方式,可以产生一系列信息记录,被称为 log。*Printlining* 只是输出简单的,通常是临时的日志。初学者一定要理解并且使用日志,因为他们对编程的理解是局限的。因为系统的复杂性,系统架构必须理解与使用日志。在理想的状态下,程序运行时产生的日志信息数量需要是可配置的。通常,日志提供了下面三个基本的优点:
4 |
5 | - 日志可以提供一些难以重现的 bug 的有效信息,比如在产品环境中发生的、不能在测试环境重现的 bug。
6 | - 日志可以提供统计和与性能相关的数据,比如语句间流逝过的时间。
7 | - 可配置的情况下,日志允许我们获取普通的信息,使得我们可以在不修改或重新部署代码的情况下调试以处理具体的问题。
8 |
9 | 需要输出的日志数量总是一个简约与信息量的权衡。太多的信息会使得日志变得昂贵,并且造成[*滚动目盲*](../../4-Glossary.md),使得发现你想要的信息变得很困难。但信息太少的话,日志可能不包含你需要的信息。出于这个原因,让日志的输出可配置是非常有用的。通常,日志中的每个记录会标记它在源代码里的位置,执行它的线程(如果可用的话),时间精度,并且通常还有一些额外的有效信息,比如一些变量的值,剩余内存大小,数据对象的数量,等等。这些日志语句撒遍源码,但只出现在主要的功能点和一些可能出现危机的代码里。每个语句可以被赋予一个等级,并且只有在系统被配置成输出相应等级的记录的时候才输出这个等级的记录。你应该设计好日志语句来标记你预期的问题。预估测量程序表现的必要性。
10 |
11 | 如果你有一个永久的日志,printling 现在可以用日志的形式来完成,并且一些调试语句可能会永久地加入日志系统。
12 |
13 | Next [如何理解性能问题](05-How to Understand Performance Problems.md)
14 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/05-How to Understand Performance Problems.md:
--------------------------------------------------------------------------------
1 | # 如何理解性能问题
2 | [//]: # (Version:1.0.0)
3 | 学习理解运行的程序的性能问题与学习 debug 是一样不可避免的。即使你完美、精确地理解了你的代码运行时所产生的开销,你的代码也会调用其他你几乎不能控制的或者几乎不可看透的软件系统。然而,实际上,通常性能问题和调试有点不一样,而且往往要更简单些。
4 |
5 | 假如你或你的客户认为你的一个系统或子系统运行太慢了。在你把它变快之前,你必须构建一个它为什么慢的思维模型。为了做到这个,你可以使用一个图表工具或者一个好的日志,去发现时间或资源真正被花费在什么地方。有一句很有名的格言:90%的时间会花费在10%的代码上。在性能这个话题上,我想补充的是输入输出开销的重要性。通常大部分时间是以某种形式花费在 I/O 上。发现昂贵的 I/O 和昂贵的10%代码是构建思维模型的一个好的开始。
6 |
7 | 计算机系统的性能有很多个维度,很多资源会被消耗。第一种资源是“挂钟时间”,即执行程序的所有时间。记录“挂钟时间”是一件特别有价值的事情,因为它可以告诉我们一些图表工具表现不了的不可预知的情况。然而,这并不总是描绘了整幅图景。有时候有些东西只是稍微多花费了一点点时间,并且不会引爆什么问题,所以在你真实要处理的计算机环境中,多一些处理器时间可能会是更好的选择。相似的,内存,网络带宽,数据库或其他服务器访问,可能最后都比处理器时间要更加昂贵。
8 |
9 | 竞争共享的资源被同步使用,可能导致死锁和互斥。死锁是由于不恰当的同步和请求资源导致线程执行能力的丧失。互斥是对于资源访问的不恰当安排。如果这是可以预料到的,最好在你的项目开始前就采取措施来地衡量线程争抢。即使线程争抢不会发生,对于有效维护它们也是很有帮助的。
10 |
11 | Next [如何修复性能问题](06-How to Fix Performance Problems.md)
12 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/06-How to Fix Performance Problems.md:
--------------------------------------------------------------------------------
1 | # 如何修复性能问题
2 | [//]: # (Version:1.0.0)
3 | 大部分软件都可以通过付出相对较小的努力,让他们比刚发布时快上10到100倍。在市场的压力下,选择一个简单而快速的解决问题的方法是比选择其它方法更为明智而有效率的选择。然而,性能是可用性的一部分,而且通常它也需要被更仔细地考虑。
4 |
5 | 提高一个非常复杂的系统的性能的关键是,充分分析它,来发现其“瓶颈”,或者其资源耗费的地方。优化一个只占用1%执行时间的函数是没有多大意义的。一个简要的原则是,你在做任何事情之前必须仔细思考,除非你认为它能够使系统或者它的一个重要部分至少快两倍。通常会有一种方法来达到这个效果。考虑你的修改会带来的测试以及质量保证的工作需要。每个修改带来一个测试负担,所以最好这个修改能带来一点大的优化。
6 |
7 | 当你在某个方面做了一个两倍提升后,你需要至少重新考虑并且可能重新分析,去发现系统中下一个最昂贵的瓶颈,并且攻破那个瓶颈,得到下一个两倍提升。
8 |
9 | 通常,性能的瓶颈的一个例子是,数牛的数目:通过数脚的数量然后除以4,还是数头的数量。举些例子,我曾犯过的一些错误:没能在关系数据库中,为我经常查询的那一列提供适当的索引,这可能会使得它至少慢了20倍。其他例子还包括在循环里做不必要的 I/O 操作,留下不再需要的调试语句,不再需要的内存分配,还有,尤其是,不专业地使用库和其他的没有为性能充分编写过的子系统。这种提升有时候被叫做“低垂的水果”,意思是它可以被轻易地获取,然后产生巨大的好处。
10 |
11 | 你在用完这些“低垂的水果”之后,应该做些什么呢?你可以爬高一点,或者把树锯倒。你可以继续做小的改进或者你可以严肃地重构整个系统或者一个子系统。(不只是在新的设计里,在信任你的 boss 这方面,作为一个好的程序员,这是一个非常好的使用你的技能的机会)然而,在你考虑重构子系统之前,你应该问你自己,你的建议是否会让它好五倍到十倍。
12 |
13 | Next [如何优化循环](07-How to Optimize Loops.md)
14 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/07-How to Optimize Loops.md:
--------------------------------------------------------------------------------
1 | # 如何优化循环
2 | [//]: # (Version:1.0.0)
3 | 有时候你会遇到循环,或者递归函数,它们会花费很长的执行时间,可能是你的产品的瓶颈。在你尝试使循环变得快一点之前,花几分钟考虑是否有可能把它整个移除掉,有没有一个不同的算法?你可以在计算时做一些其他的事情吗?如果你不能找到一个方法去绕开它,你可以优化这个循环了。这是很简单的,move stuff out。最后,这不仅需要智慧而且需要理解每一种语句和表达式的开销。这里是一些建议:
4 |
5 | - 删除浮点运算操作。
6 | - 非必要时不要分配新的内存。
7 | - 把常量都放在一起声明。
8 | - 把 I/O 放在缓冲里做。
9 | - 尽量不使用除法。
10 | - 尽量不适用昂贵的类型转换。
11 | - 移动指针而非重新计算索引。
12 |
13 | 这些操作的具体代价取决于你的具体系统。在一些系统中,编译器和硬件会为你做一些事情。但必须清楚,有效的代码比需要在特殊平台下理解的代码要好。
14 |
15 | Next [如何处理I/O开销](08-How to Deal with IO Expense.md)
16 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/08-How to Deal with IO Expense.md:
--------------------------------------------------------------------------------
1 | # 如何处理I/O代价
2 | [//]: # (Version:1.0.0)
3 | 在很多问题上,处理器的速度比硬件交流要快得多。这种代价通常是小的 I/O,可能包括网络消耗,磁盘 I/O,数据库查询,文件 I/O,还有其他与处理器不太接近的硬件使用。所以构建一个快速的系统通常是一个提高 I/O,而非在紧凑的循环里优化代码或者甚至优化算法的问题。
4 |
5 | 有两种基本的技术来优化 I/O:缓存和代表(译者注:比如用短的字符代表长的字符)。缓存是通过本地存储数据的副本,再次获取数据时就不需要再执行 I/O,以此来避免 I/O(通常避免读取一些抽象的值)。缓存的关键在于要让哪些数据是主干的,哪些数据是副本变得显而易见。主干的数据只有一份(在一个更新周期里)。缓存有这样一种危险:副本有时候不能立刻反映主干的修改。
6 |
7 | 代表是通过更高效地表示数据来让 I/O 更廉价。这通常会限制其他的要求,比如可读性和可移植性。
8 |
9 | 代表通常可以用他们第一实现中的两到三个因子来做优化。实现这点的技术包括使用二进制表示而非人类可识别的方式,传递数据的同时也传递一个符号表,这样长的符号就不需要被编码,一个极端的例子是哈弗曼编码。
10 |
11 | 另一种有时能够用来优化本地引用的技术是让计算更接近数据。例如,如果你正在从数据库读取一些数据并且在它上面执行一些简单的计算,比如求和,试着让数据库服务器去做这件事,这高度依赖于你正在工作的系统的类型,但这个方面你必须自己探索。
12 |
13 | Next [如何管理内存](09-How to Manage Memory.md)
14 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/09-How to Manage Memory.md:
--------------------------------------------------------------------------------
1 | # 如何管理内存
2 | [//]: # (Version:1.0.0)
3 | 内存是一种你不可以耗尽的珍贵资源。在一段时期里,你可以无视它,但最终你必须决定如何管理内存。
4 |
5 | 堆内存是在单一子程序范围外,需要持续(保留)的空间。一大块内存,在没有东西指向它的时候,是无用的,因此被称为*垃圾*。根据你所使用的系统的不同,你可能需要自己显式释放将要变成垃圾的内存。更多时候你可能使用一个有*垃圾回收器*的系统。一个垃圾回收器会自己注意到垃圾的存在并且在不需要程序员做任何事情的情况下释放它的内存空间。垃圾回收器是奇妙的:它减小了错误,然后增加了代码的简洁性。如果可以的话,使用垃圾回收器。
6 |
7 | 但是即使有了垃圾回收机制,你还是可能把所有的内存填满垃圾。一个典型的错误是把哈希表作为一个缓存,但是忘了删除对哈希表的引用。因为引用仍然存在,被引用者是不可回收但却无用的。这就叫做*内存泄露*。你应该尽早发现并且修复内存泄露。如果你有一个长时间运行的系统,内存可能在测试中不会被耗尽,但可能在用户那里被耗尽。
8 |
9 | 创建新对象在任何系统里都是有点昂贵的。然而,在子程序里直接为局部变量分配内存通常很便宜,因为释放它的策略很简单。你应该避免不必要的对象创建。
10 |
11 | 当你可以定义你一次需要的数量的上界的时候,一个重要的情况出现了:如果这些对象都占用相同大小的内存,你可以使用单独的一块内存,或缓存,来持有所有的这些对象。你需要的对象可以在这个缓存里以循环的方式分配和释放,所以它有时候被称为环缓存。这通常比堆内存分配更快。(译者注:这也被称为对象池。)
12 |
13 | 有时候你需要显式释放已分配的内存,所以它可以被重新分配而非依赖于垃圾回收机制。然后你必须谨慎机智地分配每一块内存,并且为它设计一种在合适的时候重新分配的方式。这种销毁的方式可能随着你创建的对象的不同而不同。你必须保证每个内存分配操作都与一个内存释放操作相匹配。(译者注:在C里面,no malloc no free,在C++里面,no new no delete)。这通常是很困难的,所以程序员通常会实现一种简单的方式或者垃圾回收机制,比如引用计数,来为它们做这件事情。
14 |
15 | Next [如何处理偶现的 Bug](10-How to Deal with Intermittent Bugs.md)
16 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/10-How to Deal with Intermittent Bugs.md:
--------------------------------------------------------------------------------
1 | # 如何处理偶现的 Bugs
2 | [//]: # (Version:1.0.0)
3 | 偶现 bug 是一种类似于外太空50足隐身蝎子的东西。这种噩梦是如此稀少以至于它很难观察,但其出现频率使得它不能被忽视。你不能调试因为你不能找到它。
4 |
5 | 尽管在8个小时后你会开始怀疑,偶现的 bug 必须像其他事情一样遵循相同的逻辑规律。但困难的是它只发生在一些未知的情形。尝试着去记录这个 bug 出现时的情景,这样你可以去推测到底是什么样的可变性。情况可能跟数据的值相关,比如“这只是在我们把*Wyoming*作为一个值输入时发生”,如果这不是可变性的根源,下一个怀疑应该是不合适的同步并发。
6 |
7 | 尝试,尝试,尝试去在一种可控的方式下重现这个 bug。如果你不能重现它,用日志系统给它设置一个圈套,来在你需要的时候,在它真的发生的时候,记录你猜想的,需要的东西。重新设计这个圈套,如果这个bug只发生在产品中,且不在你的猜想中的话,这可能是一个漫长的过程。你从日志中得到的(信息)可能不能提供解决方案,但可能给你足够的信息去优化这个日志。优化后的日志系统可能花很长时间才能被放入产品中使用。然后,你必须等待 bug 重新出现以获得更多的信息。这个循环可能会继续好几次。
8 |
9 | 我曾创建过的最愚蠢的偶现 bug 是在用一个函数式编程语言里为类工程做多线程实现的时候。我非常仔细地保证了函数式程序的并发估计, CPU 的充分使用(在这个例子里,是8个 CPU)。我却简单地忘记了去同步垃圾回收器。系统可能运行了很长一段时间,经常结束在我开始任何一个任务的时候,在任何能被注意到的事情出错之前。我很遗憾地承认在我理解我的错误之前,我甚至开始怀疑硬件了。
10 |
11 | 在工作中我们最近有这样一个偶现的 bug 让我们花了几个星期才发现。我们有一个多线程的基于 Apache™ 的 Java™web 服务器,在维护第一个页面跳转的时候,我们在四个独立线程而非页面跳转线程里,为一个小的集合执行所有的 I/O 操作。每一次跳转会产生明显的卡顿然后停止做任何有用的事情,直到几个小时后,我们的日志才让我们了解到底发生了什么。因为我们有四个线程,在一个线程内部发生这种情况并不是什么大问题,除非所有的四个线程都阻塞了。然后被这些线程排空的队列会迅速填充所有可用的内存,然后导致我们的服务器崩溃。这个 bug 花了我们一个星期去揪出这个问题,但我们仍然不知道什么导致了这个现象,不知道它什么时候会发生,甚至不知道它们阻塞的时候,线程们在干什么。
12 |
13 | 这表明了有关使用第三方软件的一些风险。我们在使用一段授权的代码,从文本中移除HTML标签。受它的起源的影响,我们把它叫做法国脱衣舞者。尽管我们有源代码(由衷感谢!),我们没有仔细研究它,直到查看我们服务器的日志的时候,我们最终意识到是“法国脱衣舞者”使邮件线程阻塞了。
14 |
15 | 这个工具在大多数时候工作得很好,除了处理一些长而不常见的文本时。在那些文本里,代码复杂度是 N 的平方或者更糟。这意味着处理时间与文本的长度的平方成正比。正式由于这些文本通常都会出现,所以我们才可以马上发现这个 bug。如果他们从来都不会出现,我们永远都不会发现这个问题。当它发生时,我们花了几个星期去最终理解并且解决了这个问题。
16 |
17 | Next [如何学习设计技能](11-How to Learn Design Skills.md)
18 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/11-How to Learn Design Skills.md:
--------------------------------------------------------------------------------
1 | # 如何学习设计技能
2 | [//]: # (Version:1.0.0)
3 | 为了学习如何设计软件,你可以在导师做设计的时候,在他身边学习他的行为。然后学习精心编写过的软件片段(译者注:比如 android 系统中的谷歌官方应用源码)。在这之后,你可以读一些关于最新设计技术的书。
4 |
5 | 然后你必须自己动手了。从一个小的工程开始,当你最后完成时,考虑为什么这个设计失败了或成功了,你是怎样偏离你最初的设想的。然后继续去着手大一点的工程,在与其他人合作时会更有希望。设计是一种需要花很多年去学习的关于评判的事情。一个聪明的程序员可以在两个月内充分打好这种基础,然后从这里开始进步。
6 |
7 | 发展出你自己的风格是自然而有用的,但记住,设计是一种艺术,而不是一种技术。人们写的关于这个主题的书都有一种使得它好像是技术的既定的兴趣。不要武断对待特定的设计风格。
8 |
9 | Next [如何进行实验](12-How to Conduct Experiments.md)
10 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Personal-Skills/12-How to Conduct Experiments.md:
--------------------------------------------------------------------------------
1 | # 如何进行实验
2 | [//]: # (Version:1.0.0)
3 | 已故的伟大的 Edsger Dijkstra 曾经充分解释过:计算机科学不是一门实验科学[ExpCS],并且不依赖于电子计算机。当他提出这个观点时,他指的是19世纪60年代。[Knife]
4 |
5 | > ...危害已经出现:主题现在已经变成了“计算机科学” - 这实际上,像是把外科手术引用为“手术刀科学” - 这在人们心中深深植入了这样一个概念:计算机科学是关于机器和它们的外围设备的。
6 |
7 | 编程不应该是一门实验科学,但大多数职业程序员并没有保卫 Dijkstra 对于计算机科学的解释的荣耀。我们必须在实验的领域里工作,正如一部分,但非所有的物理学家做的那样。如果三十年后,编程可以在不进行任何实验的前提下进行,这将是计算机科学的一个巨大成就。
8 |
9 | 你需要进行的实验包括:
10 | - 用小的例子测试系统以验证它们遵循文档,或者在没有文档时,理解它们的反应;
11 | - 测试一些小的代码修改去验证它们是否确实修复了一个 bug;
12 | - 由于对一个系统不完全的理解,需要在两种不同情况下测量它们的性能表现;
13 | - 检查数据的完整性;
14 | - 对困难的或者难以重现的 bug,收集解决方案中可能提示的统计数据。
15 |
16 | 我不认为在这篇文章里我可以讲述实验的设计,你会在实践中学习到这方面的知识。然而,我可以提供两点建议:
17 |
18 | 第一,对你的假设或者你要测试的断言要非常清楚。把假设写下来也是很有用的,尤其是如果你有点迷惑或者与其他人合作时。
19 |
20 | 第二,你会经常发现你必须设计一系列的实验,它们中的每个都基于对最后一个实验的理解。所以,你应该设计你的实验尽量去提供最多的信息。但不幸的是,这会让实验保持简单变的困难 - 你必须通过经验来提升这种权衡的能力。
21 |
22 | Next [团队技能 - 为什么评估很重要](../Team-Skills/01-Why Estimation is Important.md)
23 |
--------------------------------------------------------------------------------
/zh/1-Beginner/README.md:
--------------------------------------------------------------------------------
1 | # 1. 入门
2 | [//]: # (Version:1.0.0)
3 | - 个人技能
4 | - [学会 Debug](Personal-Skills/01-Learn To Debug.md)
5 | - [如何通过分割问题 Debug](Personal-Skills/02-How to Debug by Splitting the Problem Space.md)
6 | - [如何移除一个错误](Personal-Skills/03-How to Remove an Error.md)
7 | - [如何使用日志调试](Personal-Skills/04-How to Debug Using a Log.md)
8 | - [如何理解性能问题](Personal-Skills/05-How to Understand Performance Problems.md)
9 | - [如何解决性能问题](Personal-Skills/06-How to Fix Performance Problems.md)
10 | - [如何优化循环](Personal-Skills/07-How to Optimize Loops.md)
11 | - [如何处理 I/O 开销](Personal-Skills/08-How to Deal with IO Expense.md)
12 | - [如何管理内存](Personal-Skills/09-How to Manage Memory.md)
13 | - [如何处理偶现的 Bug](Personal-Skills/10-How to Deal with Intermittent Bugs.md)
14 | - [如何学习设计技能](Personal-Skills/11-How to Learn Design Skills.md)
15 | - [如何进行实验](Personal-Skills/12-How to Conduct Experiments.md)
16 | - 团队技能
17 | - [为什么预估很重要](Team-Skills/01-Why Estimation is Important.md)
18 | - [如何预估编程时间](Team-Skills/02-How to Estimate Programming Time.md)
19 | - [如何搜索信息](Team-Skills/03-How to Find Out Information.md)
20 | - [如何把人们作为信息源](Team-Skills/04-How to Utilize People as Information Sources.md)
21 | - [如何优雅地写文档](Team-Skills/05-How to Document Wisely.md)
22 | - [如何在垃圾代码上工作](Team-Skills/06-How to Work with Poor Code.md)
23 | - [如何使用源代码控制](Team-Skills/07-How to Use Source Code Control.md)
24 | - [如何进行单元测试](Team-Skills/08-How to Unit Test.md)
25 | - [毫无头绪?休息一下](Team-Skills/09-Take Breaks when Stumped.md)
26 | - [如何决定下班时间](Team-Skills/10-How to Recognize When to Go Home.md)
27 | - [如何与不好相处的人相处](Team-Skills/11-How to Deal with Difficult People.md)
28 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/01-Why Estimation is Important.md:
--------------------------------------------------------------------------------
1 | # 为什么评估很重要
2 | [//]: # (Version:1.0.0)
3 | 为了尽快获得一个可以高效使用的工作软件系统,不仅需要为开发做计划,还需要为文档,部署,市场做计划。在一个商业工程里,这还需要销售和金融计划。没有对开发时间的预测能力,是不可能高效预测以上这些东西的。
4 |
5 | 好的估计提供了预测能力。管理者喜欢,而且应该这么做。事实是这不可能,不论是理论上还是实践上,准确预测开发软件所消耗的时间总是被管理者所忽视。我们总是被要求做那些不可能的事情,而且我们必须诚实地面对它。不论如何,不承认这个任务的不可能性也是不诚实的,必要的时候,需要解释。对于评估来说,会产生很多沟通不畅的情况,因为人们令人吃惊地倾向于一厢情愿地认为下面这句话:
6 | > 我估计,如果我确实理解了这个问题,我们在5周内有50%的可能完成任务(如果在此期间没有人干扰我们的话)。
7 |
8 | 的真实的含义是:
9 |
10 | > 我保证从现在开始五个星期内完成任务。
11 |
12 | 这个常见的解读问题需要你与你的 boss 和客户明确地讨论(就好像把他们当做傻子那样)。重新阐述你的解释,不管对你来讲它们有多么显而易见。
13 |
14 | Next [如何估计编程时间](02-How to Estimate Programming Time.md)
15 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/02-How to Estimate Programming Time.md:
--------------------------------------------------------------------------------
1 | # 如何评估编程时间
2 | [//]: # (Version:1.0.0)
3 | 评估需要实践,也需要劳动。因为它需要花如此长的时间,以至于评估评估本身的时间可能是一个好主意,尤其是你被要求去评估一些巨大的事情。
4 |
5 | 当被要求评估一些比较大的事情的时候,该做的最可靠的事情是先停下来。大多数工程师是充满热情并且是渴望愉悦的,而停下来当然会让他们不开心。但对一个进行中的事情做评估一般是不准确且不可靠的。
6 |
7 | 停下来,使得考虑一些事情或者为任务重新定型成为可能。如果政策压力允许,这是执行评估的最准确的方式,并且它会产生确实的进度。
8 |
9 | 在没有时间做调查的时候,你首先应该非常清晰地建立评估的含义。首先重新阐述要评估的内容和你编写的评估的最后部分。在你准备编写评估的时候应该把这项任务分解为一个个更小的循序渐进的任务,并且使每个小任务需要的时间不超过一天(理想情况是每个任务的长度最多为一天)。最重要的事情是不要漏掉任何事情。例如,文档,测试,规划的时间,与其他小组交流的时间,还有度假时间,这些都是很重要的。如果你每天都要花时间和一些傻逼交流,在评估里为这件事情划一个明确的时间界限。这能让你的boss对于你将要花费的最少时间有了一个认识,并且可能给你更多的时间。
10 |
11 | 我认识一些会隐式地填充评估时间的好的程序员,但我推荐你不要这样做。填充的一个结果是你可能会耗尽别人对你的信任。例如,一个工程师可能为一个将要花费一天的工作评估为三天。这个工程师可能计划花两天去为代码写文档,或者花两天去做一些其他有用的工程。但当任务在一天内完成时,如果它在那天暴露出来的话,这是可以察觉的,并且松懈或高估的表现会出现。为你确实要做的事情做合适的剖析要好得多。如果写文档需要花两倍于编程的时间,并且评估的结果就是这样的,让这对管理者可见就能得到巨大的好处。
12 |
13 | 相反,显式填充。如果一个任务可能花一天,但如果你的方法没有生效,可能花十天 - 用某种方式在你的评估里记下这个情况,否则,至少为这个可能性,评估一个权重计算可能的时间。任何你可以识别和进行评估的风险因素应该在时间表里被体现。一个人不太可能在给定的任何星期都生病。但一个有很多工程师的大项目可能会有一些疾病时间,还有休假时间。或者,是否会有公司内部的强制培训研讨会的可能性呢?如果这可以预估,也把它算进来。当然,还有一些未知的未知,或者 [unk-unk](../../4-Glossary.md) 。Unk-unk 在定义上是不能被独立评估的。你可以尝试为所有 unk-unk 创建一个全局的界线,或者用你与你的 boss 交流好的其他方式去处理它们。然而,你不能让你的 boss 忘记它们的存在。在把评估变成时间表的过程中,把它们遗忘是超级容易的。
14 |
15 | 在一个团队环境里,你应该让任务的执行者去做这种评估,而且你们应该在团队范围内对评估的结果达成一致。人与人在技术,经验,准备和信心上都有很多的不同。当一个牛逼的程序员为他自己评估了时间,然后一些弱一点的程序员被这种评估约束时,灾难就会降临。整个团队在一个一行一行的细致的评估计划上取得的一致,阐述了团队的理解,以及允许在策略上对资源的重新分配的机会(比如,把负担从弱一点的团队成员那里移到强一点的成员那里)。
16 |
17 | 如果有不能评估的大风险,你应该无论如何都要提出来,这是你的责任,这让才能让管理者不会在这个问题上做承诺,以免在风险发生时让管理者难堪。这种情况下,任何需要的事情都有希望被执行来减小这个风险。
18 |
19 | 如果你可以说服你的公司去使用*极限编程*,你只需要评估相当小的事情,这也是更加有趣和有效率的。
20 |
21 | Next [如何发现信息](03-How to Find Out Information.md)
22 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/03-How to Find Out Information.md:
--------------------------------------------------------------------------------
1 | # 如何发现信息
2 | [//]: # (Version:1.0.0)
3 | 你所搜寻的事情的本质决定了你应该如何去寻找它。
4 |
5 | 如果你需要客观的而且容易辨认的*关于具体事物*的信息,例如一个软件的最新补丁版本,可以在Internet搜索,礼貌的询问很多的人,或者发起一个讨论组。不要在网上搜索任何带有观点或主观解释的东西:能够抵达真相的概率太低了。
6 |
7 | 如果你需要“一些主观的普遍知识”,人们对这些东西已有的思考历史,那就去图书馆吧。例如,想要了解数学,蘑菇或着神秘主义,就去图书馆吧。
8 |
9 | 如果你需要知道*如何做一些琐碎的事情*,找两三本关于这个主题的书,仔细阅读。你可以从网络上学到如何做好这些琐碎的事情,比如安装一个软件包。你甚至可以学到一些重要的东西,例如好的编程技术,但相比读一本纸质书的相关部分,你很容易花更多时间在搜索和对结果排序,以及评估结果的权威性。
10 |
11 | 如果你需要*可能没有人知道的信息*,例如,“这个新品牌的软件在海量数据的情况下能工作吗”,你仍然必须在网络和图书馆里搜索。在这些选项都完全竭尽后,你可能需要设计一个实验来搞清楚这个问题。
12 |
13 | 如果你需要一些考虑了某些特殊环境的观点或估值,和一个专家聊聊。例如,如果你想要知道用 Lisp 构建一个现代数据库管理系统是否是一个好主意,你应该和一个 Lisp 专家和一个数据库专家聊一聊。
14 |
15 | 如果你想要知道*它具体是怎样的*,比如一个还未发布的在一个特定程序上更快的算法,跟一些在这个领域工作的人聊聊。
16 |
17 | 如果你想要做一个*只有你自己能做的个人决定*,比如你是否应该开始某个事业,尝试把一些对这个想法有益和有害的点列出来。如果这没有什么用,做一些预测。假设你已经从各个角度研究了这个想法,并且做了所有该做的准备,在心里列举所有的后果,包括好的和坏的,但你仍可能犹豫不决。你现在应该遵循你自己内心的想法,然后让你的大脑停止思考。大多数可用的预测技术都对决定你内心一半的欲望有作用,因为它们在体现你自己完全多义和随机模式的潜意识都很有用。
18 |
19 | Next [如何将人们作为信息源](04-How to Utilize People as Information Sources.md)
20 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/04-How to Utilize People as Information Sources.md:
--------------------------------------------------------------------------------
1 | # 如何把人们作为信息源
2 | [//]: # (Version:1.0.0)
3 | 尊重其他每个人的时间,与你的时间相平衡。问别人问题比得到答案能获得更多。人们会从你的存在和倾听特定的问题从你身上学到东西。你也可以用同样的方式从别人身上学习到东西,你可能学到你正在搜寻的东西的答案。这通常比你的问题更加重要得多。
4 |
5 | 然而,这个问题的价值会减少你在上面做的事情。你毕竟使用了一个人拥有的最珍贵的商品:时间。交流的好处必须与代价相权衡。更进一步,特定的代价和好处在人与人之间都不一样。我强烈相信一个100人的管理者每个月应该花五分钟与他所在的组织的每个人谈话,大概是它们的时间的5%。但十分钟可能太多了,如果他们有1000个员工,5分钟也可能太多了。你与组织中每个人交谈花费的时间取决于他们的角色(而非他们的位置)。你应该和你的 boss 交谈而非和你 boss 的 boss 交谈,但你偶尔也可以和你 boss 的 boss 交谈啦。这可能不太舒服,但我相信你有责任每个月和你的上上级稍微聊聊,什么都行。
6 |
7 | 基本的规则是,每个与你交谈的人都能稍微受益,他们与你聊得更多,他们能获得的收益越少。你的应该给他们提供这种好处,还有得到与他们交流的好处,平衡这种好处与花费的时间。
8 |
9 | 尊重你自己的时间是很重要的。如果和一些人聊天,即使这会消耗他们的时间,结果会节省你很多的时间,那么你应该这样做,除非你认为他们的时间在这个因素上,对整个集体,比你的时间更加有价值。
10 |
11 | 一个奇怪的例子是暑期实习生。一个处于高技术含量位置的暑期实习生不能被期望去完成太多东西;他们可能会把每个人纠缠到地狱。但为什么这是被允许的呢?因为被纠缠的人从实习生身上可以接收到一些重要的东西。他们得到了一点炫耀的机会,他们可能有机会去听到一些新的思想,他们有机会可以从不同的角度去看问题。他们可能会尝试招聘这个实习生,但即使不是这样,他们也获得了很多。
12 |
13 | 如果你真诚地相信别人有一些东西可以告诉你,无论合适,应该询问他们的意见与智慧。这能让他们高兴并且你可以从他们身上学到一些东西,也可以教会他们一些东西。一个好的程序员不会经常需要销售副经理的建议,但如果你需要,你当然应该询问这个问题。我曾经被要求去倾听一些销售电话以便更好地理解我们的销售员工的工作。这不会耗费超过30分钟,但却让我通过这么小的付出就对公司的销售队伍有了深刻的印象。
14 |
15 | Next [如何优雅地写文档](05-How to Document Wisely.md)
16 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/05-How to Document Wisely.md:
--------------------------------------------------------------------------------
1 | # 如何睿智地写文档
2 | [//]: # (Version:1.0.0)
3 | 人生太短,不能写没人会读的废话,如果你写了废话,没人会去读。所以好一点的文档是最好的。经理不会去理解这些东西,因为不好的文档会给他们错误的安全感以至于他们不敢依赖他们的程序员。如果一些人绝对坚持你真的在写没用的文档,就告诉他们“是的”,然后安静的找一份更好的工作。
4 |
5 | 没有其他事情比精确估计 把好的文档转为放松文档要求的估计 更为有效率。真相是冷酷而艰难的:文档,就像测试,会花比开发代码多几倍的时间。
6 |
7 | 首先,写好的文档是好的写作。我建议你找一些关于写作的事情,学习,练习他们。但即使你是一个糟糕的写手或者对你需要写文档的语言掌握不好,这条黄金规则是你真正需要的:己所不欲,勿施于人。花时间去确实地思考谁会读你的文档,他们从文档中想要获得的真正的东西是什么,并且你可以如何把这些东西交给他们。如果你这样做,你将会变成一个超过平均水平的文档编写者,和一个好的程序员。
8 |
9 | 当代码可以自成文档时,与提供文档给非程序员看相反,我认识的最好的程序员们有这样一个普遍的观点:编写具有自我解释功能的代码,仅在你不能通过代码清晰解释其含义的地方,才写注释。有两个好的原因:第一,任何人需要查看代码级别的文档大多数情况下都能够并且更喜欢阅读代码。不可否认的,有经验的程序员似乎比初学者更容易做到这件事,然而,更重要的是,没有文档的话,代码和文档不会是自相矛盾的。源代码最糟糕的情况下可能是错误并且令人困惑的。没有完美编写的文档,可能说谎,这可糟糕一千倍。
10 |
11 | 负责任的程序员也不能让这件事变得更简单些。如何写自解释的代码?那意味着什么?它意味着:
12 |
13 | - 编写知道别人会去阅读的代码(译者注:编写给人看的代码)
14 | - 运用黄金法则
15 | - 选择直接的解决方案,即使你可以更快地获得另一个解决方案
16 | - 牺牲那些可能混淆代码的小的优化
17 | - 为读者考虑,把你珍贵的时间花在让她更加容易阅读的事情上,并且
18 | - 永远不要使用这样的函数名比如 `foo`,`bar`, 或 `doIt`!
19 |
20 | Next [如何在糟糕的代码上工作](06-How to Work with Poor Code.md)
21 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/06-How to Work with Poor Code.md:
--------------------------------------------------------------------------------
1 | # 如何在糟糕的代码上工作
2 | [//]: # (Version:1.0.0)
3 | 工作在别人写的糟糕的代码上是常有的事。不要把他们想得太糟,直到你用他们的鞋子走路时。他们可能被要求非常自觉地快速完成一些东西来满足时间表的压力。不管之前发生了什么,为了在不清晰的代码上工作,你必须理解它。理解它需要花费一些学习时间,你必须坚持从时间表中某些部分划出一部分时间来做这件事。为了理解它们,你必须读源代码,你可能需要在上面做一些实验。
4 |
5 | 即使是为你自己,编写文档也是一个好的时机,因为尝试为你的代码编写文档会强迫你从你可能没有考虑过的角度思考,并且完成的文档可能会有用。当你在做这个时,考虑重写部分或所有代码会消耗你什么东西。是否重写一部分代码事实上真的会节省时间?你重写代码后你会更信任它吗?在这里小心你的傲慢。如果你重写它,你处理它会更容易,但下一个必须阅读它的人是否真的更加容易?如果你重写了,测试的负担在哪里?重新测试的需要是否大于可能获得的好处?
6 |
7 | 在任何对你没有编写的代码的评估中,代码的质量会影响你对风险问题的认识以及一些未知的事情。
8 |
9 | 铭记抽象和封装是很重要的,这两个程序员最好的工具,对糟糕的代码是特别好用的。你可能不能够重新设计一大块代码,但如果你可以为它增加一定量的抽象,你不用重新在这整团迷雾上工作就可以获一些好的设计所带来的好处。特别的,你可以尝试去隔离尤其糟糕的代码,这样他们就可以被独立重构。
10 |
11 | Next [如何使用源代码控制](07-How to Use Source Code Control.md)
12 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/07-How to Use Source Code Control.md:
--------------------------------------------------------------------------------
1 | # 如何使用源代码控制
2 | [//]: # (Version:1.0.0)
3 | 源代码控制系统(又称版本控制系统)让你高效地管理工程。他们对一个人是很有用的,对一个团队是至关重要的。它们追踪不同版本里的所有改变,以至于所有代码都未曾丢失,其含义可以归属于改变。有了源代码控制系统,一个人可以自信地写一些而半途而废的代码和调试的代码,因为你修改的代码被仔细地与提交的、官方的即将与团队共享或发布的代码分割开。
4 |
5 | 我挺晚才开始意识到源代码控制系统的好处,但现在即使是一个人的工程,我也不能离开源代码控制系统。当你们团队在同样的代码基础上工作时,通常它们是必要的。然而,它们有另一个巨大的优点:它们鼓励我们把代码当做一个成长的有机系统。因为每个改变都会被标记为带有名字或数字的修正,一个人会开始认为软件是一种可见的一系列渐进的提升。我认为这对初学者是尤其有用的。
6 |
7 | 使用源代码控制系统的一个好的技术是一直保持在几天后提交更新。在提交后,一定程度上不活跃,不被调用的代码在几天内都不会完成,因此也不会对其他任何人产生任何问题。因提交错误的代码而降低你队友的开发速度是一个严重的错误,这往往是一种禁忌。
8 |
9 | Next [如何进行单元测试](08-How to Unit Test.md)
10 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/08-How to Unit Test.md:
--------------------------------------------------------------------------------
1 | # 如何进行单元测试
2 | [//]: # (Version:1.0.0)
3 | 单元测试,对独立的代码功能片段,由编写代码的团队进行测试,也是一种编码,而非与之不同的一些事情。设计代码的一部分就是设计它该如何被测试。你应该写一个测试计划,即使它只是一句话。有时候测试很简单:“这个按钮看起来好吗?”,有时候它很复杂:“这个匹配算法可以精确地返回正确的匹配结果?”。
4 |
5 | 无论任何可能的时候,使用断言检查以及测试驱动。这不仅能尽早发现 bug,而且在之后也很有用,让你在其他方面担心的谜题得到解决。
6 |
7 | 极限编程开发者广泛高效地编写单元测试,除了推荐他们的作品,我不能做更好的事情了。
8 |
9 | Next [毫无头绪?休息一下](09-Take Breaks when Stumped.md)
10 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/09-Take Breaks when Stumped.md:
--------------------------------------------------------------------------------
1 | # 毫无头绪?,休息一下
2 | [//]: # (Version:1.0.0)
3 | 没有思路时,休息一下。我有时候没有思路时会冥思15分钟,当我回来看问题时,它就神奇地解开了。更大尺度上,一个晚上的睡眠能做到一样的事情,临时切换到其他活动上可能也会有效。
4 |
5 | Next [如何决定下班时间](10-How to Recognize When to Go Home.md)
6 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/10-How to Recognize When to Go Home.md:
--------------------------------------------------------------------------------
1 | # 如何识别下班时间
2 | [//]: # (Version:1.0.0)
3 | 计算机编程是一种活动也是一种文化。不幸的事实是它不是一种看重身心健康的文化。从文化/历史缘由看(例如,在机器空载的晚上工作的需要),还有因为超过市场时间的压力和程序员的缺乏,计算机程序员传统上总是过度工作。我不认为你可以相信你听到的所有故事,但我认为一周工作60小时是常见的,50小时更多的像一个最小值。这意味着实际总是比需要的时间花费得更多。这对一个好的,不仅为他们自己负责而且为他们的同事负责的程序员来说是一个严重的问题。你需要识别什么时候下班,有时候还要建议其他人回家的时间。解决这个问题的固定规则不存在,抚养一个孩子的固定规则也是,出于同样的原因---每个人都是不同的。
4 |
5 | 一周超过60个小时工作对我来说是非常辛苦的,我可以申请挺短的一段时间(大概是一周),有时候在我的预料中。我不知道对一个人来说一周工作超过60小时是否公平,我甚至不知道40小时是否是公平的。然而,我确定,如果你努力工作,却在你额外工作的时间里获得了很少东西,这是很愚蠢的。对我个人来说,我认为做一个懦夫不是一个程序员该做的事。遗憾的是,事实上,程序员经常*被*要求做一个懦夫来为一些人表演,例如一个经理想要给总经理留下深刻印象。程序员经常对此屈服,因为他们希望开心,并且不善拒绝,与此相反的有四道防护墙:
6 | - 尽可能与公司里的任何人交流,这样没人可以误导总经理正在发生的事情;
7 | - 学习明确而防御性地评估和规划,让每个人看到时间表的内容以及它的立场;
8 | - 学会拒绝,在必要时作为一个团队拒绝,并且
9 | - 如果必须的话,退出团队
10 |
11 | 大多数程序员是好的程序员,好的程序员想要做很多东西。为了做到这点,他们需要高效管理他们的时间。从一个问题中兴奋和深陷其中都有一定量的心理惯性。许多程序员发现他们在长久不被打扰的一段时间里能够保持兴奋和集中注意力,这让他们能最好地工作。然而,人们必须睡觉,并且有其他的责任。每个人需要找到一种方式去满足他们的生物节奏和工作节奏。每个程序员需要做任何必须的事情来提供高效的工作周期,比如只参加的某些最关键的会议,以此保留一定的时间。
12 |
13 | 因为我有孩子,我尝试和他们在晚上相处。我自己最好的工作节奏是工作很长的一天,在办公室或办公室附近睡觉(从家到工作我需要很长的转换时间)然后足够早地回家,在我的孩子们睡觉前与他们相处。我觉得这并不舒服,但这是我可以工作的最好的妥协。如果你得了传染病,回家。如果你有自杀的想法,回家。如果你有超过几秒的凶杀的想法,回家。如果有人有严重的心理障碍或者超出心情低落的心理疾病的标志,把他送回家。如果你由于疲劳变得与平时不同地在某种程度上趋于不诚实或失望,休息一下。不要使用药物缓解疲劳。不要滥用咖啡因。
14 |
15 | Next [如何与不好相处的人相处](11-How to Deal with Difficult People.md)
16 |
--------------------------------------------------------------------------------
/zh/1-Beginner/Team-Skills/11-How to Deal with Difficult People.md:
--------------------------------------------------------------------------------
1 | # 如何与不好相处的人相处
2 | [//]: # (Version:1.0.0)
3 | 你可能必须和不好相处的人相处。甚至可能你本身就是一个不好相处的人。如果你是那种与同事和权威人物有许多矛盾的人,你应该珍惜这种独立所暗示的东西,但需要在不牺牲你的智力或原则的前提下提高你的人际交往能力。
4 |
5 | 在这方面没有什么经验,或者先前生活的行为模式在工作场合的经验不能适用的一些程序员,对这种事情会非常困扰。不好相处的人经常习惯于拒绝,并且与他人相比,他们更不容易受社交压力所影响。关键是合适地尊重他们,而非你可能想做的事,但不要充分地满足他们想要的(译者注:他们想要的往往是过分的)。
6 |
7 | 程序员必须作为一个团队一起工作。当分歧出现时,它必须用某种方式解决,它不能被长时间挂起。不好相处的人通常是极度聪明的,并且有一些很有用的意见可以发表。不带对这个人的偏见,倾听并理解不好相处的人是至关重要的。失败的交流通常是分歧的基础,但它有时候可以被巨大的耐心移除。尝试冷静诚恳地保持交流,并且不接受任何可能产生更大矛盾的引诱。在一个合理的尝试理解的周期后,再做决定。
8 |
9 | 不要让一个恶霸强迫你做你所不同意的事情。如果你是老大,做你认为最好的事情。不要为任何个人因素做出决定,并时刻准备好为你的决定做出解释。如果你是一个有着不好相处的同事的团队成员,不要让老大的决定有任何个人影响。如果没有按你的想法发展,全身心地按(已成事实的)另一种方法去做。
10 |
11 | 不好相处的人能够改变与进步。我曾亲眼目睹这种情况,但这很稀少。然而,每个人都有暂时的高兴与失落情绪。
12 |
13 | 每个程序员但尤其是领导都会面临这样一个挑战:让不好相处的人保持完全的忙碌。他们比别人更倾向于枯燥的工作,并且更能被动地忍受。
14 |
15 | Next [进阶技能](../../2-Intermediate)
16 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/01-How to Tradeoff Quality Against Development Time.md:
--------------------------------------------------------------------------------
1 | # 如何在开发质量与开发时间权衡
2 | [//]: # (Version:1.0.0)
3 | 软件开发总是在工程该做什么与完成工程间妥协。但你可能被要求以牺牲你的工程适用性或商业适用性的方式,去交换工程的开发速度。例如,你可能被要求做一些糟糕的软件工程实践,但这将会导致大量维护问题。
4 |
5 | 如果这发生了,你的首要任务是通知你的团队,然后清楚地解释降低质量的代价。在这之后,你对这个问题的理解会比你的 boss 的理解还要更清晰。明白将会失去什么以及将要得到什么,以及在这次失去的东西,能在下一轮中得到什么。在这个过程中,由一个好工程提供的可见性应该会很有用。如果用质量换时间影响了质量保证工作,(向你的 boss 和质量保证人员)指出这个问题。如果用质量换时间会导致在之后的质量保证周期中出现更多的 bug,指出来。
6 |
7 | 如果她仍然坚持,你应该把劣质部分隔离到特殊的你可以在下一个开发周期计划重写或优化的组件中。向你的团队解释这个问题,这样他们可以为此做些计划。
8 |
9 | 忍者程序员在 Slashdot 写下了这样的格言:
10 |
11 | > 记住,一个好的设计会被糟糕的代码实现弹回。如果好的接口和抽象在代码中到处存在,最后的重写会更加痛苦。如果写难以修复的清晰代码很困难,考虑是什么与核心设计冲突的东西导致了这个问题。
12 |
13 | Next [如何管理软件依赖](02-How to Manage Software System Dependence.md)
14 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/02-How to Manage Software System Dependence.md:
--------------------------------------------------------------------------------
1 | # 如何管理软件系统依赖
2 | [//]: # (Version:1.0.0)
3 | 现代软件系统趋向于依赖大量的非直接可控的组件。通过协同与重用,这增加了生产效率。然而,每个组件会带来一些问题:
4 |
5 | - 你该如何修复组件中的 bug?
6 | - 组件限制你使用特殊的硬件或软件系统了吗?
7 | - 如果组件完全坏掉了,你该做什么?
8 |
9 | 某些程度上解耦组件,让它独立可以被移除,总是最好的。如果组件被证明完全不可用,你可能能够使用不同的组件,但你可能必须自己写一个组件。解耦不是可移植性,但这让移植变得简单,这大多数时候是好事。
10 |
11 | 拥有组件源代码可以把风险降到1/4.有了源代码,你可以更容易地评估它,调试它,找到避免踩坑的方法,并且使得修复更容易。如果你进行修复,你必须把修复的内容提交给组件的拥有者,并且让修改合并到官方发布版中,否则你将不适地必须维护一个非官方版本。
12 |
13 | Next [如何判断软件是否太不成熟了](03-How to Decide if Software is Too Immature.md)
14 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/03-How to Decide if Software is Too Immature.md:
--------------------------------------------------------------------------------
1 | # 如何判断软件是否太不成熟了
2 | [//]: # (Version:1.0.0)
3 | 使用其他人写的软件是一种最有效率的构建一个坚实的系统的方法之一。这本不该被排斥,但与此相关的风险必须被检验。最大的一种风险在于,它通过使用变成一个可用产品成熟前的 bug 周期和与软件相关的故障时期。在你考虑将软件系统集成前,不论是你自己写的还是第三方的,考虑它是否足够成熟以使用是非常重要的。这里有十个你应该自问的相关问题:
4 |
5 | 1. 它是蒸汽吗?(那肯定是不成熟的)
6 | 2. 有可用的懂这个软件的人吗?
7 | 3. 你是第一使用者吗?
8 | 4. 有持续使用的强烈动机吗?
9 | 5. 有维护负担吗?
10 | 6. 没有当前的维护者的话,它还能用吗?
11 | 7. 有至少和它的一半那样好的经验丰富的其他可用途径?
12 | 8. 你的团队或公司了解它吗?
13 | 9. 你的团队或公司对它满意吗?
14 | 10. 即使它不好,你可以雇人在它上面工作吗?
15 |
16 | 对这些标准的一点考虑论证了良好构建的自由软件和开源软件在减小企业家风险上的巨大价值
17 |
18 | Next [如何做一个购买或构建决定](04-How to Make a Buy vs Build Decision.md)
19 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/04-How to Make a Buy vs Build Decision.md:
--------------------------------------------------------------------------------
1 | # 如何做购买还是构建的决定
2 | [//]: # (Version:1.0.0)
3 | 一个尝试用软件完成一些任务的企业级公司或工程必须不断做所谓的 *buy vs. build* 的决定。这个问题的不幸在两个方面:似乎忽视了不必*被购买*的开源软件和自由软件。更重要的是,这可能应该被称作*获取与集成 vs. 购买与集成*决定,因为集成的代价需要被考虑。这需要商业上,管理上,工程理解上的大量结合。
4 |
5 | - 你的需要与它的设计意图有多接近?
6 | - 对于你购买的软件,你想要怎样的可移植性?
7 | - 评估集成的代价是什么?
8 | - 集成的代价是什么?
9 | - 购买会增加还是减少长期维护代价?
10 | - 构建会把你放在一个你不想要的商业位置吗?
11 |
12 | 在你构建一些大到足够成为另一整个商品的基础的东西前请三思。这样的想法通常是乐观积极的将会对你的团队做出许多贡献的人提出来的。如果他们的想法很引人注目,你可能会想要改变你的商业计划,但不要在没有周全考虑前就投资一个比你自己的商业还大的解决方案。
13 |
14 | 在考虑了这些问题后,你可能应当准备两个工程计划草案,一个给购买,一个给构建。这会强迫你考虑集成代价。你也应当考虑两种措施的长期维护代价。为了评估集成代价,你必须在购买软件前对它做一个彻底的评估。如果你不能评估好它,你可以假设购买它会有一个不可预料的风险,你应该以此决定是否购买特定的产品。如果考虑后有几个购买决定,需要花一些精力去评估每个决定。
15 |
16 | Next [如何专业地成长](05-How to Grow Professionally.md)
17 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/05-How to Grow Professionally.md:
--------------------------------------------------------------------------------
1 | # 如何专业地成长
2 | [//]: # (Version:1.0.0)
3 | 承担超过你的权力的责任。扮演你想要扮演的角色。对那些对更大组织的成功做出过贡献以及对你个人提供过帮助的人表示感谢与欣赏。
4 |
5 | 如果你想成为团队的领导,去激励与团结。如果你想成为一个经理,担起规划的责任。你通常可以在和领导或经理在一起时,舒服地完成这些事情,因为这使得他们可以抽空去承担更大的责任。如果这太多了以至于你不能尝试,一次只做一点点。
6 |
7 | 评估你自己。如果你想要变成一个好的程序员,询问一些你欣赏的人你怎样才能变成他们那样。你也可以问你的 boss,他可以告诉你的东西会少一些,但对你的事业会有更大的影响。
8 |
9 | 计划学习新技能的方式,包括琐碎的技术类型,比如学习一个新的软件系统,和困难的社交类型,像漂亮的写作,把它们集成到你的工作中。
10 |
11 | Next [如何评估面试者](06-How to Evaluate Interviewees.md)
12 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/06-How to Evaluate Interviewees.md:
--------------------------------------------------------------------------------
1 | # 如何评估面试者
2 | [//]: # (Version:1.0.0)
3 | 评估可能的员工,却没有得到它应得的能量。一个糟糕的雇佣,就像糟糕的婚姻,是非常糟糕的。每个人首要的一部分精力应该投入到招聘上,尽管这很少发生。
4 |
5 | 有不同的面试风格。有的是折磨人的,设计用来把候选人放在巨大压力下。这是为了这样一个有用的目的:在压力下折射出性格缺陷和弱点。候选人对待面试官不会比对待他们自己更诚实,而且,人的自欺能力是令人惊奇的。
6 |
7 | 你应当,最少,对候选人进行两个小时的与口头考核等价的技术技能考核。实践后,你会能够快速了解他们知道什么,快速收缩他们不知道的来标明边界。面试者会尊重这件事情。我有几次听面试者说面试的质量是他们选择公司的一个动机。聪明人会因他们的技能而被雇佣,而非他们之前工作过的地方或他们上了哪个学校或者一些无关紧要的特征。
8 |
9 | 做这些事情,你也应当评估他们的学习能力,这比他们所知道的要更加重要得多。你也应当留心那些难以相处的人所散发出的火药味。你可能能够在面试后通过比较笔记来识别这一点,但在面试的热烈环境中这很难分辨。人们交流的能力以及与人合作的能力比在最新的编程语言上领先更为重要。
10 |
11 | 一个读者有“在家”测验面试的经验。这有一个优点是揭露了一些面试者能良好地自我表现但不能写代码 - 这样的人是很多的。我个人没有尝试过这种技术,但这听起来挺合适的。
12 |
13 | 最后,面试也是一个销售的过程。你应该把你的公司或工程销售给候选人。然而,你是在与程序员谈话,所以不要尝试改变事实。从坏的事物开始讲起,最后以好的事物作为强有力的结束。
14 |
15 | Next [怎么决定什么时候使用奇妙的计算机科学](07-How to Know When to Apply Fancy Computer Science.md)
16 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/07-How to Know When to Apply Fancy Computer Science.md:
--------------------------------------------------------------------------------
1 | # 如何决定什么时候使用奇妙的计算机科学
2 | [//]: # (Version:1.0.0)
3 | 有这样一些,例如算法,数据结构,数学,还有其他极客范的大多数程序员知道但很少使用的东西。实践中,这种奇妙的东西太复杂了,通常是不需要的。例如,当你花费大多数时间在低效的数据库调用上时,提高算法是没有什么用的。不幸的大量编程由让系统相互交流以及使用非常简单的数据结构去构建漂亮的用户界面组成。
4 |
5 | 高科技什么时候是合适的科技?你什么时候应当打开一本书去找一些东西而非一个毫秒级算法?做这些有时候是有用的,但这需要被小心评估。
6 |
7 | 对于潜在的计算机技术三个最重要的考虑是:
8 |
9 | - 它是否充分封装所以其他低级系统风险和复杂度过量增加以及维护代价很低?
10 | - 好处是否是令人惊奇的(例如,成熟系统的两倍或新系统的十倍?)
11 | - 你能够高效测试和评估它吗?
12 |
13 | 如果一个充分独立算法使用了些许奇妙的可以减少硬件消耗或增加整个系统的两倍性能表现的算法,不考虑它可能是有罪的。争论这样一个方法的一个关键是,证明风险确实是相当的低,因为目标技术可能被充分研究过了,唯一的话题是集成的风险。在这里一个程序员的经验和评估能够真的协同奇妙的算法让集成变得容易。
14 |
15 | Next [如何与非工程师交谈](08-How to Talk to Non-Engineers.md)
16 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Judgment/08-How to Talk to Non-Engineers.md:
--------------------------------------------------------------------------------
1 | # 如何与非工程师交谈
2 | [//]: # (Version:1.0.0)
3 | 工程师和程序员(尤其是)通常被主流文化认为与他人不同。这意味着其他人与我们不同。与非工程师交流时,这是值得记在心里的,你应该时刻去理解观众。
4 |
5 | 非工程师聪明,但在创造技术类的东西不像我们那样踏实。我们制造东西。他们销售,处理,统计,管理,但他们在制造上不是专家。他们不像工程师那样擅长团队合作(毫无疑问会有例外。)他们的社交技能在非团队环境里通常像工程师那样,甚至比工程师要好,但他们的工作不总要求他们像我们那样进行亲密,珍贵的交流,以及细致的任务划分。
6 |
7 | 非工程师可能太渴望以至于不能被取悦和与你亲近,他们可能在不是真的对你满意的时候却对你说“是”,或者是因为他们有点怕你,然后不会对你说实话。
8 |
9 | 非工程师可以理解技术的东西,但他们不会做那件甚至对我们来讲都很困难的事情 - 技术评审。他们确实理解技术是如何工作的,但他们不能理解为什么一个特定的方法需要花三个月而另一种方法要花三天。(毕竟,程序员对这种估计也感到事多得可怕。)这相当于一个巨大的和他们协作的机会。
10 |
11 | 与你的团队交谈时,你会不假思索地使用某种程度上的简略表达方式,一种简单的语言更有效率,因为你通常对技术或者特别是你的产品会有许多的共享经验。对于那些没有这些共享经验的人不使用简略表达方式是需要作出一些努力的,特别是你团队内部的人员也在场的时候。这些简略的词汇会让你与那些没有分享到相关经验的人之间构建出一道墙,甚至更糟的是,浪费着他们的时间。
12 |
13 | 与你的团队一起,基本的假设和目标不需要经常重申,大多数谈话集中于细节。与外人一起,就是另一回事了。他们可能不理解你认为理所当然的东西。由于你把这当做理所当然,并且没有重申它们,使得你们的谈话陷入这样一种情况:你可能认为你们相互理解,但事实上有一个巨大的误解。你应当假设你会有错误的交流,并且仔细观察去找出这样的误解。试着总结或将你说的东西分点,来确保他们能够理解。如果你有机会经常与他们见面,花一点时间询问你是否在有效地交流,以及你可以怎样把它做得更好。如果交流有问题,在对他们失望前,寻找方法去提高你自己的实践。
14 |
15 | 我喜欢与非工程师工作。这提供了绝大的机会来学习与传授。你可以经常由实例得到关于你的交流的阐述的指引。工程师被训练于从混乱中梳理秩序,从困惑中得到解释,非工程师会因此喜欢我们。因为我们有技术评审,并且通常可以理解商业话题,我们经常可以发现一个简单的方法来解决问题。
16 |
17 | 很多时候非工程师会出于好意以及一种正确做事情的欲望去规划他们认为会让我们更容易的事情,事实上存在一个仅能通过借助你的技术评审协助外人的观点看到的好得多的方法。我个人喜欢极限编程因为它处理了这种低效,通过与快速评估相结合,使得发现成本与好处最佳结合的方法更加容易。
18 |
19 | Next [高级技能](../../3-Advanced)
20 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/01-How to Stay Motivated.md:
--------------------------------------------------------------------------------
1 | # 如何保持活力
2 | [//]: # (Version:1.0.0)
3 | 创建美丽,有用,聪明的东西的欲望能高度调动程序员的积极性。这是奇妙而令人惊奇的。这种欲望对程序员既不特殊也不普遍,但在程序员中,它是如此强烈而普遍以至于它把程序员与其他角色的人们分割开来。
4 |
5 | 这有一个现实而重要的推论。如果当程序员被要求做一些既不美丽,也没有用,也不漂亮的事情,他们会斗志低落。虽然可以通过做丑陋的,愚蠢的,无聊的东西赚很多的钱,但最后,乐趣才会为公司赚最多的钱。
6 |
7 | 很明显,有一些完全由动机技术组织起来的工业适用这里的情况。这些我可以识别的特定的编程中的事情有:
8 | - 为工作使用最好的语言
9 | - 寻找机会去使用新技术,新语言,新科技
10 | - 尝试在每个工程里学习或教授一些东西,即使很小
11 |
12 | 最后,可能的话,估量个人激励的东西对你工作的影响。例如,修复 bug 时,数一数我完全不感兴趣的 bug 的数目,因为这和仍然存在的 bug 数目是独立的,并且这也是影响我对公司的顾客的增值的最小的可能方式。把每个 bug 和一个高兴的顾客关联起来,*是*对我个人的激励。
13 |
14 | Next [如何被广泛信任](02-How to be Widely Trusted.md)
15 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/02-How to be Widely Trusted.md:
--------------------------------------------------------------------------------
1 | # 如何被广泛信任
2 | [//]: # (Version:1.0.0)
3 | 值得信任,才能被信任。你也应该让别人了解你。如果没人了解你,没人会为你投票。跟你亲近的人一起,比如队友,这应该不是一个问题。对你部门或团队以外的人,你通过责任和博知建立信任。有时有人会滥用信任,并要求无理由的赞同。不要害怕,解释因这种赞同会让你必须放弃什么。
4 |
5 | 不要不懂装懂。与队友以外的人一起时,你必须清除地区分“当下在我脑子里不懂的东西”以及“我曾经没有认识到的东西”。
6 |
7 | Next [如何在时间和空间权衡](03-How to Tradeoff Time vs Space.md)
8 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/03-How to Tradeoff Time vs Space.md:
--------------------------------------------------------------------------------
1 | # 如何在时间与空间权衡
2 | [//]: # (Version:1.0.0)
3 | 没有上过大学的话,你也可以成为一个好的程序员,但你不知道基本的计算复杂度理论的话,你不可能成为一个好的进阶程序员。你不需要知道‘O’的定义,但我个人认为你应该理解‘常量时间’,‘nlogn’,'n²'的区别。你可能可以不靠这方面的知识,凭直觉知道如何在时间和空间之间权衡,但没有这种知识,你将不会有一个和你同事交流的稳固基础。
4 |
5 | 在设计或理解算法的过程中,算法花费的时间有时候是一个以输入量为自变量的函数。当这种情况发生时,如果运行时间与输入量的对数的 n 倍成正比,我们可以说一个算法的最坏/期望/最好情况运行时间是'nlogn',这个定义和阐述的方式也可以被应用在数据结构占用的空间上。
6 |
7 | 对我来时候,计算复杂度理论是美妙的,并且与物理学一样意义深远,并且可能还有很长的路要走!
8 |
9 | 时间(处理器周期)和空间(内存)可以相互交易。工程是关于妥协的,这就是一个好的例子。它并不总是有条理的,然而,编码一些东西时更加紧凑可以节省空间,但要以解码时花费更多的处理时间为代价。你可以通过缓存节省时间,也就是,花费空间去存储某些东西的一个本地副本,但要以维持缓存的一致性为代价。你偶尔可以通过把更多信息放在一个数据结构里来节省时间。这通常只会有较小的空间占用,但可能会使算法复杂化。
10 |
11 | 提高时间空间转换经常把它们中的一个或另一个戏剧性地改变。然而,在你开始做这个工作前,你应该问你自己,你将要优化的是否是最需要优化的?研究算法是有趣的,但你不能让这遮蔽了你的双眼让你看不到这样一个冷酷的事实:优化一些不是问题的问题将不会带来任何明显的区别,但却会造成测试的负担。
12 |
13 | 现代计算机内存越来越便宜,因为不像处理器时间,你在达到边界前你不能看见它,但这种失败是灾难性的。使用内存也有隐藏的代价,比如你影响了其他需要被保留的程序,以及你分配和释放内存的时间。在你想要花更多空间去换取速度之前,请仔细考虑这一点。
14 |
15 | Next [如何进行压力测试](04-How to Stress Test.md)
16 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/04-How to Stress Test.md:
--------------------------------------------------------------------------------
1 | # 如何进行压力测试
2 | [//]: # (Version:1.0.0)
3 | 压力测试很有趣,一开始好像压测的目的是找出系统在负载下能不能工作。现实中,系统在负载下确实能工作,但在负载足够重的某些情况下不能工作。我把这叫做*碰壁*或*撞响*[1]。可能会有例外,但大多数情况下会有这么一堵“墙”。压测的目的是为了指出墙在哪里,然后弄清楚怎么把墙移得更远些。
4 |
5 | 压测计划需要在工程的早期就规划好,因为它经常有助于弄清楚到底什么是被期望的。两秒的网页请求是一个悲伤的失败还是一个了不起的成功?500个并发用户是否足够?这,当然,视情况而定,但一个人在设计系统时就应该知道满足需求的答案。压测需要足够好地为现实建模,使之足够有用。非常容易地模拟500个不稳定并且不可预测的人并行使用系统不是真的可能的,但我们可以至少创造500个模拟(用户),然后尝试模拟他们可能做的部分事情。
6 |
7 | 在压测中,从轻负载开始,然后为系统在一些维度上增加复杂 - 比如输入频率和输入规模 - 直到你抵达那堵墙。如果墙太近了以至于不能满足你的需要,弄明白哪个资源是瓶颈(这通常是那个主要的资源)。它是内存?处理器?I/O?网络带宽?还是数据连接?然后弄明白你可以怎么移动那堵墙。记录下移动墙的那个要素,也就是增加了系统可以处理的负载的那个要素,它可能不能真正在低负载系统下产生危害。但通常重负载下的表现比轻负载下更重要。
8 |
9 | 你必须能够观察几个不同维度,以此来为之构建一个思维模型;单一的技术是不够的。例如,日志经常是给出系统中两个事件间的挂钟时间的好主意。但除非仔细构建,日志不会给出内存使用的可见性甚至是数据结构的大小。相似的,在现代系统里,大量电脑和许多软件系统是合作的。特别是在你碰到那堵墙时(也就是,表现与输入不成线性比例时),这些软件系统可能成为瓶颈。对这些系统的透视力,甚至仅仅对所有参与工作的机器的处理器做测量,都可能是非常有帮助的。
10 |
11 | 意识到墙在哪里的关键不仅是移动这堵墙,而且也是提供对其的预测能力。这样公司可以得到更高效的管理。
12 |
13 | ---
14 |
15 | [1] "撞响"
16 |
17 | Next [如何在简洁与抽象间平衡](05-How to Balance Brevity and Abstraction.md)
18 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/05-How to Balance Brevity and Abstraction.md:
--------------------------------------------------------------------------------
1 | # 如何在简洁与抽象间平衡
2 | [//]: # (Version:1.0.0)
3 | 抽象是编程的关键。你应该仔细选择你需要抽象的程度。充满活力的初学者经常创建许多没有什么用的抽象。一个标识是,你是否创建了这样一个类,不包含任何代码并且没有真的做什么事情,除了抽象一些东西。这种抽象是可以理解的,但代码的简洁性的价值必须与代码的抽象价值相权衡。有时候,我们可以看到一种热情的理想主义者犯的错误:在工程的一开始,定义了一大堆的看起来抽象得很美的类,然后他会推测说它们可以处理每一个可能出现的情况。随着项目推进及琐事掺杂进来,这些代码本身变得混乱了。函数体比他们本来该有的样子还要长。空的类是一种写文档的负担,在压力之下,它们会被忽略。如果让花在抽象上的精力去保持其简短,最后的结果应该会更好。这是一种*推测编程*的形式。我强烈推荐 PAUL gRAHAM[PGSite] 的这篇文章 ['Succinctness is Power' by Paul Graham](http://www.paulgraham.com/power.html)。
4 |
5 | 有这样一种关于*信息封装*和*面向对象编程*的有用技能,但有时候它们被带远了。这些技术让一个人抽象地编码并预计变数。然而,我个人认为,你不应该写太多推测性的代码。例如,在一个对象里用增量器和访问器隐藏一个整数变量是一种可接受的风格,这样变量本身就没有暴露,仅仅暴露了很少的关于它的接口。这确实允许了变量的实现的改变不影响调用代码,并且可能对一个必须提供一个稳定 API 的库编写者是合适的。我不认为这种好处会超过其冗长的代价,特别是当我的团队拥有调用代码并因此可以把调用器重构为比原来的更容易时。四到五行多余的代码会是这种推测性好处的沉重代价。
6 |
7 | 可移植性也有类似的问题。代码是否应当可移植到不同的电脑,编译器,软件系统或平台?还是简单地传输?我认为,不可移植,短而简单传输的代码比长而可移植的代码要好。把不可移植代码限制在特定的领域是一个想对轻松而且无疑是好的主意。比如一个使用了特定 DBMS 的数据库查询的类。
8 |
9 | Next [如何学习新技能](06-How to Learn New Skills.md)
10 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/06-How to Learn New Skills.md:
--------------------------------------------------------------------------------
1 | # 如何学习新技能
2 | [//]: # (Version:1.0.0)
3 | 学习新技能,尤其是非技术类,是最大的一种乐趣。大多数公司会更加有斗志如果它们明白这对程序员来说是多大的激励。
4 |
5 | 人类通过*做*来学。读书和上课是有用的。但你对一个从不写程序的程序员会有任何敬意吗?学习任何技能,你应该把自己放在一个可以练习技能的宽容的位置。学习一个新的编程语言时,在你必须做一个大工程前,试着用它做一个小的工程。学习管理软件项目时,先试着管理一个小的工程。
6 |
7 | 一个好的导师不是你做事情的替代品,而是比一本书更好的存在。你可以提供什么给一个潜在的导师,作为他的知识的交换?至少,你应该努力学习这样他们的时间才不会被浪费。
8 |
9 | 试着让你的 boss 给你正规的训练,但必须知道,这通常并不会比把相同量的时间花在用你想学的技能来简单玩耍要好上多少。然而,要求训练比在我们不完美世界里的玩耍时间要容易得多,尽管大量正规训练只是在课程上睡觉,等着晚餐聚会。
10 |
11 | 如果你领导团队,需要知道他们是怎么学习的,并且通过给他们安排适量的和他们感兴趣的技能的工程来锻炼他们。不要忘记程序员最重要的技能不是技术。让你的团队成员有一个机会去玩,锻炼勇气,诚实,以及交流。
12 |
13 | Next [学会打字](07-Learn to Type.md)
14 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/07-Learn to Type.md:
--------------------------------------------------------------------------------
1 | # 学会打字
2 | [//]: # (Version:1.0.0)
3 | 学会盲打。这是一个进阶技能,因为写代码是如此困难以至于你的打字速度是不太相关的,并且不能削减写代码花费的时间,不管你打字有多好。但是,到了你是一个进阶程序员的时候,你可能花费很多时间在用自然语言给你的同事或他人写东西上。这是对你的责任感是一种有趣的测试,学习这样的东西需要专注的时间,但不怎么有趣。有这样一个传说,当 Michael Tiemann 在 MCC 的时候,人们会站在他的门外面倾听他击键的声音,这种声音是如此的急促以至于难以分辨。
4 |
5 | Next [如何做集成测试](08-How to Do Integration Testing.md)
6 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/08-How to Do Integration Testing.md:
--------------------------------------------------------------------------------
1 | # 如何做集成测试
2 | [//]: # (Version:1.0.0)
3 | 集成测试是对已经进行单元测试的各个部分的一种整合测试。集成是昂贵的,并且它出现在测试中。你必须把这个考虑到你的预计和时间表里。
4 |
5 | 理想情况下,你应该这样组织一个项目,使得最后没有一个阶段是必须通过显式集成来进行的。这比在项目过程中,随着事情完成逐渐集成事情要好得多。如果这是不可避免的,请仔细评估。
6 |
7 | Next [交流语言](09-Communication Languages.md)
8 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/09-Communication Languages.md:
--------------------------------------------------------------------------------
1 | # 交流语言
2 | [//]: # (Version:1.0.0)
3 | 在语法系统里,有一些正式定义的,非编程语言但是*交流语言*的语言,它们为促进交流而非标准而特别设计。2003年,最重要的这种语言有: UML, XML, SQL。你应该熟悉这些东西,这样你就可以很好地交流并且决定什么时候去使用它们。
4 |
5 | UML 是一个丰富的用图表描述设计的正式系统。它的美丽之处在于它既虚拟又正式,在作者和观众都了解 UML 的前提下,可以容纳大量的信息。你需要了解它,因为设计有时候就是用这种方式交流的。有一些非常有用的工具可以让制作 UML 图看起来非常专业。在很多情况下,UML 太正式了,我自己会使用更简单的*箱子与箭头*的风格来设计图标。但我非常确定 UML 对你来说至少跟学习拉丁语一样有用(译者注:国外拉丁语使用很广泛)。
6 |
7 | XML 是设计新标准的标准。这不是一个数据间交换的问题的解决方案,尽管你有时候会看到它在这种情况下出现。更进一步,它是一种受欢迎的对大部分数据交换的无聊部分的自动化,也就是,把表现结构化为线性序列,还有将其转回一个结构。它提供了一些漂亮的类型和正确性检查,尽管,又一次,实践中你可能需要的只是其中的一部分。
8 |
9 | SQL 是一种非常有力而丰富的数据查询和操作语言,而非一种编程语言。它有许多种类,典型地依赖于产品,但这没有标准核心那么重要。SQL 是关系数据库的*巧舌弗兰卡*。你可能可以也可能不可以在任何领域从对关系数据库的理解中受益,但你必须对它们和 SQL 的语法和含义有基本的理解。
10 |
11 | Next [重型工具](10-Heavy Tools.md)
12 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/10-Heavy Tools.md:
--------------------------------------------------------------------------------
1 | # 重型工具
2 | [//]: # (Version:1.0.0)
3 | 随着我们的科技文化的进步,软件技术从不可想象,到研究,到新的产品,到标准化产品,到广泛可用和廉价产品。这些重型工具可以拉动很大的负载,但可能是进阶的,并且需要花大量投资去理解。进阶程序员必须知道如何管理它们以及它们什么时候应该被使用或考虑。
4 |
5 | 现在在我看来,一些最好的重型工具是:
6 |
7 | - 关系数据库;
8 | - 全文搜索引擎;
9 | - 数学库;
10 | - OpenGL;
11 | - XML 解析器;
12 | - 电子表格。
13 |
14 | Next [如何分析数据](11-How to analyze data.md)
15 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Personal-Skills/11-How to analyze data.md:
--------------------------------------------------------------------------------
1 | # 如何分析数据
2 | [//]: # (Version:1.0.0)
3 | 当你检查一个商业活动并且发现了把它转换为软件应用程序的需求时,数据分析是软件开发早期的一个过程。这是一个官方的定义,当你,一个程序员,应该集中注意力在写别人设计的东西的代码时,这可能会让你相信数据分析是一种更应该归入系统分析的行为。如果我们严格遵循软件工程范式,这可能是正确的。有经验的程序员会成为设计者,最尖锐的设计者变成商业分析师,因此被冠名去思考所有数据需要,并且给你充分定义的任务去执行。这不完全是对的,因为数据是每种编程活动的核心。不管你在你的程序里做什么,你不是在移动数据就是在修改数据。商业分析师分析的是更大尺度上的需要,软件设计者更加压榨这个比例以至于,当问题在你的桌上落地时,好像你需要做的所有事情是应用聪明的算法,开始移动已经存在的数据。
4 |
5 | 不是这样的。
6 |
7 | 不管你开始观察它的是哪个阶段,数据是一个良好设计的应用程序主要考虑的因素,如果你仔细观察一个数据分析师是怎么从客户请求中获取需求的,你会意识到,数据扮演了一个基本的角色。分析师创建了所谓的数据流表,所有的数据源被标记出来,信息的流动被塑造出来。清晰定义了什么数据应该是系统的一部分,设计师将会用数据关系,数据交换协议,文件格式的形式塑造数据源,这样任务就准备好传递给程序员了。然而,这个过程还没结束,因为你(程序员)在这个周密的数据提取过程后,需要分析数据以用最好的可能方式表现任务。你的任务的底线是 Niklaus Wirth,多种语言之父,的金句:“算法+数据结构=程序”。这永远不是一个独立的自嗨的算法。每个算法都至少被设计去做一些至少与一段数据相关的事情。
8 |
9 | 因此,由于算法不会在真空中滚动轮子,你需要分析其他人已经为你标记好的数据和必须写入代码的必要的数据。
10 | 一个小例子会使得事情更清楚。实现一个图书馆的搜索程序时,通过你的说明书,用户用类型/作者标题/出版社/出版年份/页数来选择书本。你的程序的中级目标是提供一个合法的 SQL 语句去搜索后端数据库。基于这些需要,你有几个选择:按顺序检查每个控制条件,使用一个 switch 语句,或者几个 if 语句;用一个数据控制数组,把它们与一个事件驱动引擎相连。
11 |
12 | 如果你的需求也包括提高查询性能,通过确认每个项在一个特殊顺序里,你可能考虑使用组件树去构建你的 SQL 语句。正如你可以看到的,算法的选择依赖于你决定使用或将要创建的数据。这样的决定产生高效算法和糟糕算法间的区别。
13 | 然而,效率不是唯一要考虑的因素。你可能在你的代码里使用一打命名变量,让它变得尽可能高效。但这样一段代码可能不能容易地维护。可能为你的变量选择一种合适的容器可以保持相同的速度,此外,在的你同事明年看代码的时候,让他们能够更好地理解代码。更多的,选择一个良好设计的数据结构可能允许他们在不重写代码的前提下,拓展你的代码的功能。长久看来,你对数据的选择决定了你结束代码的工作后,它能工作多久。
14 |
15 | 让我给你看另一个例子,只是一些思想粮食,让我们假设你的任务是找到字典里超过三位的同字异构词(一个异构词必须在同样的字典里有另一个词)。如果你把这当做一个计算任务,你将会结束于无尽的,尝试找出每个单词的所有组合,然后拿它跟列表里的所有其他单词比较,这样一个无尽的努力中。然而,如果你分析了手头的数据,你会意识到,每个单词可能被一个包含这个词本身以及用它的字母作为 ID 的排序数组的记录所代表,这个蛮力算法可能需要运行几天,而小的那个算法只是一件几秒的事。下次面对一个棘手的问题时,记住这个例子。
16 |
17 | Next [团队技能 - 如何管理开发时间](../Team-Skills/01-How to Manage Development Time.md)
18 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/README.md:
--------------------------------------------------------------------------------
1 | # 2. 进阶
2 | [//]: # (Version:1.0.0)
3 | - 个人技能
4 | - [如何保持活力](Personal-Skills/01-How to Stay Motivated.md)
5 | - [如何被广泛信任](Personal-Skills/02-How to be Widely Trusted.md)
6 | - [如何在时间和空间权衡](Personal-Skills/03-How to Tradeoff Time vs Space.md)
7 | - [如何进行压力测试](Personal-Skills/04-How to Stress Test.md)
8 | - [如何在简洁与抽象间平衡](Personal-Skills/05-How to Balance Brevity and Abstraction.md)
9 | - [如何学习新技能](Personal-Skills/06-How to Learn New Skills.md)
10 | - [学会打字](Personal-Skills/07-Learn to Type.md)
11 | - [如何做集成测试](Personal-Skills/08-How to Do Integration Testing.md)
12 | - [沟通语言](Personal-Skills/09-Communication Languages.md)
13 | - [重型工具](Personal-Skills/10-Heavy Tools.md)
14 | - [如何分析数据](Personal-Skills/11-How to analyze data.md)
15 | - 团队技能
16 | - [如何管理开发时间](Team-Skills/01-How to Manage Development Time.md)
17 | - [如何管理第三方软件的风险](Team-Skills/02-How to Manage Third-Party Software Risks.md)
18 | - [如何管理咨询师](Team-Skills/03-How to Manage Consultants.md)
19 | - [如何适量交流](Team-Skills/04-How to Communicate the Right Amount.md)
20 | - [如何直言反对意见以及避免如此](Team-Skills/05-How to Disagree Honestly and Get Away with It.md)
21 | - 判断
22 | - [如何在开发质量和开发时间权衡](Judgment/01-How to Tradeoff Quality Against Development Time.md)
23 | - [如何管理软件系统依赖](Judgment/02-How to Manage Software System Dependence.md)
24 | - [如何判断一个软件是否太不成熟了](Judgment/03-How to Decide if Software is Too Immature.md)
25 | - [如何决定购买还是构建](Judgment/04-How to Make a Buy vs Build Decision.md)
26 | - [如何专业地成长](Judgment/05-How to Grow Professionally.md)
27 | - [如何评估面试者](Judgment/06-How to Evaluate Interviewees.md)
28 | - [如何知道何时实施昂贵的计算机科学](Judgment/07-How to Know When to Apply Fancy Computer Science.md)
29 | - [如何与非工程师交谈](Judgment/08-How to Talk to Non-Engineers.md)
30 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Team-Skills/01-How to Manage Development Time.md:
--------------------------------------------------------------------------------
1 | # 如何管理开发时间
2 | [//]: # (Version:1.0.0)
3 | 管理开发时间,需要维护一个简明且实时更新的计划。一个工程计划是一个估计,一个时间表,一系列取得进步的里程碑,还有对你的团队或者你的时间在每个任务的估计和安排。这也应该包括你需要记得去做的其他事,比如与质量保障人员见面,准备文档,或者订购设备。如果你在一个团队里,工程计划会是一个共同承认的协议,不论是在开始,还是进行的过程中。
4 |
5 | 工程计划存在的意义是帮助做出决定,而非展示你是如何组织的。如果一个工程计划太长或者不是最新的,它对做出决定将是无用的。现实中,这些决定通常是关于独立的个人的。计划和你的判断让你决定你是否应当把任务从一个人身上移到另一个人身上。里程碑标识了你的进展。如果你有一个奇妙的工程规划工具,不要被为工程创建一个表面巨大设计(Big Design Up Front)所迷惑,但可以用它保持清晰和实时性。
6 |
7 | 如果你没有一个里程碑,你应该采取即时的行动,比如通知你的 boss 工程已经滑过的部分中进度的完成。这种估计和时间表可能不会在开始时很完美,这会产生这样一种幻觉,你能够填补工程的上一个部分中错过的日志。你可以。但这很可能是因为你低估了那个部分或者高估了一部分。所以工程进度的完成已经滑过了,不管你是否喜欢。
8 |
9 | 确保你的计划包括了:内部团队会议,写代码,文档,规划周期活动,集成测试,处理外部关系,疾病,休假,已有工程维护,还有开发环境维护。工程计划可以作为一种为局外人或你的 boss 准备的关于你或你的团队正在做的事情的视图。因为如此,所以它应该是短且及时更新的。
10 |
11 | Next [如何管理第三方软件危机](02-How to Manage Third-Party Software Risks.md)
12 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Team-Skills/02-How to Manage Third-Party Software Risks.md:
--------------------------------------------------------------------------------
1 | # 如何管理第三方软件危机
2 | [//]: # (Version:1.0.0)
3 | 一个工程通常依赖于其不能控制的组织所生产的软件,第三方软件危机是每个相关的人都必须意识到的。
4 |
5 | 永远也不要把希望放在*蒸汽*上面。蒸汽是任何所谓的尚未可用然而声称可用的软件。这是最确定的一种破产的方式。仅仅怀疑一个软件公司在某个日期对于某个软件产品的某个特性的承诺是不明智的。更明智的做法是完全忽略它,并且忘记你曾听说过这种事。不要在你的公司使用的任何文档里写下这些东西。
6 |
7 | 如果一个第三方软件不是蒸汽,它仍然是有风险的,但至少它是一个可以处理的蒸汽。如果你正在考虑使用第三方软件, 你应该早点投入一点精力去评估它。人们可能没听说过,评估三个产品的适合性要花两个星期还是两个月,但这必须尽可能及早做。如果没有合适的评估,集成的代价就不能被准确计算。
8 |
9 | 理解已有的为某个特殊目的的第三方软件的适用性是非常见仁见智的东西。这是非常客观的,并且通常住在专家心里。如果你发现了那些专家,你可以节省很多时间。很多时候,一个工程会如此完全地依赖于第三方软件,以至于如果集成失败了,工程就失败了。像时间表里写的那样清晰地表达了危机。如果危机不能被尽早消除,试着订一个为意外准备的计划,比如可用的第二方案,或者自己写下功能点的能力。永远不要让时间表依赖于蒸汽。
10 |
11 | Next [如何管理咨询师](03-How to Manage Consultants.md)
12 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Team-Skills/03-How to Manage Consultants.md:
--------------------------------------------------------------------------------
1 | # 如何管理咨询师
2 | [//]: # (Version:1.0.0)
3 | 使用咨询师,但不要依赖他们。他们是神奇的人,非常值得尊敬。因为他们看过许多不同的工程,他们通常比你知道更多具体技术,甚至是编程技术。最好的使用他们的方式是像家教那样用例子教学。
4 |
5 | 然而,他们通常不能像正常员工那样用相同的感觉融入团队,可能仅仅是因为你没有足够的时间去学习他们的优点和缺点。他们的工资更低。他们更容易离开。如果公司做得好,他们可能得到的更少。有些可能是好的,有些可能与平均水平一致,有些可能挺糟糕,但希望你对咨询师的选择不会像你对雇员的选择那样仔细,这样你会获得更多不好的咨询师。
6 |
7 | 如果咨询师要写代码,你必须在你使用它们前仔细 review。有着大段带风险而没有被 review 的代码,会让你完成不了工程。事实上这对所有的团队成员都是成立的,但你通常有更多与你接近的团队成员的知识。
8 |
9 | Next [如何适量交流](04-How to Communicate the Right Amount.md)
10 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Team-Skills/04-How to Communicate the Right Amount.md:
--------------------------------------------------------------------------------
1 | # 如何适量交流
2 | [//]: # (Version:1.0.0)
3 | 仔细考虑会议的代价:这花费了*随参与者数量倍增的时间*。会议有时候是必要的,但越小越好。小会议的交流质量更好,过度浪费的时间更少。如果一个人在会议感到厌烦,把这当做会议应该更小的标识。
4 |
5 | 非正式交流值得做任何事情去鼓励。更多有用的沟通工作在同事间的午饭可以进行,而非其他的时间。许多公司没有意识到或者不支持这一点,这是一种遗憾。
6 |
7 | Next [如何直言异议以及如何避免](05-How to Disagree Honestly and Get Away with It.md)
8 |
--------------------------------------------------------------------------------
/zh/2-Intermediate/Team-Skills/05-How to Disagree Honestly and Get Away with It.md:
--------------------------------------------------------------------------------
1 | # 如何直言异议以及如何避免
2 | [//]: # (Version:1.0.0)
3 | 异议是一个做出好决定的绝佳机会,但这需要被谨慎处理。你可能会觉得你充分的表达了你的想法,并且在决定做出前,你的意见已经被听取。这种情况下,没有什么可以再说的,你应该决定你是否要支持这个决定,即使你不同意它。如果你可以在自己不同意的情况下,支持这个决定,就这样说实话。这展示了你是多么有价值,因为你是独立的,不是一个唯唯诺诺之人,同时是一个尊重决定的团队成员。
4 |
5 | 有时候一个你不同意的决定,会在决策者没有充分听取你的观点前做出。你应该在公司和集体的基础上评估是否应该提出这个话题。如果在你看来这只是一个小错误,这可能不值得重新考虑。如果在你看来这是一个大错,你当然必须提出异议。
6 |
7 | 通常,这不是一个问题。在一些充满压力的环境下,在一些个人因素下,这会导致事情个人化。例如,一些非常牛逼的程序员缺乏在有好的理由认为一件东西是错的情况下去挑战决议的信心。在最糟的情况下,决策者是不可靠的,并会把这变成一个对权威的挑战。最好记住,这种情况下,人们会用他们大脑中爬虫动物的部分来做出反应。你应该私下提出你的争议,然后尝试展示新的知识是如何改变决议做出的基础的。
8 |
9 | 不管决议是否被推翻,你必须记住你永远不能说出“我的话撂这了,我早就这样告诉你了”这样的话,因为这个决定已经得到了充分探讨。
10 |
11 | Next [判断 - 如何在开发质量和开发时间间权衡](../Judgment/01-How to Tradeoff Quality Against Development Time.md)
12 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Compromising-Wisely/01-How to Fight Schedule Pressure.md:
--------------------------------------------------------------------------------
1 | # 如何与时间压力做斗争
2 | [//]: # (Version:1.0.0)
3 | 发布压力是快速推出好产品的压力。这是好的,因为它反映了市场事实,并且在某个意义上是健康的。时间压力是迫使一个产品更快地推出的压力,这是浪费的,不健康的,并且太普遍了。
4 |
5 | 时间压力的存在是有原因的。给程序员任务的人们没有完全尊重我们的强烈的工作道德以及作为一个程序员的乐趣。可能是因为他们把自己的习惯投射到我们身上,他们相信,要求更快会让我们更加努力工作,使得工程更快完成。这可能确实是对的,但效果很小,损害很大。另外,他们看不到生产软件真实需要的东西。他们看不到,也不能够自己创造,他们能做的唯一事情就是看着发布的压力,然后烦程序员。
6 |
7 | 与时间压力斗争的方法是简单地把它当做发布压力,实现的方法是让可用劳力与产品间的关系变得透明。提供一个诚实,细致,大部分可理解的对所有相关劳力的估计,是一种最好的实现方式。允许做出好的管理决定以权衡可能的功能也是一个附加的好处。
8 |
9 | 必须清楚解释的关键是,预算是一种几乎不可压缩的液体。就像你不能把水放进充满的瓶子里,你不能往充满的时间中填入更多任务。某种意义上,程序员永远不会拒绝,但更喜欢说“得到你想要的东西,你会失去什么?”,做出清晰的预算的效果将会是增加对程序员的尊敬。这也是其专业行为的一种表现。程序员的努力工作会被看到。很明显,设置一个不现实的时间表对每个人都是痛苦的。程序员不能被欺骗。要求他们做一些不现实的东西是对他们的不尊重和不道德。极限编程放大了这个问题,并且围绕它构建了一套流程,我希望每个读者能足够幸运去使用它。
10 |
11 | Next [如何理解用户](02-How to Understand the User.md)
12 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Compromising-Wisely/02-How to Understand the User.md:
--------------------------------------------------------------------------------
1 | # 如何理解用户
2 | [//]: # (Version:1.0.0)
3 | 理解用户以及帮助你的 boss 理解用户是你的责任。因为用户没有像你一样密切地与你的产品的制造产生联系,他们的表现有点不同:
4 |
5 | - 用户通常会做出简短的判断
6 | - 用户有他们自己的工作,他们主要会思考你的产品中小的改进,而非大的改进
7 | - 用户看不到你的产品的整个用户画像
8 |
9 | 你的责任是找出他们真实需要的东西,而非他们说他们需要的东西,然而,更好的是在你开始前给他们提出建议,并且让他们认同你的建议就是他们想要的,但他们也可能没有做这种事的愿景。你对你自己的主意的信心是要看情况的。你必须同时与自大和错误的谦逊做斗争去找出什么是人们真实想要的。这两种人,或者同一个人身上两种思维模式,一同和谐工作会给出最好的机会来给出正确的愿景。
10 |
11 | 你在用户身上花费的时间越多,你就越能更好地理解什么能够真正地成功。你应当尝试在你的用户上尽可能测试你的想法,如果可能的话,你甚至应当和他们一起吃饭。
12 |
13 | Guy Kawasaki [Rules] 强调过在倾听之外,*观察*你的用户的重要性。
14 |
15 | 我相信,合伙人和咨询师让客户说出他们内心真正想要的东西有巨大的困难。如果你想成为一个咨询师,建议你基于用户清晰的头脑以及他们的钱包来选择客户。
16 |
17 | Next [如何得到晋升](03-How to Get a Promotion.md)
18 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Compromising-Wisely/03-How to Get a Promotion.md:
--------------------------------------------------------------------------------
1 | # 如何获得晋升
2 | [//]: # (Version:1.0.0)
3 | 想要被提升为某种角色,先做那个角色该做的事情。
4 |
5 | 为了提升到某个位置,找到那个位置期望做的事情,然后去做。
6 |
7 | 想要得到薪酬的提升,带着信息去协商。
8 |
9 | 如果你觉得你值得得到提升,与你的 boss 聊一聊。清楚地问他们你需要做什么才能获得提升,然后努力去做。这听起来很老套,但大多数时候你对你需要做的事情的追求与你 boss 的想法是不同的。这可能会让你的 boss 在某些程度上有些失落。
10 |
11 | 大多数程序员可能在某些形式上对他们的相对能力有夸张的感觉 --- 毕竟,我们不可能都在前10%里!然而,我也见过一些非常不得志的人。人不能期望每个人的评价在什么时候都完美与现实相同,但我认为人们通常在一定程度上是公平的,有这样一个警告:如果别人看不到你的工作,你就得不到欣赏。有时候,因为偶然或个人习惯,有些人可能得不到太多关注。在家努力工作或者与你的团队和 boss 地理隔离的话,这会变得特别困难。
12 |
13 | Next [服务你的团队 - 如何发展才能](../Serving-Your-Team/01-How to Develop Talent.md)
14 |
--------------------------------------------------------------------------------
/zh/3-Advanced/README.md:
--------------------------------------------------------------------------------
1 | # 3. 高级
2 | [//]: # (Version:1.0.0)
3 | - 技术评审
4 | - [如何从不可能中找到困难的地方](Technical-Judgment/01-How to Tell the Hard From the Impossible.md)
5 | - [如何使用嵌入式语言](Technical-Judgment/02-How to Utilize Embedded Languages.md)
6 | - [选择语言](Technical-Judgment/03-Choosing Languages.md)
7 | - 明智地妥协
8 | - [如何与时间压力斗争](Compromising-Wisely/01-How to Fight Schedule Pressure.md)
9 | - [如何理解用户](Compromising-Wisely/02-How to Understand the User.md)
10 | - [如何得到晋升](Compromising-Wisely/03-How to Get a Promotion.md)
11 | - 服务你们的团队
12 | - [如何发展你们的才能](Serving-Your-Team/01-How to Develop Talent.md)
13 | - [如何选择工作的内容](Serving-Your-Team/02-How to Choose What to Work On.md)
14 | - [如何让你队友的价值最大化](Serving-Your-Team/03-How to Get the Most From Your Teammates.md)
15 | - [如何划分问题](Serving-Your-Team/04-How to Divide Problems Up.md)
16 | - [如何处理无聊的任务](Serving-Your-Team/05-How to Handle Boring Tasks.md)
17 | - [如何为工程获取支持](Serving-Your-Team/06-How to Gather Support for a Project.md)
18 | - [如何发展一个系统](Serving-Your-Team/07-How to Grow a System.md)
19 | - [如何有效地沟通](Serving-Your-Team/08-How to Communicate Well.md)
20 | - [如何告诉别人他们不像知道的东西](Serving-Your-Team/09-How to Tell People Things They Don't Want to Hear.md)
21 | - [如何处理管理神话](Serving-Your-Team/10-How to Deal with Managerial Myths.md)
22 | - [如何处理组织混乱](Serving-Your-Team/11-How to Deal with Organizational Chaos.md)
23 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/01-How to Develop Talent.md:
--------------------------------------------------------------------------------
1 | # 如何发展才能
2 | [//]: # (Version:1.0.0)
3 | Nietschze 夸大了他所说的:
4 |
5 | >那些无法摧毁我的,只会让我更强大
6 |
7 | 你最大的责任是对你的团队负责。你应该非常了解他们中的每个人。你应该激励你的团队,但不要让他们过劳。你通常应该告诉他们他们被激励的方式。如果他们觉得划算,他们会被很好的激励。每个工程中,或者在每个其他的工程里,试着同时用他们建议的以及你认为对他们好的方式去激励他们。激励他们的方法不是给他们更多工作,而是给他们一个新的技能或在团队里扮演一个新的角色。
8 |
9 | 你应该允许人们(包括你自己)偶尔失败,并且应该为一些失败预留一些时间。如果从未有失败,冒险也就没有意义。如果没有偶然的失败,说明其实你没有足够努力。当一个人失败了,你应该尽可能温柔地对待他,但不该把他们像成功了那样对待。
10 |
11 | 为了让每个团队成员被充分激励,问清楚他们中的每个人,如果他们没有动力的话,他们需要什么才能被充分激励。你可能需要让他们保持不满意的状态,但你需要知道每个人需要的是什么。
12 |
13 | 你不能放弃因为低落的情绪或者不满就故意不承担工作的那些人,然后就让他们这样懒散下去。你必须试着让他们充分被激励并且有效率。只要你有耐心,坚持这样做。当你的耐心耗尽时,就解雇他们吧。你不能允许故意不司其职的员工留在团队里,因为这对团队不公平。
14 |
15 | 通过在公众场合这样说,让你团队中的强大成员清楚地知道他们是强大的。表扬应当公开,批评应当私密。
16 |
17 | 团队中的强大成员会自然地比弱的成员有更多困难的任务。这是完美而自然的,没人会因此困扰,因为每个人都在努力工作。
18 |
19 | 一个在工资中没有反馈出来的奇怪的事实是,好的程序员比十个糟糕的程序员要有效率得多。这导致了一种奇怪的现象。通常,如果你们的弱程序员不挡道的话,你能跑的更快。如果你这样做了,事实上你在短期能取得更多进度。然而, 你的交易会失去一些重要的好处,叫做对弱小成员的训练,对集体知识的传递,失去强大程序员后的恢复能力。强大的程序员对这种现象应该温和些,并且从各种角度去考虑这个问题。
20 |
21 | 你可以经常给强大的团队成员有挑战的,但细致描绘的任务。
22 |
23 | Next [如何选择工作的内容](02-How to Choose What to Work On.md)
24 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/02-How to Choose What to Work On.md:
--------------------------------------------------------------------------------
1 | # 如何选择工作的内容
2 | [//]: # (Version:1.0.0)
3 | 你需要在你个人的需要和团队的需要间权衡,选择需要做工程中的哪个部分。你应该做你最擅长的东西,但是也要试着去找一种方式来激励自己,不是通过承担更多的工作而是通过练习新的技能。领导才能和交流能力比技术能力更重要。如果你非常强大,承担最困难或最有风险的任务,在工程中尽可能早地完成这部分,以此减少风险。
4 |
5 | Next [如何让你队友的价值最大化](03-How to Get the Most From Your Teammates.md)
6 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/03-How to Get the Most From Your Teammates.md:
--------------------------------------------------------------------------------
1 | # 如何让你队友的价值最大化
2 | [//]: # (Version:1.0.0)
3 | 为了让你的队友的价值最大化,发展好的团队精神,试着保持每个人的个人挑战与渴望。
4 |
5 | 为了发展团队精神,文化衫与聚会是有益的,但不如对个人的尊重。如果每个人尊重其他的每个人,就没有人会让其他人失望。团队精神产生于人们为团队做出牺牲,优先思考团队的利益而非自己利益的时候。作为一个领导者,在这个方面,没有付出就没有收获。
6 |
7 | 团队领导力的一个关键是促进团结,这样每个人都会听你的。有时候这意味着允许你的队友犯错。也就是,基于这种团结,如果对项目没有太大的损害,你必须允许你团队的一部分成员用他们自己的方式做事,即使你有很大的信心认为这是一件错事。当这种情况确实发生时,不要同意他们的观点,简单公开地反对之,然后接受这种团结。不要让人觉得你受伤了,或者认为你是被迫的,简单地陈述你不同意,但认为团队的团结是更加重要的。这经常会导致他们反悔。如果他们真的反悔了,不要坚持他们一开始的计划。
8 |
9 | 如果在你们从所有合适的角度讨论了这个话题后,有个人会反对,简单地告诉他们,你必须做一个决定,并且这就是你的决定。如果有方法去评估你的决定是否是错的,或者它稍后是否是错的,尽可能快速切换,并感激那个对的人。
10 |
11 | 询问你的团队,包括集体与个人这样一个问题:他们认为什么能创造团队精神以及创造一个高效的团队。
12 |
13 | 经常表扬,但不要浪费。尤其是表扬那些反对你且确实值得表扬的人。公开表扬,私下批评。但有这样一种例外:有时候进步或者纠正一个错误但却没有注意到错误的根源,是不能被表扬的,这种进步应该私下表扬。
14 |
15 | Next [如何划分问题](04-How to Divide Problems Up.md)
16 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/04-How to Divide Problems Up.md:
--------------------------------------------------------------------------------
1 | # 如何划分问题
2 | [//]: # (Version:1.0.0)
3 | 接手一个软件工程并把它分为可以由个人实现的任务是很有趣的。这事应该及早进行。有时候经理可能会认为不考虑个人的项目能够起作用。这是不可能的,因为每个人的生产力是如此广泛地不同。对某个组件有特殊知识的人也经常改变,并且可以对工作效果有一个数量级的影响。
4 |
5 | 正如一个作曲家对其演奏乐器的音色的考虑,或者运动队教练对每个运动员的体能的考虑那样,有经验的团队领导,通常不能够把工程依据团队成员需要承担的角色那样划分成一个个的任务。这是好的团队不容易解散的一个原因。
6 |
7 | 因此有这样一种危险:人们在锻炼自己的能力时会感到无聊,并且不会提高他们的弱项或者学习新技能的能力。然而,如果不被过度使用的话,精通是一个非常有用的生产工具。
8 |
9 | Next [如何处理无聊的任务](05-How to Handle Boring Tasks.md)
10 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/05-How to Handle Boring Tasks.md:
--------------------------------------------------------------------------------
1 | # 如何处理无聊的任务
2 | [//]: # (Version:1.0.0)
3 | 有时候避免对公司或工程的成功至关重要却很无聊的任务是不可能的。这些任务可能真的会降低那些必须执行它们的人的斗志。最好的处理方法是使用或者发扬 Larry Wall 的程序员懒惰美德。试着找一些方法让计算机去做这个任务,或者帮助你的队友去做这个。用一个程序花一个星期去完成要手动去用一个星期完成的任务能让你懂得更多,并且有时候这是可重用的。
4 |
5 | 如果所有其他的途径都不能工作,为那些必须做这个无聊任务的人道歉,但无论什么情况,不要让他们去单独完成它。至少安排一个两人团队去做这个事情,并增强健康的团队协作来完成这个任务。
6 |
7 | Next [如何为工程获取支持](06-How to Gather Support for a Project.md)
8 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/06-How to Gather Support for a Project.md:
--------------------------------------------------------------------------------
1 | # 如何为工程获取支持
2 | [//]: # (Version:1.0.0)
3 | 要给工程获取支持,需要创建并交流一个能够证明这个组织整体的真正价值的愿景。试着让其他人分享他们对你所创造的愿景的观点。这给他们一个理由去支持你并给予你他们的观点所带来的价值。独立地为你的工程补充关键的支持者。不论在什么可能的地方,展示,但不告诉。如果可能的话,构建一个原型或者一个模型来证明你的主意。一个原型总是有力的,但在软件中,它比任何书面的描述都要高级得多。
4 |
5 | Next [如何发展一个系统](07-How to Grow a System.md)
6 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/07-How to Grow a System.md:
--------------------------------------------------------------------------------
1 | # 如何发展一个系统
2 | [//]: # (Version:1.0.0)
3 | 树的种子包含了成长的思想,但不完全实现成长体的形式与力量。胚胎会成长。它会变大。它看起来更像成长体,并越来越有用。最终它孕育果实。最后,它死亡并且它的躯体喂养了其他的有机体。
4 |
5 | 对待软件我们也应当有这样的荣耀。一架桥不是这样的,永远不会有一架婴儿桥,但只是有一座未完成的桥。桥比软件要简单得多。
6 |
7 | 认识到软件的成长是有益的,因为这允许我们在有一个完美的思维图景前取得有用的进步。我们可以从用户那里获得反馈,并用之纠正这种成长。修剪掉疲软的四肢才能健康。
8 |
9 | 程序员必须设计一个完成的可分发可使用的系统。但高级程序员需要做的更多。你必须设计一个终止于完结系统的成长路线。你的工作是,得到一个想法的萌芽,然后把它尽可能顺利地变成一个有用的人工制品。
10 |
11 | 因此,你必须模拟最终的结果,用一种工程团队可以为之雀跃的方式去交流。但你也必须和他们交流一条非跳跃式的路径,从他们所知到他们想要成为的地方去。在整个过程中,这棵树必须活着,它不能在什么时候死去,然后又复活过来。
12 |
13 | 这条路径会是螺旋发展的。里程碑之间永远不会太远,这对于在路上取得进步是有用的。在极端的商业环境里,如果里程碑可以实现并尽早赚钱是最好的。即使他们离良好设计的端点还有很远。程序员的一个工作就是通过理智的选择用里程碑表示的成长路径来平衡即时的报酬与将来的报酬。
14 |
15 | 高级程序员对软件,团队,个人的成长有集体责任。
16 |
17 | 一个读者,Rob Hafernik,在这一节中写下了这样的评论:
18 |
19 | > 我认为你过低强调了这里的重要性。不仅是系统,还有算法,用户界面,数据模型,等等。因为你工作在一个庞大的系统中,必须有即时目标相关的可测量的进步,所以这些也是*至关重要的*。没有什么比抵达终点却发现一切都不能工作更加恐怖(看看最近的投票新闻系统的崩溃吧)。我甚至想进一步把这当做自然的法则:没有庞大,复杂的系统可以由碎片实现,这只能由一个简单的系统循序渐进成长为一个复杂的系统。
20 |
21 | 对此,我们只能回答,*要有光*!
22 |
23 | Next [如何有效地沟通](08-How to Communicate Well.md)
24 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/08-How to Communicate Well.md:
--------------------------------------------------------------------------------
1 | # 如何有效地沟通
2 | [//]: # (Version:1.0.0)
3 | 为了良好地沟通,你必须认识到它的困难。它本身就是一种技能。与你交流的人本身是有瑕疵的,这一事实使得沟通变得更加困难。他们不会努力去理解你。他们不善言辞。他们经常过度工作或者无聊,至少,有时候只关注他们自己的工作而非你要发表的长篇大论。上课,练习写作,公共演讲,聆听,这些东西的一个好处是,如果你擅长它们,你可以更容易看到问题所在以及解决方法。
4 |
5 | 程序员是一种依赖于与团队交流而生存的社会动物。高级程序员是一种依赖于与团队外的人交流而满意的社会动物。
6 |
7 | 程序员从混沌中带来秩序,一种实现这一目标的有趣方法是从外部的一个提议开始。这能用*稻草人*或*白纸*模式或者口头的方式来完成。这种领导对于让团队置身于辩论中有极大的好处。这也把你暴露到批评,或者拒绝与否定中。高级程序员必须准备好接受这些,因为他有特殊的能力,也因此有特殊的责任。非程序员出身的企业家需要程序员在某些方面提供领导。程序员是思想与现实之间的一部分桥梁。
8 |
9 | 我没有很好地掌握沟通的技巧,但我正在尝试的是一种四叉路径:在我有了一些有序的主意并且充分准备好后,我试着口头表达,交给人们一张白纸(可能是真实的纸,也可能是电子的)来给他们展示一个 demo,然后耐心地重复这个过程。很多次我想过,我们在这种困难的沟通里还是不够耐心。如果你的想法没有马上被接受,你不应该丧气。如果你在准备中投入了精力,没有人会因此看低你。
10 |
11 | Next [如何告诉人们他们不想听的东西](09-How to Tell People Things They Don't Want to Hear.md)
12 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/09-How to Tell People Things They Don't Want to Hear.md:
--------------------------------------------------------------------------------
1 | # 如何告诉人们他们不想听的东西
2 | [//]: # (Version:1.0.0)
3 | 你会经常需要告诉人们一些让他们不舒服的事情。记住,你必须为某种原因才这样做。即使没有什么可以用来解决这个问题,你也该尽早告诉他们,这样他们才能充分警觉。
4 |
5 | 向别人指出一个问题的最好方法是同时提供一个解决方案。其次的方法是呼吁他们寻求帮助。如果你有不被信任的危险,你应该为你的主张寻求支持。
6 |
7 | 一种你必须说的最不舒服且普遍的事情是“时间不够”。尽责的程序员讨厌这样说,但必须尽早说。没有什么比 deadline 抵达,不得不推迟进度更加糟糕,即使唯一的行动是通知每个人。更好的做法是,作为一个团队整体来做这件事,如果物理上做不到,至少是精神上这样做。你会想要得到你的团队对你的观点以及你为之所做的事情的支持,团队必须与你共同面对这样的后果。
8 |
9 | Next [如何处理管理神话](10-How to Deal with Managerial Myths.md)
10 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/10-How to Deal with Managerial Myths.md:
--------------------------------------------------------------------------------
1 | # 如何处理管理神话
2 | [//]: # (Version:1.0.0)
3 | *神话*这个词有时候意味着虚构。但这有着更深层的内涵。它也意味着一些解释宇宙以及和人类和宇宙之间的关系的宗教故事。管理者倾向于忘记他们作为一个程序员时学到的东西,并且相信某种传说。试着让他们相信这种传说是错的,正如让一个虔诚的宗教信徒从他们的信仰中醒悟过来一样粗鲁而失败。因此,你应该认可这些信仰:
4 |
5 | - 文档越多越好。(他们需要文档,但他们不会想要你在这些东西上花时间。)
6 | - 程序员是平等的。(程序员可以按重要程度分类。)
7 | - 分配更多资源给迟来的项目可以让它加速。(与新人的交流的代价大多数时候很繁重并且无用。)
8 | - 程序员的效率可以用一些简单的标准尺度来度量,比如代码行数(如果简洁才是力量,那么代码行数是坏的,而非好的。)
9 |
10 | 如果有机会,你可以试着解释这些东西,但如果你没有成功,不要觉得悲伤,不要好斗地反对这些神话以致损害了你的声望。每个这样的神话增强了管理者关于他们有一些对正在进行的事情的实际控制的想法。真相是,如果管理者是好的,他们会帮助你,如果他们是坏的,他们会妨碍你。
11 |
12 | Next [如何处理组织混乱](11-How to Deal with Organizational Chaos.md)
13 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Serving-Your-Team/11-How to Deal with Organizational Chaos.md:
--------------------------------------------------------------------------------
1 | # 如何处理组织混乱
2 | [//]: # (Version:1.0.0)
3 | 经常会有短暂的组织混乱,比如解雇,收购,IPO,新雇佣,等等。对每个人来说这都是令人不安的,但可能对于那些将自尊建立在能力而非位置上的程序员来讲,这种不安不会那么严重。组织混乱对程序员来讲是锻炼他们的魔力的好机会。因为这是一个集体秘密,在最后我会有所保留。如果你不是一个程序员,就不要再读下去了。
4 |
5 | > 工程师有能力去创造与维持。
6 |
7 | 非工程师可以安排人们,但,在典型的软件公司,如果没有程序员的话,他们不能创造与维持任何东西,正如工程师通常不能有效地销售产品或者管理商业。这种力量对于大多数与临时组织混乱相关的问题是一种抵抗。如果你有这种力量,你应当完全忽视这种混乱并当做什么都没发生那样坚持下去。你可能,当然,被解雇,但如果这发生了,你可能因为这种力量得到新的工作。更普遍的,一些紧张的没有这种魔力的人会进入你的空间并告诉你做一些蠢事。如果你真的确信这是一件蠢事,最好的做法是微笑,点头,直到他们走开,然后继续做你认为对公司最好的事情。
8 |
9 | 如果你是一个领导者,告诉你的员工做一样的事情,告诉他们忽视其他任何人告诉他们的东西。这种行为的过程对你个人是最好的,对你的公司或工程也是最好的。
10 |
11 | Next [词汇表](../../4-Glossary.md)
12 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Technical-Judgment/01-How to Tell the Hard From the Impossible.md:
--------------------------------------------------------------------------------
1 | # 如何从不可能中找到困难的部分
2 | [//]: # (Version:1.0.0)
3 | 解决困难,识别不可能是我们的工作。大多数职业程序员认为,如果有些问题不能从一个简单系统发展而来,或者不能评估,那它就是不可能实现的。然而,根据这个定义,研究本身就是不可能的。大量的工作是困难的,但不是必然不可能的。
4 |
5 | 这种区别是滑稽的,因为你可能经常被要求做一些事实上不可能的事情,不论是从科学观点还是从软件工程观点。然后你的工作就变成了帮助老板找到一个合理的,仅仅是困难而非不可能的解决方案,去满足他们大部分的需要。当一个解决方案可以被自信地规划且风险可以预料时,它只是困难而已。
6 |
7 | 砍掉模糊的需求是不可能的,比如“构建一个系统为任何人计算最受欢迎的发型和颜色”。如果需求可以做得更加细致,它就经常会变成仅仅是困难,比如“构建一个系统去计算某个人的发型和颜色,允许他们预览与做出改变,让顾客在原始风格的基础上满意度变大,这样我们就可以赚很多钱”。如果没有关于成功的清晰定义,你就不会成功。
8 |
9 | Next [如何使用嵌入型语言](02-How to Utilize Embedded Languages.md)
10 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Technical-Judgment/02-How to Utilize Embedded Languages.md:
--------------------------------------------------------------------------------
1 | # 如何使用嵌入型语言
2 | [//]: # (Version:1.0.0)
3 | 把一种编程语言嵌入到一个系统对程序员来讲有着几乎与性一样的魔力。这是一种最具有创造力的可以表现的行为。这使得系统惊人地强大。这也允许你锻炼大多数创造性和有生命力的能力,把系统变成你的朋友。
4 |
5 | 世界上最好的文本编辑器都有嵌入性语言。这可以被用于预计的观众可以掌握的语言的范围,语言的使用可以变为可选的,正如文本编辑器里那样,这样在一开始可以使用它,而没有其他人必须使用它。
6 |
7 | 我和许多其他的程序员曾坠入创造特殊目的的嵌入型语言的困境里。我曾经历过两次。已经存在了许多为嵌入型语言设计的语言,在创造一个新的语言前,你应该三思。
8 |
9 | 使用嵌入型语言前,真实的需要自问的问题是:这种工作与我的观众的文化是一致还是相悖?如果你的目标观众都是非程序员,这会有帮助吗?如果你的目标观众都是非程序员,他们会更喜欢 API 吗?他会是什么语言?程序员不会想要学习一种新的使用范围很窄的语言,但如果这与他们的文化混在一起了,他们将不会花太多时间去学习它。创造一种新的语言是一种快乐。但我们不应该让这遮蔽了观察用户的双眼。除非你有一些真正原始的需求与想法,为什么不使用一种已存在的语言呢?这样你就可以利用好用户对它已有的这种熟悉了。
10 |
11 | Next [选择语言](03-Choosing Languages.md)
12 |
--------------------------------------------------------------------------------
/zh/3-Advanced/Technical-Judgment/03-Choosing Languages.md:
--------------------------------------------------------------------------------
1 | # 选择语言
2 | [//]: # (Version:1.0.0)
3 | 喜欢程序员这份工作的独立的程序员可以为任务选择最好的语言。大多数职业程序员控制不了他们将要使用的语言。通常,这个话题会由执行行政决议而非技术决议的 boss 说出,他们缺少勇气去提升新型工具,即使他们知道,大多数时候使用最新的知识,最少被接受的工具是最好的。另一些情况下,这种团体中真实的好处,以及拓展一个更大的社区的好处,排除了个人的选择。通常管理者由能够雇用在给定的语言有些经验的程序员的需求所驱动。毫无疑问他们服务于他们所追求的,以成为工程或公司的最佳乐趣,而且他们会以此被尊敬。并且,我个人相信,这种最浪费而且错误的常见行为,你很有可能遇到。
4 |
5 | 但是,当然,事物永远不会是一维的。即使一种核心语言妥协了,超出了你的控制范围,通常的情况是,工具和其他程序可以且应该由另一种不同的语言来编写。如果一种语言需要作为嵌入型的(你通常都要考虑它!),语言的选择很大程度上会依赖于使用者的文化。一个人应该利用好这个问题来为你的公司或工程服务,为任务使用最好的语言,这样可以让工作变得有趣。
6 |
7 | 一门编程语言,如果学习它比学习自然语言还要难,那它真的应该被称为符号。对初学者和一些门外汉来说“学习一门新语言”像是一个令人生畏的任务,但在你掌握了三种语言后,这只是一个熟悉可用的库的简单问题。一个程序员趋向于思考一个由三四门语言组成的一个大杂烩系统,但我认为这样一个系统在以下几方面要比单一语言系统在很多情况下要强大:
8 |
9 | - 不同符号编写的部分间,必要的松耦合存在(虽然可能没有干净的接口)
10 | - 通过独立重写每个组件,你可以轻松地写出一个新的语言平台
11 | - 只有一门语言可能对一个庞大的系统不太适合 - 你的多个模块由多种语言组成,能让你为任务找到正确的工具。
12 |
13 | 这些效应可能有些只是心理上的,但心理上的东西也很重要。最后要说的是,语言暴政的代价超过了它能提供的所有好处。
14 |
15 | Next [明智地妥协 - 如何与时间压力斗争](../Compromising-Wisely/01-How to Fight Schedule Pressure.md)
16 |
--------------------------------------------------------------------------------
/zh/4-Glossary.md:
--------------------------------------------------------------------------------
1 | # 词汇表
2 | [//]: # (Version:1.0.0)
3 | 这是这篇文章里用到的一些短语的词汇表。它们不一定是人们熟悉的标准含义,Eric S. Raymond 曾经编译过一份信息量巨大的词汇表 [HackerDict],如果你能理解其中的一些片段,阅读这个词汇表将是惊喜而愉悦的。
4 |
5 | **unk-unk**
6 | : unknown-unknown 的简写。指的是一些暂时不能被概念化的问题,它们会偷走项目的时间并且阻塞时间表。
7 |
8 | **boss**
9 | : 给你任务的人或实体,有些地方可能泛指公众。
10 |
11 | **printlining**
12 | : 在严格的临时机制上,在程序中插入一些语句,为调试输出一些程序执行过程中的信息。
13 |
14 | **logging**
15 | : 实践中编写程序的一种方式,使得它能够产生可设置的输出以描述它的执行过程。
16 |
17 | **分治**
18 | : 一种自上而下设计的技术,更重要的是,一种调试的技术,划分问题或谜题为小的问题或谜题。
19 |
20 | **vapour**
21 | : 幻觉,而且通常是对还不能出售的软件虚假的承诺,往往不会物质化为任何固定的东西。
22 |
23 | **boss**
24 | : 给你设定任务的人,有些时候,也指用户。
25 |
26 | **tribe**
27 | : 与你一同为相同目标奋斗的人们。
28 |
29 | **低垂的水果**
30 | : 轻易能达到的巨大提升。
31 |
32 | **主办人**
33 | :项目的发起人
34 |
35 | **垃圾**
36 | : 不再需要被放在内存中的对象
37 |
38 | **商业**
39 | : 一群为财富聚合在一起的人
40 |
41 | **公司**
42 | : 一群为财富聚合在一起的人
43 |
44 | **集体**
45 | : 一群与你共享文化亲缘与忠诚的人。
46 |
47 | **滚动目盲**
48 | : 一种由于有效信息被太多无效信息掩盖导致你不能发现它的效应
49 |
50 | **挂钟**
51 | : 由挂钟测量的现实中真实的时间,与 CPU 时间相对。
52 |
53 | **瓶颈**
54 | : 系统性能最重要的限制/一个可以限制性能的界限。
55 |
56 | **主线**
57 | : 一个独特的信息块,所有缓存副本都从它继承而来,作为这份数据的官方版本。
58 |
59 | **分配的堆**
60 | : 一份内存在这样的情况下可以被称为分配了堆:当释放它的机制已经完成时。
61 |
62 | **垃圾**
63 | : 已经被分配但不再有有效意义的内存。
64 |
65 | **GC**
66 | : 一个回收垃圾的系统。
67 |
68 | **内存泄露**
69 | : 无意持有的一系列对象的引用,它们避免了垃圾回收(或者垃圾回收器或内存管理系统中的 bug!)导致程序随时间逐渐增加了它的内存占用。
70 |
71 | **极限编程**
72 | : 一种强调与客户交流以及自动化测试的编程风格。
73 |
74 | **碰壁**
75 | : 因为耗尽了某种特定的资源导致性能突然大幅度地降级
76 |
77 | **投机编程**
78 | : 在知道一个东西有用前就把它做出来。
79 |
80 | **信息隐藏(封装)**
81 | : 通过使用尽可能少暴露信息的接口来让事情保持独立解耦的一种设计原则。
82 |
83 | **面向对象编程**
84 | : 一种强调在对象内部管理状态的编程风格。
85 |
86 | **交流语言**
87 | : 一种优先为标准化而非执行设计的语言。
88 |
89 | **箱子与箭头**
90 | : 一种宽松,非正式的,由箱子和箭头组合而成表达关系的图表制作风格,这与正式的图表方法论,比如 UML,相对。
91 |
92 | **通用语**
93 | : 一种语言是如此受欢迎以至于它成了它的领域中实际上的标准,例如法语一度成为国际外交的手段。
94 |
95 | **buy vs. build**
96 | : 用来形容购买软件还是自己编写软件这样的选择。
97 |
98 | **合并工作**
99 | : 需要很少创造力并产生很少风险的工作,合并工作可以被很容易地评估。
100 |
101 | **编程符号**
102 | : 编程语言的同义词,强调编程语言的数学本质以及它们与自然语言相比的简单之处。
103 |
104 | **稻草人**
105 | : 一种用来作为技术讨论起点的文档。稻草人也可以引申出火柴人,罐头人,木头人,铁人,等等。
106 |
107 | **白纸**
108 | : 一种信息文档,通常用来解释或将产品或思想卖给观众而非程序员。
109 |
110 | Next [书籍/网站](5-Bibliography.md)
111 |
--------------------------------------------------------------------------------
/zh/5-Bibliography.md:
--------------------------------------------------------------------------------
1 | # 附录 A - 书目/网站目录
2 | [//]: # (Version:1.0.0)
3 | ## 书目
4 |
5 | [Rules00] Guy Kawasaki, Michelle Moreno, and Gary Kawasaki. 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating and Marketing New Products and Services.
6 |
7 | [RDev96] Steve McConnell. 1996. Microsoft Press. Redmond, Wash. Rapid Development: Taming Wild Software Schedules.
8 |
9 | [CodeC93] Steve McConnell. 1993. Microsoft Press. Redmond, Wash. Code Complete.
10 |
11 | [XP99] Kent Beck. 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change.
12 |
13 | [PlanXP00] Kent Beck and Martin Fowler. 2000. 0201710919. Addison-Wesley. Planning Extreme Programming.
14 |
15 | [Prag99] Andrew Hunt, David Thomas, and Ward Cunningham. 1999. 020161622X. Addison-Wesley. The Pragmatic Programmer: From Journeyman to Master.
16 |
17 | [Stronger] Friedrich Nietzsche. 1889. Twilight of the Idols, "Maxims and Arrows", section 8..
18 |
19 | ## 网站
20 |
21 | [PGSite] Paul Graham. 2002. Articles on his website: [http://www.paulgraham.com/articles.html](http://www.paulgraham.com/articles.html). All of them, but especially "Beating the Averages".
22 |
23 | [Hacker] Eric S. Raymond. 2003. How to Become a Hacker. [http://www.catb.org/~esr/faqs/hacker-howto.html](http://www.catb.org/~esr/faqs/hacker-howto.html).
24 |
25 | [HackDict] Eric S. Raymond. 2003. The New Hacker Dictionary. [http://catb.org/esr/jargon/jargon.html](http://catb.org/esr/jargon/jargon.html).
26 |
27 | [ExpCS] Edsger W. Dijkstra. 1986. How Experimental is Computing Science?. [http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF](http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.PDF).
28 |
29 | [Knife] Edsger W. Dijkstra. 1984. On a Cultural Gap. [http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF](http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.PDF).
30 |
31 | Next [History](6-History.md)
32 |
--------------------------------------------------------------------------------
/zh/6-History.md:
--------------------------------------------------------------------------------
1 | # 附录 B - 历史
2 | [//]: # (Version:1.0.0)
3 | ## 迁移到 Github
4 |
5 | 这篇文章已经在 github 上作为一个仓库创建了,这样它可以很容易地被分享、更新、提高。它是从这里复制过来的。[http://samizdat.mines.edu/howto/HowToBeAProgrammer.htm](http://samizdat.mines.edu/howto/HowToBeAProgrammer.htm) by [Braydie Grove](https://github.com/braydie)。 2016年1月迁移到 github。
6 |
7 | ## 希望反馈或扩展。
8 |
9 | 请将你对这篇文章的任何评论发给我,我会考虑所有的建议,大部分都会对这篇文章有所帮助。
10 |
11 | 这篇文章处于 GNU 免费文档授权下。这个授权不是专门为文章而设计的。文章通常有连贯的令人信服的服务于一个中心的论据。我希望这篇文章尽量短而易读。
12 |
13 | 我希望它是说明性的,尽管不是一本教科书,它被划分成许多小节,这样新的章节可以被自由地添加进去。有了这样的倾向,你可以用你觉得合适的方式来扩展这篇文章,且服从这个授权的规定。
14 |
15 | 可能认为这个文档值得扩展有点自大,但希望生生不息。我会很高兴看到你用以下的方式扩展它:
16 |
17 | 对每个章节增加一些阅读理解,
18 |
19 | 增加更多章节,
20 |
21 | 翻译为其他语言,即使只是一小部分一小部分地翻译,或者
22 |
23 | 在文字间留下批评或评论,
24 |
25 | 用不同形式构建的能力:比如 palm 格式或更好的 HTML 格式。
26 |
27 | 如果你向我传达了你的工作,我会考虑把它包括在我的子版本里,遵循这个许可证的规定。你也可以在我的了解之外制作你自己的版本,正如这个协议所说的。
28 |
29 | Thank you.
30 |
31 | Robert L. Read
32 |
33 | ## 原始版本
34 |
35 | 这个文档的原始版本由 Robert L. Read 在2000年制作,并且以电子形式在2002年首发于 Samizdat Press(http://Samizdat.mines.edu) 。被 Hire.com 的程序员所使用。
36 |
37 | 在这篇文章2003年被 Slashdot 刊载后,大概有75个人给我发过邮件提过建议与错误修改。我感激他们中的所有人。可能有很多重复,但这些人不是提出来最主要的建议就是第一个找到了我的 bug:Morgan McGuire, David Mason, Tom Moertel, Ninja Programmer (145252) at Slashdot, Ben Vierck, Rob Hafernik, Mark Howe, Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Ioffe, Andrew Wu, David Jeschke, 以及 Tom Corcoran。
38 |
39 | 最后,我想感谢 Christina Vallery,他的编辑和校对巨大地提高了第二份草稿,还有 Wayne Allen,他鼓励我开始了这件事情。
40 |
41 | ## 原始作者的简介
42 |
43 | Robert L. Read 生活在德克萨斯,奥斯汀, 有一个妻子和两个孩子,他现在是 Hire.com 的首席工程师。他在那里工作了四年。在这之前他建立了 4R 科技,为造纸工业生产基于扫描的图像分析质量控制工具。
44 |
45 | Rob 在1995年在德州大学获得数据库理论方向的计算机博士学位。1987年他在 Rice 大学获得计算机科学学士学位,在16岁时,他就是一个带薪程序员了。
46 |
47 | Next [License](LICENSE.md)
48 |
--------------------------------------------------------------------------------
/zh/7-Contributions.md:
--------------------------------------------------------------------------------
1 | # Contributions
2 | [//]: # (Version:1.0.0)
3 | 这个仓库目标是成为一个社区驱动的工程,你的加入会极大地促进这个向导的质量。
4 |
5 | ## 我可以做什么贡献?
6 |
7 | 有很多方式为 "How to be a Programmer" 做贡献
8 |
9 | - 新章节的思想
10 | - 提升已有的章节
11 | - 识别排版错误或其他章节中的问题
12 | - 为章节提供额外的资源链接
13 | - 一般的用于提升工程的建议
14 | - 为这份指导提供翻译
15 |
16 | ## 翻译
17 |
18 | 当前,这份指导已经从英文翻译为以下语言:
19 |
20 | - 中文 by [ahangchen](https://github.com/ahangchen)
21 |
22 | **如果你第一个提供了其他语言的翻译,你就是这个工程的一个明确的贡献者,请帮忙维护和 review 对翻译版本的修改。**
23 |
24 |
25 | ## 贡献者
26 |
27 | Github 在这里会维护一个所有贡献者的列表 [contributors](https://github.com/braydie/HowToBeAProgrammer/graphs/contributors)
28 |
29 | ## 校正与迁移到GitHub
30 |
31 | [Braydie Grove](https://www.github.com/braydie) 已经同意作为主编。
32 |
33 | Braydie 把原始的文档转成了 Markdown 的形式并创建了这个仓库。
34 |
--------------------------------------------------------------------------------
/zh/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | ## Creative Commons Attribution Share-Alike
3 | [//]: # (Version:1.0.0)
4 | "How To Be A Programmer: Community Version" by Robert L. Read with Community is licensed under Creative Commons Attribution Share-Alike Internal v 4.0.
5 |
6 | At present this work will be edited by Braydie Grove and Robert L. Read.
7 |
8 | We will make reasonable attempts to maintain proper attributions of contributions in the section entittle "Contributions". If you make a pull-request with a significant contribution, please add a very brief description of your contribution to that section.
9 |
10 |
11 |
12 | 
How To Be A Programmer: Community Version by Robert L. Read with Community is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
13 |
--------------------------------------------------------------------------------