About the book "
Programmer pragmatist. The path from the apprentice to the master "Andrew Hunt and David Thomas know, probably, all who are engaged in programming, and many - mostly from references in collections and quotes in more modern articles. Given that this collection of practical tips for developers will soon celebrate the twentieth anniversary, the fact that it is still cited as a source of valuable information is a matter of respect. The secret is simple: the authors, although they emphasized the practical applicability of their hints, spoke for the most part about the fundamental principles of building the workflow. Many of the technical points mentioned in the text are really outdated for a long time, but the basic approaches to the development, testing, interaction within the team and with the audience remain relevant.

Below you will find a summary of the first four chapters; they deal with the author's concept of self-education, the fundamentals of a pragmatic approach to programming, and the rules for selecting tools. The book is very convenient for "point" reading: the material is presented in the form of separate paragraphs, hints, provided with cross-references. Examples of specific languages, case studies from the author’s practice, those very references, exercises for fastening and some funny analogies that enliven the text - so I recommend to get acquainted with the original, if any of the theses are interesting for you. Enjoy reading!
Tip 1: Take care of your craft.
It makes no sense to develop programs if you do not care about the quality of work. It is necessary to do this not only in the short term, as applied to specific projects, but also in the long term - forming the right approach and working principles.
')
What distinguishes the pragmatic programmer?
- Advanced Perception and Quick Adaptation. Pragmatists have an instinct for useful technologies and methods that they are happy to test in practice. They are able to quickly grasp new information and combine it with existing knowledge.
- Curiosity. Pragmatists ask questions, collect small facts, and are interested in someone else's experience.
- Critical thinking. Pragmatists do not take anything for granted without first reading the facts.
- Realism. Pragmatists are trying to find where the pitfalls are in every problem that we face.
- Versatility. Pragmatists seek to get acquainted with a large number of technologies and operating systems and are working to keep pace with the times.
Tip 2: Think about work
While writing code, you should fully concentrate on what you are doing. Never go into autopilot mode. Think constantly, critically thinking about your work in real time. This is called conscious programming. Its development will take some time and will require effort, but the reward will be the habit of constantly making minor improvements, improving the quality of the code as a whole and reducing the development time.
Chapter 1: Pragmatic Philosophy
Pragmatic programming originates from the philosophy of pragmatic thinking. This chapter presents its main provisions.
Tip 3: Present solutions, not excuses
One of the cornerstones of a pragmatic philosophy is the idea of taking responsibility for yourself and for your actions. A pragmatic programmer assumes that his career and the results of his work depend primarily on him, and he is not afraid to admit ignorance or error.
Taking responsibility for the outcome implies a willingness to report. If you make a mistake (and we all make them), admit it honestly and try to suggest options for correction. Do not shift the blame on colleagues, partners, tools, or invent excuses - it is a waste of time. The same applies to situations where you encounter demands that you cannot satisfy: do not simply say: “This is impossible”, but explain what is needed to save the situation (additional resources, reorganization, etc.).
Tip 4: Do not leave broken windows.
Entropy is a term from physics, denoting the level of "disorder" in a system. Entropy in the universe tends to a maximum, and the same pattern is observed in the design. Increasing the degree of confusion in programs in professional jargon is called program corruption. There are many factors contributing to program corruption, but the most important one is the culture of working on a project.
According to the theory of broken windows, sloppy decisions and problem areas tend to multiply. Do not leave the “broken windows” (bad constructions, errors, poor-quality code) without attention. If there is no time for proper repair, at least comment out the erroneous fragment or display the message “Under development”, or use dummy data. It is necessary to take even the slightest action to prevent further destruction, and to show that you are in control of the situation. Carelessness speeds up spoilage faster than any other factor.
Tip 5: Be a catalyst for change.
If you see what needs to be done, do not expect initiative from others. Make a plan, work out the details - people will be more willing to support you if they see that work has already begun.
Tip 6: Stay tuned
Keep your eyes on the big picture. Constantly watch what happens around you, not just what you personally do. Most of the disasters in the code begin with unobtrusive things that are piling up until one day the project goes into action. Step by step, the system deviates from the requirements, the code is cluttered with “patches” until nothing remains of the original. Often it is the accumulated trivia that leads to the destruction of morals and commands. But if you seize this process in the early stages and take immediate action (see the previous paragraph), you can get rid of a little blood.
Tip 7: Make quality one of the requirements
Quality must be a contractual clause in a contract that you enter into with users. Of course, ideally, it should be maximum, but often you will find yourself in situations where you have to compromise due to tight deadlines or lack of resources. And here it is useful to train yourself to create acceptable programs. “Acceptable” does not mean “made a mistake”: you simply give users the right to vote in determining the quality threshold that can be considered valid. Surprisingly, many would prefer to use the program with some flaws today, instead of waiting for a year to release the multimedia version.
In addition, sometimes programs get better due to a shorter incubation period. In the development, there is a problem of "rounding" - external constraints help to stop in the pursuit of perfection in time.
Tip 8: Invest regularly in your knowledge portfolio.
A portfolio of knowledge means everything that a programmer knows about the development in his field, as well as his experience. Knowledge portfolio management is very similar to financial portfolio management:
The general principles are:
- Invest on a regular basis . Even if the amount of investment is small, this habit is useful in itself.
- Invest in various areas . The more areas you capture, the more valuable you are. At a minimum, you must know the specific technologies you are working with at the moment, from and to. But don't stop at that. The demand for technology and its applicability is constantly changing. The more tools you have in your arsenal, the easier it will be to adapt.
- Weigh the risks . Technologies exist in a certain range - from risky and potentially high-profit to low-risk and low-profit. To invest everything in risky options, the course of which can suddenly collapse, is not the best idea, but also excessive care, which does not allow to take advantage of advantageous opportunities - as well. Better keep the middle line.
- Buy cheaper, sell more expensive . Mastering advanced technology before it becomes popular is a difficult task, but worth it: early followers often make a dizzying career.
- Regularly review and rebalance . Programming is a very dynamic industry. Be prepared to periodically critically review your assets: discard obsolete options, restore those that have risen in price, and replenish empty niches.
The learning process will expand your thinking, opening for you new opportunities and new paths in creativity. If you have learned something new, try to apply this knowledge to the project you are currently working on as far as the technologies used allow.
Tip 9: Critically analyze what you read and hear.
You need to make sure that the knowledge in your portfolio is accurate, that it is not distorted by those who benefit from it, and that its value is not inflated by hyip. Be wary of fanatics insisting that their dogma provides the only correct answer - it is quite possible that it is not applicable in your project.
Tip 10: It is important what to say and how to talk.
Most of the programmer's day is spent in communication - with the team, management, users, future generations of developers through the documentation and comments in the code. Therefore, it is necessary to master his art. The more effective this communication, the higher your ability to translate ideas into reality.
Principles of effective communication:
- Know what you want to say : Plan what you will say in advance, outline a plan and a couple of strategies for how best to communicate the idea. This works both for drafting documents and for important negotiations.
- Know your audience : you communicate only if you transmit information. To do this, you need to be aware of the needs, interests and abilities of the audience. Present the information so that it is understandable and interesting to the listener.
- Choose the right moment : An important point to understand the audience is to understand its immediate priorities. What you say should be not only relevant in content, but also timely. If necessary, ask directly: “Is it convenient to talk now about ...?”
- Choose the style you need : Determine the style of presentation of the material in accordance with the requirements of the audience: someone prefers bare facts, someone prefers details, examples and extensive introductions. Again, if in doubt, specify.
- Meet on clothes : Be able to properly "serve" your ideas. In the final document, everything should be verified: spelling, layout, text styles, typography.
- Reach your audience : If possible, involve future readers in the process of creating documents. Use their ideas. So you will get the best result and strengthen the working relationship.
- Learn to listen : Join people in conversation by asking questions or making them summarize what you have said. Turn the meeting into a dialogue, and you better convey what you want to say, and perhaps at the same time get something for yourself.
- Do not interrupt the conversation: Always respond to requests and messages with at least a promise to return to this issue later. If you keep people informed, they feel that they have not been forgotten, and it is much easier to forgive random mistakes.
Chapter 2: A Pragmatic Approach
There are a number of hints and tricks applicable at all levels of program development — ideas that can be considered axioms, processes that are almost universal. This chapter reviews these ideas and processes.
Tip 11: Do not repeat
Each piece of knowledge must have a unique, unambiguous, reliable representation in the system. An alternative is to present the same subject in several places. This is an inconvenience: if something is edited in one place, you must immediately make changes to all the others, otherwise the program will collapse under the weight of contradictions. Sooner or later you will forget something, it is a matter of time.
Most duplication cases fall into one of the following categories:
- Imposed duplication . Developers feel that they have no choice - duplication is necessary for some external reasons: standards of documentation, a combination of several platforms with different environments, languages and libraries, the specifics of the language itself. In some cases, it remains only to accept, but in others you can still find workarounds with the help of filters, active code generators, metadata, and the right approach to commenting.
- Inadvertent duplication . Developers do not realize that they duplicate information. This usually occurs as a result of errors or inconsistencies at the deep level (for example, the same attribute is written in several objects), and the elimination requires reorganization. In some such cases, the principle can be violated for the sake of performance, but only within the class.
- Impatient duplication . Developers make duplication, because it seems to them that this is easier. This is usually done by copying pieces of code. It all comes down to self-discipline - do not be lazy to spend a few extra seconds to avoid a headache in the future.
- Collective duplication . The piece of information is duplicated by several members of the same development team during the course of the work. The most difficult case in terms of both detection and resolution. At a high level, the problem is solved through a clear project decision, a strong technical manager and a clear division of responsibilities. On the modular - due to active communication between developers: create groups for communication, create a publicly accessible place in the catalog for storing service routines and scripts, encourage study and discussion of someone else's code.
Tip 12: Make it easy to reuse the program.
Try to create an environment where it is easier to find and reuse existing material than to create it yourself from scratch. This helps reduce the risk of duplication. Just keep in mind: if reuse is fraught with difficulties, people will not do it.
Tip 13: Eliminate interactions between objects that are not related to each other.
This rule is also called the principle of orthogonality. Two or more objects are orthogonal if the changes made to one of them do not affect the others. This scheme has two big benefits: increased productivity and reduced risk.
When changes in the system are localized, the development and testing time is reduced. Once a small, self-contained component is designed, implemented and tested, you can simply forget about it, instead of constantly making changes as new fragments are added to the code.
The orthogonal approach also contributes to the reuse of components. The less connectedness in systems, the easier it is to reconfigure or reengineer.
The risk reduction is due to the fact that the erroneous fragments are isolated and do not affect the entire system; accordingly, it is also easier to fix or replace them. As a result, the system becomes more stable - problem areas remain areas. It also helps that testing at the module level is usually done more thoroughly.
The principle of orthogonality should be respected not at the level of individual technologies, but cover all processes: from design to selection of tools, from testing to product management. It minimizes duplication and makes the system more flexible and transparent.
Tip 14: There are no final decisions.
Requirements, users, and hardware change faster than we develop software. Therefore, you should always be prepared for the fact that any decision you make (not only within the code, but also, say, when choosing a tool from a third party, an architectural template, a deployment model), will have to be revised in the future under the influence of external factors. The principle of “minimum duplication”, the principle of disconnection and the use of metadata make the system more reversible.
Tip 15: Use tracer bullets to find the target.
Expanding the metaphor: when creating a new product, the development team often acts blindly, working with unfamiliar methods, languages and libraries. You can predict the final result either by hard forecasting, based on a very detailed analysis of technologies, or by using “tracing” - creating a series of simplified, trial, gradually improved working versions to bring together the system components and check how they work in conjunction.
An alternative to this approach is the isolated development of separate modules, which at the final stage are assembled together and then already tested at the system level - more heavy and less convenient. Among other things, the tracing method gives you a rough version of the product (it can be presented to users to show them the essence of the project, to interest and get feedback); smoother and focal integration of finished new modules into the environment and the ability to immediately identify and easily eliminate errors in the interaction.
Tip 16: Create prototypes to learn from them.
Unlike the test versions described above, prototypes have a narrower focus: they are created to work out several specific characteristics and require significantly less resource. All details unrelated to the problem in question are omitted, even if they are extremely important for the operation of the system as a whole. When working on a prototype, correctness, completeness, reliability and style can be neglected.
For prototyping, it is not necessary to create a full-fledged working application, sometimes it is enough to just lay out schemes on paper or blackboard. If it is still necessary, then it makes sense to choose a very high level language for this purpose — above the level of the language used by the rest of the project (language like Perl, Python or Tel). A high-level scripting language allows you to omit many details (including the indication of data types) and at the same time create a functional, albeit incomplete and slow, fragment of the program.
Tip 17: Write the code with an eye on the scope
Programming languages affect how you think about a problem and user interaction. Each language has its own peculiarities that suggest certain solutions or, on the contrary, prevent them. A Lisp style solution is different from a C-based thinking solution, and vice versa. The reverse is also true - a language reflecting the specifics of the problematic with which you work may, for its part, offer a programming solution.
Listening to the requirements of users, you can understand into which language it will be easiest to translate them at a higher, abstract level. Different types of users (final - the audience for which you are doing the project, and secondary - managers, future generations of developers) may require the generation of their own mini-environments and languages.
Tip 18: Evaluate to avoid surprises.
To give a rough estimate is a skill, and an essential part of this skill is the ability to determine acceptable accuracy based on context. The unit of measurement you choose should also reflect the degree of accuracy (compare: the task will take two weeks and the task will take 75 working hours).
Evaluation is carried out in several stages. First, we delve into the essence of the question asked and evaluate the scale of the subject area; however, often the very formulation of the question suggests an answer. Then a model of the problem is built up - an approximate sequence of stages that will need to be completed in solving it. The model is subjected to decomposition into components, for each of which a significance parameter is set. Calculations are made on the basis of these parameters and approximate values. The last step is carried out after the fact - the forecast is compared with the real state of affairs, with serious deviations, work is being done on the errors.
Tip 19: Specify the project schedule if required by the code.
This may not appeal to management, who usually needs the numbers to be announced before the project starts, and not subject to change. You will have to convey to them that the task schedule will be determined by the team’s performance and circumstances. By formalizing this procedure and refining the schedule during each iteration, you will be able to give management the most accurate estimates of the timing for each stage.
Chapter 3: Travel Toolkit
Tools - a means of enhancing your talent. The better they are and the better you own them, the more you can do. Start with a versatile, hiking toolkit that you will use for all basic operations. This kit will grow as you accumulate experience and face specific requirements.
Tip 20: Save information in plain text format.
The best format for the permanent storage of knowledge is simple text, which allows you to process information both manually and using any available tools. The problem with most binary formats is that the context necessary to understand the data is separate from the data itself. And with plain text that can be read without decryption, you can create a self-documented data stream independent of the program that generated it.
Plain text has two major drawbacks: (1) it may take up more space when stored than a compressed binary format, and (2) from a computational point of view, the interpretation and processing of a plain text file may be slower. Depending on the application, one or both of the above situations may be unacceptable. But even in these cases, it is permissible to save metadata that will describe the source data in plain text format.
Plain text is:
- Ensuring data is not out of date
- Shorter path to goal
- Easier testing
Tip 21: Use the strengths of the command shells.
If you work only with a graphical interface, then you use far from all the possibilities provided by the operating system - you do not automate typical tasks, do not use the available tools at full strength, do not combine different solutions to create specialized macrotools. The advantage of the graphical user interface is that they work on the principle of "what you see, you get." The main disadvantage of the graphical interface can be formulated as follows: “you get only what you see.” The scope of application of such tools is usually limited to the tasks for which it was originally conceived. If you want to go beyond this template (and sooner or later you will want to), you are not on the path with them.
Make a little effort to familiarize yourself with the shell, and you will be surprised how much more productive your work will be. Lower-case commands may not be clear, but they are powerful and short. Summarizing them into script files, you can create sequences of commands to automate frequently performed procedures.
Tip 22: Use one text editor, but to the maximum
Text processing should take a minimum of effort, so it’s better to master a single editor perfectly and use it for all editing tasks: working with program text, documentation, notes, system administration, etc. It’s hard to be an expert right away several software environments, bring work to each to a reflex, given that each of them has its own set of commands and standards. Trying to combine several editors, you risk repeating the situation with the Babylonian pandemonium.
The choice of the editor is almost a religion, so there is no specific recommendation to give here. However, when making a decision, the following parameters should be considered:
- Customizable All properties of the editor should be customized according to your wishes, including fonts, colors, window sizes and hotkeys.
- Extensibility The editor should not become obsolete as soon as a new programming language appears. It must be able to integrate into any compiler environment you are currently using. You should have the option to “teach” it to the nuances of any new programming language or text format.
- Programmability You must have the ability to program the editor for complex multistep operations.
Tip 23: Always use source code control.
Source control systems track any changes that are made to the text and documentation. The best of them can also track changes in the versions of the compiler and operating system. With the help of a source code management system configured properly, you can always return to the previous version of the program.
The source text management system does much more than just undo erroneous actions. A good system allows you to track changes and answers the characteristic questions: “Who made the changes to this line of text? What is the difference between the current version and the version that existed last week? How many lines of program text have been changed in this version?
Which files change the most? Such information is invaluable when tracking errors, auditing, evaluating performance and quality.
How is debugging going?
Tip 24: Resolve the problem, not the accusation.
We turn to the topic of eliminating bugs - a very delicate and highly relevant for teamwork. Here, like nowhere else, the right attitude is important. Soak up the fact that debugging is the same task as everyone else, and approach it from this position. In fact, it does not matter who is to blame for the error - you or someone else. It still remains your problem.
Tip 25: Do not panic
, , , ̆ . — .
, , ̆, – ̆. , , . ; — , .
26: ̆
, , . « », , , , , . , , ̆ ̆ ̆ .
: - , , . , .
27: ̆ – ̆
, , - , . , , , ̆ . , , , «», . — , .
, , , . - , ̆ ̆.
28:
, . ̆ . , ̆ – - .
, .
29: ,
: , , . . , .
. , . , , , , , , .
̆ , . « ». , . , . , .
4:
30:
. , . , ̆ ̆.
31: ̆
̆ ̆ , . , .
̆ ̆ ̆ ̆ : « , , ». , , , . : , , , , , .
, ̆ ̆ . – ̆, , (, , ), – . , , .
32: ̆ ̆
– ̆ , , . : , - .
, ̆ (, - , ̆ ). ̆ – , , , . , ̆, ̆, , . , .
33: - ̆, ̆ , , ̆
̆ , : « , ̆», . ̆ ̆ – . ̆ ++ assert _assert, ̆ . . , , ̆ ̆ , NULL, .
̆ . , ̆. , , , . : , . , , ̆ ̆.
34: ̆
, , , ̆; ̆ - . .
, , , . ; ̆.
̆ – ̆ goto. , ̆ ̆ , , ̆ . : , , ̆.
35: ,
: , , , ̆, ̆ – , , . ̆ : , , . , . : , , .
, :
- Release the resources in the reverse order of the one in which they were distributed. At the same time, the appearance of “orphaned” resources can be avoided if one of them contains links to the other.
- When allocating the same set of resources in different places of the program, it is necessary to carry out this operation in the same order. This reduces the chance of deadlocks.
In programs that use dynamic data structures, there are times when the basic resource allocation scheme is not suitable. In this case, the trick is to establish a semantic invariant for memory allocation.