Skip to content

Instantly share code, notes, and snippets.

@jonnyjava
Last active November 27, 2023 22:16
Show Gist options
  • Save jonnyjava/caaae696ab35deb4403b1555e41a6a6a to your computer and use it in GitHub Desktop.
Save jonnyjava/caaae696ab35deb4403b1555e41a6a6a to your computer and use it in GitHub Desktop.
97 Things Every Programmer Should Know: Collective Wisdom from the Experts

97 Things Every Programmer Should Know: Collective Wisdom from the Experts

  1. Act with Prudence

    • Pay off technical debt as soon as possible. It would be imprudent to do otherwise.
  2. Apply Functional Programming Principles

  3. Ask "What Would the User Do?" (You Are Not the User)

    • Spending an hour watching users is more informative than spending a day guessing what they want.
  4. Automate Your Coding Standard

    • Make sure code formatting is part of the build process, so that everybody runs it automatically every time they compile the code.
    • Use static code analysis tools to scan the code for unwanted antipatterns. If any are found, break the build.
    • Learn to configure those tools so that you can scan for your own, projectspecific antipatterns.
    • Do not only measure test coverage, but automatically check the results, too. Again, break the build if test coverage is too low.
  5. Beauty Is in Simplicity

    • Beauty of style and harmony and grace and good rhythm depends on simplicity.
    • There are a number of things we strive for in our code:
      • Readability
      • Maintainability
      • Speed of development
      • The elusive quality of beauty
  6. Before You Refactor

    • The best approach for restructuring starts by taking stock of the existing codebase and the tests written against that code. Avoid the temptation to rewrite everything.This will waste a lot of time, effort, and knowledge gained over the years.
    • Many incremental changes are better than one massive change.
    • After each development iteration, it is important to ensure that the existing tests pass
    • Personal preferences and ego shouldn’t get in the way.
    • New technology is an insufficient reason to refactor
    • Remember that humans make mistakes
  7. Beware the Share

  8. The Boy Scout Rule

    • Always leave the campground cleaner than you found it.
  9. Check Your Code First Before Looking to Blame Others

  10. Choose Your Tools with Care

  11. Code in the Language of the Domain

  12. Code Is Design

    • There is one inescapable fact: great designs are produced by great designers dedicating themselves to the mastery of their craft. Code is no different
  13. Code Layout Matters

  14. Code Reviews

    • The purpose of code reviews should be to share knowledge and establish common coding guidelines.
    • Sharing your code with other programmers enables collective code ownership.
  15. Coding with Reason

  16. A Comment on Comments

  17. Comment Only What the Code Cannot Say, Comment what the code cannot say, not simply what it does not say.

  18. Continuous Learning, Technology changes fast. Don’t get left behind.

  19. Convenience Is Not an -ility.

    • An API should provide an expressive language, which gives the next layer above sufficient vocabulary to ask and answer useful questions. A consistent and well-thought-out API vocabulary makes for expressive and easy-to-understand code in the next layer up
  20. Deploy Early and Often

  21. Distinguish Business Exceptions from Technical.

    • Mixing technical exceptions and business exceptions in the same hierarchy blurs the distinction and confuses the caller about what the method contract is, what conditions it is required to ensure before calling, and what situations it is supposed to handle.
    • Separating the cases gives clarity and increases the chances that technical exceptions will be handled by some application framework, while the business domain exceptions actually are considered and handled by the client code.
  22. Do Lots of Deliberate Practice

    • You do deliberate practice to master the task, not to complete the task
  23. Domain-Specific Languages

  24. Don’t Be Afraid to Break Things, Never stop caring about the general health of the code.

  25. Don’t Be Cute with Your Test Data

    • In summary, when writing any text in your code—whether comments, logging, dialogs, or test data—always ask yourself how it will look if it becomes public. It will save some red faces all around.
  26. Don’t Ignore That Error!

  27. Don’t Just Learn the Language, Understand Its Culture.

    • If you explore new languages to expand your mind and get fresh ideas on how you can solve things in different ways, you will find that the code you write in your trusty old language gets more beautiful for every new language you’ve learned.
  28. Don’t Nail Your Program into the Upright Position

  29. Don’t Rely on "Magic Happens Here"

    • When you aren’t actively involved in things, there is an unconscious tendency to assume that they are simple and happen "by magic". While the magic continues to happen, all is well. But when—it is usually "when" and not "if" the magic stops, the project is in trouble.
    • You don’t have to understand all the magic that makes your project work, but it doesn’t hurt to understand some of it, or to appreciate someone who understands the bits you don’t.
    • Most importantly, make sure that when the magic stops, it can be started again.
  30. Don’t Repeat Yourself

    • "every piece of knowledge must have a single, unambiguous, authoritative representation within a system".
  31. If it’s broken, production is not the place to fix it.

  32. Encapsulate Behavior, Not Just State

  33. Floating-Point Numbers Aren’t Real, you shouldn’t use floating-point numbers for financial applications

  34. Fulfill Your Ambitions with Open Source

  35. The Golden Rule of API Design

    • It’s not enough to write tests for an API you develop; you have to write unit tests for code that uses your API.
  36. The Guru Myth.

    • A "guru" is simply a smart person with relentless curiosity.

    • We don’t need gurus. We need experts willing to develop other experts in their field. There is room for all of us.

  37. Hard Work Does Not Pay Off

    • If you are trying to be focused and "productive" for more than 30 hours a week, you are probably working too hard.

    • Avoid embarrassing yourself, and our profession, by behaving like a hamster in a cage spinning the wheel.

    • As a professional programmer, you should know that trying to be focused and “productive” 60 hours a week is not a sensible thing to do.

    • Act like a professional: prepare, effect, observe, reflect, and change.

  38. How to Use a Bug Tracker

    • A good bug report needs to convey three things:
      • How to reproduce the bug, as precisely as possible, and how often this will make the bug appear
      • What should have happened, at least in your opinion
      • What actually happened, or at least as much information as you have recorded.
    • Remember that a bug is not a standard unit of work any more than a line of code is a precise measurement of effort.
  39. Improve Code by Removing It

    • What are you working on right now? Is it all needed?
  40. Install Me, make onboarding easy or peoplevwill leave quickly

  41. Interprocess Communication Affects Application Response Time.

    • When you’re designing an application, be mindful of the number of interprocess communications in response to each stimulus.
    • When analyzing applications that suffer from poor performance, I have often found IPC-to-stimulus ratios of thousands-to-one. Reducing this ratio, whether by caching or parallelizing or some other technique, will pay off much more than changing data structure choice or tweaking a sorting algorithm.
  42. Keep the Build Clean.

    • Keeping the build clean is not just about keeping it free of compilation errors or test failures: warnings are also an important and critical part of code hygiene.
  43. Know How to Use Command-Line Tools

    • "look under the hood" and understand what your IDE is doing for you. The best way to do that is to learn to use command-line tools.
  44. Know Well More Than Two Programming Languages

  45. Know Your IDE

  46. Know Your Limits

  47. Know Your Next Commit

    • If you cannot finish, throw away your changes, then define a new task you believe in with the insights you have gained.
    • Do speculative experimentation whenever needed, but do not let yourself slip into speculative mode without noticing.
    • Do not commit guesswork into your repository.
  48. Large, Interconnected Data Belongs to a Database

  49. Learn Foreign Languages, to know another language is to have another soul.

  50. Learn to Estimate.

    • "The primary purpose of software estimation is not to predict a project’s outcome; it is to determine whether a project’s targets are realistic enough to allow the project to be controlled to meet them."
    • Thus, the purpose of estimation is to make proper project management and planning possible, allowing the project stakeholders to make commitments based on realistic targets.
  51. Learn to Say, “Hello, World”

  52. Let Your Project Speak for Itself

  53. The Linker Is Not a Magical Program

  54. The Longevity of Interim Solutions.

    • The best way to overcome interim solutions is to make them superfluous, to provide a more elegant and useful solution.
    • May you be granted the serenity to accept the things you cannot change, the courage to change the things you can, and the wisdom to know the difference.
  55. Make Interfaces Easy to Use Correctly and Hard to Use Incorrectly.

    • Remember that interfaces exist for the convenience of their users, not their implementers.
  56. Make the Invisible More Visible.

    • Lack of visible progress is synonymous with lack of progress.
    • It’s best to develop software with plenty of regular visible evidence.
    • Visibility gives confidence that progress is genuine and not an illusion, deliberate and not unintentional, repeatable and not accidental.
  57. Message Passing Leads to Better Scalability in Parallel Systems.

    • Instead of using threads and shared memory as our programming model, we can use processes and message passing.
    • Process here just means a protected independent state with executing code, not necessarily an operating system process.
    • We can go further and introduce dataflow systems as a way of computing.
    • In a dataflow system, there is no explicitly programmed control flow. Instead, a directed graph of operators, connected by data paths, is set up and then data is fed into the system.
    • Evaluation is controlled by the readiness of data within the system.
    • Definitely no synchronization problems.
  58. Think of every line of code you write as a message for someone in the future.

  59. Missing Opportunities for Polymorphism.

    • Used carefully, polymorphism creates tiny localized execution contexts that let us work without the need for verbose if-then-else blocks.
    • Being in a context allows us to do the right thing directly, whereas being outside of that context forces us to reconstruct it so that we can then do the right thing.
    • With careful use of alternate implementations, we can capture context that can help us produce less code that is more readable.
  60. News of the Weird: Testers Are Your Friends

  61. One Binary.

    • The rule is simple: Build a single binary that you can identify and promote through all the stages in the release pipeline.
    • Hold environment-specific details in the environment.
    • This could mean, for example, keeping them in the component container, in a known file, or in the path.
    • And one more thing: keep the environment information versioned, too.
  62. Only the Code Tells the Truth.

  63. Own (and Refactor) the Build

  64. Pair Program and Feel the Flow.

    • Reduce the “truck factor.”
    • Solve problems effectively
    • Integrate smoothly
    • Mitigate interruptions.
    • Bring new team members up to speed quickly
  65. Prefer Domain Specific Types to Primitive Types

  66. Prevent Errors.

    • Understanding how users think, interpret information, make decisions, and input data will help you debug the interactions between your software and your users.
  67. The Professional Programmer.

    • The single most important trait of a professional programmer is personal responsibility.
    • Professional programmers take responsibility for their career, their estimates, their schedule commitments, their mistakes, and their workmanship.
    • A professional programmer does not pass that responsibility off on others.
    • If you are a professional, then you are responsible for your own career.
    • Professionals take responsibility for the code they write.
    • Professionals are team players.
    • Professionals do not tolerate big bug lists.
    • Professionals do not make a mess.
    • Professionals are responsible. They take responsibility for their own careers. They take responsibility for making sure their code works properly. They take responsibility for the quality of their workmanship. They do not abandon their principles when deadlines loom. Indeed, when the pressure mounts, professionals hold ever tighter to the disciplines they know are right.
  68. Put Everything Under Version Control

  69. Put the Mouse Down and Step Away from the Keyboard.

    • The next time you hit a nasty problem, do yourself a favor. Once you really understand the problem, go do something involving the creative side of your brain—sketch out the problem, listen to some music, or just take a walk outside.
  70. Read Code

  71. Read the Humanities

  72. Reinvent the Wheel Often.

    • Reinventing the wheel and getting it wrong is more valuable than nailing it first time.
    • There are lessons learned from trial and error that have an emotional component to them that reading a technical book alone just cannot deliver!
    • Learned facts and book smarts are crucial, but becoming a great programmer is as much about acquiring experience as it is about collecting facts.
    • Reinventing the wheel is as important to a developer’s education and skill as weightlifting is to a body builder.
  73. Resist the Temptation of the Singleton Pattern.

    • The single-instance requirement is often imagined.Requirements will change. Good design embraces this. Singletons don’t.
    • Singletons cause implicit dependencies between conceptually independent units of code
    • Singletons also carry implicit persistent state, which again hinders unit testing
    • Multithreading introduces further pitfalls to the singleton pattern.
    • There is no support for explicitly killing singletons.
    • There is no order to the implicit cleanup of singletons at program exit.
  74. The Road to Performance Is Littered with Dirty Code Bombs

  75. Simplicity Comes from Reduction.

    • The code should be simple. There should be a minimal number of variables, functions, declarations, and other syntactic language necessities.
    • Extra lines, extra variables…extra anything, really, should be purged immediately.
  76. The Single Responsibility Principle.

    • Gather together those things that change for the same reason, and separate those things that change for different reasons
  77. Start from Yes.

    • Starting from yes means working with your colleagues, not against them.
  78. Step Back and Automate, Automate, Automate

  79. Take Advantage of Code Analysis Tools

  80. Test for Required Behavior, Not Incidental Behavior.

    • To be effective, tests need to state contractual obligations rather than parrot implementations.
    • They need to take a blackbox view of the units under test, sketching out the interface contracts in executable form. Therefore, align tested behavior with required behavior.
  81. Test Precisely and Concretely.

    • Using concrete examples eliminates accidental complexity and opportunities for accidents. In specifying behavior, tests should not simply be accurate: they must also be precise
  82. Test While You Sleep (and over Weekends)

  83. Testing Is the Engineering Rigor of Software Development

  84. Thinking in States.

    • State machines are not particularly hard. Visualize them to make them simple to understand and easy to talk about.
    • Test-drive your code to unravel valid and invalid states and transitions and to keep them correct.
    • Study the State pattern. When you feel comfortable, read up on Design by Contract. It helps you ensure a valid state by validating incoming data and the object itself on entry and exit of each public method.
  85. Two Heads Are Often Better Than One

  86. Two Wrongs Can Make a Right (and Are Difficult to Fix).

    • Single wrongs can be easy to spot and easy to fix. It is the problems with multiple causes, needing multiple changes, that are harder to resolve.
    • There is no simple advice for how to address faults arising from sympathetic defects.
  87. Ubuntu Coding for Your Friends.

    • It is not about the code, the artifact. It is about the act of creating that artifact. The next person that touches your code, in whatever way, will be a better person and a better developer.
    • Zen is about the individual. Ubuntu is about Zen for a group of people. Very, very rarely do we create code for ourselves alone.
  88. The Unix Tools Are Your Friends

  89. Use the Right Algorithm and Data Structure

  90. Verbose Logging Will Disturb Your Sleep.

    • A cluttered log is an indication that the system will be hard to control once it reaches production.
    • If you don’t expect anything to show up in the error log, it will be much easier to know what to do when something does show up.
  91. WET Dilutes Performance Bottlenecks.

    • The antithesis of DRY is WET (Write Every Time).
    • Our code is WET when knowledge is codified in several different implementations.
    • The performance implications of DRY versus WET become very clear when you consider their numerous effects on a performance profile.
  92. When Programmers and Testers Collaborate

  93. Write Code As If You Had to Support It for the Rest of Your Life.

    • The code you wrote many years ago still influences your career, whether you like it or not.
    • You leave a trail of your knowledge, attitude, tenacity, professionalism, level of commitment, and degree of enjoyment with every method, class, and module you design and write.
    • Take care of your career, of your clients, and of your users with every line of code you write.
  94. Write Small Functions Using Examples.

    • Using domain-inspired types can often make our functions much smaller. One way to find out what those types should be is to find the examples to check in problem domain terms, before writing the function.
  95. Write Tests for People.

    • Good tests act as documentation for the code they are testing. They describe how the code works. For each usage scenario, the test(s):
      • Describe the context, starting point, or preconditions that must be satisfied
      • Illustrate how the software is invoked
      • Describe the expected results or postconditions to be verified
  96. You Gotta Care About the Code.

    • The real difference between adequate programmers and great programmers is attitude.
  97. Your Customers Do Not Mean What They Say.

    • Just interact with them more.
  98. Read the book. A summary is never enough

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment