Saturday, 19 January 2013

The Pragmatic Programmer

In this post I would like to collect the best advices from the book The Pragmatic Programmer.



The book start with some interesting sentences about the role of programmers that is often wrongly perceived.
If you don’t think carefully you might think that programming is just typing statements in a programming language.
Are you a pragmatic programmer?

If you are a pragmatic programmer, you'll share many of the following characteristics:
  • Early adopter / fast adapter
    • You have an instinct for technologies and techniques, and you love trying things out. When given something new, you can grasp it quickly and integrate it with the rest of your knowledge. Your confidence is born of experience.
  • Inquisitive
    • You tend to ask questions.
  • Critical thinker
    • You rarely take things as given without first getting the facts.
  • Realistic
    • You try to understand the underlying nature of each problem you face. This realism gives you a good feel for how difficult things are, and how long things will take.
  • Jack of all trades
    • You try hard to be familiar with a broad range of technologies and environments, and you work to keep abreast of new developments. Although your current job may require you to be a specialist, you will always be able to move on to new areas and new challenges
Self-Development and Career
  • Take responsibility for everything you do.
  • Every day, work to refine the skills you have and to add new tools to you repertoire.
  • A pragmatic programmer takes charge of his or her own career, and isn't afraid to admit ignorance or error.
  • Don’t blame someone or something else, or make up an excuse. Don’t blame all the problems on a vendor, a programming language, management, or your co-workers. Any and all of these may play a role, but it is up to you to provide solutions, not excuses. Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done to salvage the situation.
  • Don’t be afraid to ask, or to admit that you need help.
  • You must invest in your knowledge portfolio regularly
  • You need to know the ins and outs of the particular technology you are working with currently. But don’t stop there. The face of computing change rapidly. The more technologies you are comfortable with, the better you will be able to adjust to change. Stay current!
  • Learning an emerging technology before it becomes popular can be just as hard as finding an undervalued stock, but the payoff can be just as rewarding.
  • Learn at least one new language every year.
  • Read a technical book each quarter (and then each month).
  • Read non-technical books, too.
  • Think critically about what you read and hear.
  • Make a point of reading other people’s source code and documentation, either informally or during code reviews. You’re not snooping- you’re learning from them. Even if your project doesn't use that technology, perhaps you can borrow some ideas.
  • There are two world-class professional societies for programmers: the Association for Computing Machinery (ACM) and the IEEE Computer Society. We recommend that all programmers belong to one (or both) of these societies. In addition, developers outside the USA may want to join their national societies, such as the BCS in the United Kingdom.
Perfectionism
  • Don’t spoil a perfectly good program by over embellishment and over-refinement. Move on, and let your code stand in its own right for a while. It may not be perfect. Don’t worry: it could never be perfect.
  • In addition to doing your own personal best, you must analyze the situation for risks that are beyond your control.
  • There is no such thing as a best solution, be it a tool, a language, or an operating system. There can only be systems that are more appropriate in a particular set of circumstances.You shouldn't be wedded to any particular technology, but have a broad enough background and experience base to allow you to choose good solutions in particular situations.
  • Because we can’t write perfect software, it follows that we can’t write perfect test software either. We need to test the tests. After you have written a test to detect a particular bug, cause the bug deliberately and make sure the test complains.
People
  • Participate in local user groups.
  • Care and cultivation of gurus is important.
  • Turn the meeting into a dialog, and you’ll make your point more effectively. Who knows, you might even learn something.
  • There’s one technique that you must use if you want people to listen to you: listen to them.
  • A good idea is an orphan without effective communication.
  • Dealing with computer systems is hard. Dealing with people is even harder.
  • Work out what you can reasonably ask for. Develop it well. Once you've got it, show people, and let them marvel. Then say “of course, it would be better if we added…”. Pretend it’s not important. Sit back and wait for them to start asking you to add the functionality you originally wanted. People find it easier to join an ongoing success.
  • Organize your resources (people) using the same techniques you use to organize code.
General Advices
  • Always respond to e-mails and voice mails, even if the response is simply “I’ll get back to you later”.
  • DRY – Don’t Repeat Yourself
  • It’s a great idea to record your estimates so you can see how close you were. When an estimate turns out wrong, don’t just shrug and walk away. Find out why it differed from you guess.
  • What to say when asked for an estimate: “I’ll get back to you”.
  • It’s important to discover the underlying reason why users do a particular thing, rather than just the way they currently do it.
  • We want to see pride of ownership. People should see your name on a piece of code and expect it to be solid, well written, tested, and documented.
Technical Advices
  • Never run on auto-pilot. Constantly be thinking, critiquing your work in real time.
  • We want to design components that are self-contained: independent, and with a single, well-defined purpose. An orthogonal approach reduces the risks inherent in any development.
  • Be careful to preserve the orthogonality of your system as you introduce third-party toolkits and libraries. Choose your technologies wisely.
  • Normally, you can simply hide a third-party product behind a well-defined, abstract interface. In fact, we've always been able to do so on any project we've worked on.
  • Write code using the vocabulary of the application domain.
  • Tools amplify your talent. The better you tools, and the better you know how to use them, the more productive you can be.
  • The best format for storing knowledge persistently is plain text.
  • GUI environments are normally limited to the capabilities that their designers intended. The command line is better suited when you want to quickly combine a couple of commands to perform a query or some other task. Invest some energy in becoming familiar with your shell and things will soon start falling into place. Investigate alternatives to you current shell.
  • Make sure that the editor you choose is available on all platforms you use.
  • Embrace the fact that debugging is just problem solving and attack it as such. It doesn't really matter whether the bug is your fault or someone else’s. It is still your problem.
  • Set compiler warning levels as high as possible. Concentrate on the harder problems at hand. You must brutally test both boundary conditions and realistic end-user usage patterns. You need to do this systematically.
  • The best way to start fixing a bug is to make it reproducible.
  • A very simple but particularly useful technique for finding the cause of a problem is simply to explain it to someone else. They do not need to say a word; the simple act of explaining, step by step, what the code is supposed to do often causes the problem to leap off the screen and announce itself.
  • Once a human tester finds a bug, it should be the last time a human tester finds that bug.
  • When faced with a “surprising” failure, you must realize that one or more of your assumptions is wrong. Don’t gloss over a routing or piece of code involved in the bug because you “know” it works. Prove it. Prove it in this context, with this data, with these boundary conditions.
  • If it can’t happen, use assertions to ensure that it won’t. Never put code that must be executed into an assert. Don’t use assertions in place of real error handling. Assertions check for things that should never happen.
  • Exceptions should rarely be used as part of a program’s normal flow.
  • We need to allow for concurrency and to think about decoupling any time or order dependencies.
  • Coding is not mechanical. There are decisions to be made every minute- decisions that require careful thought and judgment if the resulting program is to enjoy a long, accurate, and productive life. Pragmatic programmers thing critically about all code, including our own. We constantly see room for improvement in our programs and our designs. You should be careful of tools that write reams of code on your behalf unless you understand what they’re doing.
  • For routines you call, rely only on documented behavior. If you can’t, for whatever reason, then document your assumption well.
  • Don’t be a slave to history. Don’t let existing code dictate future code.
  • Software development is still not a science. Let your instincts contribute to your performance.
  • The only timing that counts is the speed of your code, running in the production environment, with real data. Be wary of premature optimization. It’s always a good idea to make sure an algorithm really is a bottleneck before investing your precious time trying to improve it.
  • Time pressure is often used as an excuse for not refactoring. But this excuse just doesn't hold up: fail to refactor now, and there’ll be a far greater time investment to fix the problem down the road- when there are more dependencies to reckon with.
  • Keep track of the things that need to be refactored.
  • Refactoring is an activity that needs to be undertaken slowly, deliberately and carefully. Don’t try to refactor and add functionality at the same time. Make sure you have good tests before you begin refactoring.
  • We need to build testability into the software from the very beginning, and test each piece thoroughly before trying to wire them together.
  • It’s convenient, but not always practical, for each class or module to contain its own unit test.
  • Don’t be a slave to any notation; use whatever method best communicates the requirements with your audience. A big danger in producing a requirements document is being too specific. Good requirements documents remain abstract.
  • Many projects failures are blamed on an increase in scope. It’s easy to get sucked into the “just one more feature” maelstrom.
  • Create and maintain a project glossary.
  • Publishing of project documents to internal web sites for easy access by all participants is particularly useful for requirements documents.
  • When faced with an intractable problem, enumerate all the possible avenues you have before you. Don’t dismiss anything, no matter how unusable or stupid it sounds. Now go through the list and explain why a certain path cannot be taken. Are you sure? Can you prove it?
  • Great performers share a trait: they know when to start and when to wait.
  • Software development is still not a science. Let your instincts contribute to your performance.
  • Blindly adopting any technique without putting it into the context of your development practices and capabilities is a recipe for disappointment.
  • We prefer to understand the whole of the system we’re working on. It may not be possible to have an in-depth grasp of every aspect of a system, but you should know how the components interact, where the data lives, and what the requirements are.
  • Never underestimate the cost of adopting new tools and methods.
  • Pragmatic programmers look at methodologies critically, then extract the best from each and meld them into a set of working practices that gets better each month.
  • There are advantages to being a pragmatic individual, but these advantages are multiplied many fold if the individual is working on a pragmatic team. The team speaks with one voice-externally. Internally, we strongly encourage lively, robust debate. Good developers tend to be passionate about their work.
  • Compile projects with make files, even when using an IDE environment.
  • Many development teams use an internal web site for project communication, and we think this is a great idea.
  • As with validation and verification, you need to perform usability testing as early as you can, while there is still time to make corrections.
  • Use metrics: cyclomatic complexity, inheritance fan-in and fan-out, response set, class coupling ratio, …
  • Pragmatic programmers embrace documentation as an integral part of the overall development process.
  • In reality, the success of a project is measured by how well it meets the expectations of its users. Never lose sight of the business problems your application is intended to solve.
Programmers are constantly in maintenance mode. Our understanding changes day by day.

Pragmatic programmers should always be learning.

No comments:

Post a Comment

What you think about this post? I really appreciate your constructive feedback (positive and negative) and I am looking forward to start a discussion with you on this topic.