CodingStyle.rst 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. .. SPDX-License-Identifier: GPL-2.0
  2. bcachefs coding style
  3. =====================
  4. Good development is like gardening, and codebases are our gardens. Tend to them
  5. every day; look for little things that are out of place or in need of tidying.
  6. A little weeding here and there goes a long way; don't wait until things have
  7. spiraled out of control.
  8. Things don't always have to be perfect - nitpicking often does more harm than
  9. good. But appreciate beauty when you see it - and let people know.
  10. The code that you are afraid to touch is the code most in need of refactoring.
  11. A little organizing here and there goes a long way.
  12. Put real thought into how you organize things.
  13. Good code is readable code, where the structure is simple and leaves nowhere
  14. for bugs to hide.
  15. Assertions are one of our most important tools for writing reliable code. If in
  16. the course of writing a patchset you encounter a condition that shouldn't
  17. happen (and will have unpredictable or undefined behaviour if it does), or
  18. you're not sure if it can happen and not sure how to handle it yet - make it a
  19. BUG_ON(). Don't leave undefined or unspecified behavior lurking in the codebase.
  20. By the time you finish the patchset, you should understand better which
  21. assertions need to be handled and turned into checks with error paths, and
  22. which should be logically impossible. Leave the BUG_ON()s in for the ones which
  23. are logically impossible. (Or, make them debug mode assertions if they're
  24. expensive - but don't turn everything into a debug mode assertion, so that
  25. we're not stuck debugging undefined behaviour should it turn out that you were
  26. wrong).
  27. Assertions are documentation that can't go out of date. Good assertions are
  28. wonderful.
  29. Good assertions drastically and dramatically reduce the amount of testing
  30. required to shake out bugs.
  31. Good assertions are based on state, not logic. To write good assertions, you
  32. have to think about what the invariants on your state are.
  33. Good invariants and assertions will hold everywhere in your codebase. This
  34. means that you can run them in only a few places in the checked in version, but
  35. should you need to debug something that caused the assertion to fail, you can
  36. quickly shotgun them everywhere to find the codepath that broke the invariant.
  37. A good assertion checks something that the compiler could check for us, and
  38. elide - if we were working in a language with embedded correctness proofs that
  39. the compiler could check. This is something that exists today, but it'll likely
  40. still be a few decades before it comes to systems programming languages. But we
  41. can still incorporate that kind of thinking into our code and document the
  42. invariants with runtime checks - much like the way people working in
  43. dynamically typed languages may add type annotations, gradually making their
  44. code statically typed.
  45. Looking for ways to make your assertions simpler - and higher level - will
  46. often nudge you towards making the entire system simpler and more robust.
  47. Good code is code where you can poke around and see what it's doing -
  48. introspection. We can't debug anything if we can't see what's going on.
  49. Whenever we're debugging, and the solution isn't immediately obvious, if the
  50. issue is that we don't know where the issue is because we can't see what's
  51. going on - fix that first.
  52. We have the tools to make anything visible at runtime, efficiently - RCU and
  53. percpu data structures among them. Don't let things stay hidden.
  54. The most important tool for introspection is the humble pretty printer - in
  55. bcachefs, this means `*_to_text()` functions, which output to printbufs.
  56. Pretty printers are wonderful, because they compose and you can use them
  57. everywhere. Having functions to print whatever object you're working with will
  58. make your error messages much easier to write (therefore they will actually
  59. exist) and much more informative. And they can be used from sysfs/debugfs, as
  60. well as tracepoints.
  61. Runtime info and debugging tools should come with clear descriptions and
  62. labels, and good structure - we don't want files with a list of bare integers,
  63. like in procfs. Part of the job of the debugging tools is to educate users and
  64. new developers as to how the system works.
  65. Error messages should, whenever possible, tell you everything you need to debug
  66. the issue. It's worth putting effort into them.
  67. Tracepoints shouldn't be the first thing you reach for. They're an important
  68. tool, but always look for more immediate ways to make things visible. When we
  69. have to rely on tracing, we have to know which tracepoints we're looking for,
  70. and then we have to run the troublesome workload, and then we have to sift
  71. through logs. This is a lot of steps to go through when a user is hitting
  72. something, and if it's intermittent it may not even be possible.
  73. The humble counter is an incredibly useful tool. They're cheap and simple to
  74. use, and many complicated internal operations with lots of things that can
  75. behave weirdly (anything involving memory reclaim, for example) become
  76. shockingly easy to debug once you have counters on every distinct codepath.
  77. Persistent counters are even better.
  78. When debugging, try to get the most out of every bug you come across; don't
  79. rush to fix the initial issue. Look for things that will make related bugs
  80. easier the next time around - introspection, new assertions, better error
  81. messages, new debug tools, and do those first. Look for ways to make the system
  82. better behaved; often one bug will uncover several other bugs through
  83. downstream effects.
  84. Fix all that first, and then the original bug last - even if that means keeping
  85. a user waiting. They'll thank you in the long run, and when they understand
  86. what you're doing you'll be amazed at how patient they're happy to be. Users
  87. like to help - otherwise they wouldn't be reporting the bug in the first place.
  88. Talk to your users. Don't isolate yourself.
  89. Users notice all sorts of interesting things, and by just talking to them and
  90. interacting with them you can benefit from their experience.
  91. Spend time doing support and helpdesk stuff. Don't just write code - code isn't
  92. finished until it's being used trouble free.
  93. This will also motivate you to make your debugging tools as good as possible,
  94. and perhaps even your documentation, too. Like anything else in life, the more
  95. time you spend at it the better you'll get, and you the developer are the
  96. person most able to improve the tools to make debugging quick and easy.
  97. Be wary of how you take on and commit to big projects. Don't let development
  98. become product-manager focused. Often time an idea is a good one but needs to
  99. wait for its proper time - but you won't know if it's the proper time for an
  100. idea until you start writing code.
  101. Expect to throw a lot of things away, or leave them half finished for later.
  102. Nobody writes all perfect code that all gets shipped, and you'll be much more
  103. productive in the long run if you notice this early and shift to something
  104. else. The experience gained and lessons learned will be valuable for all the
  105. other work you do.
  106. But don't be afraid to tackle projects that require significant rework of
  107. existing code. Sometimes these can be the best projects, because they can lead
  108. us to make existing code more general, more flexible, more multipurpose and
  109. perhaps more robust. Just don't hesitate to abandon the idea if it looks like
  110. it's going to make a mess of things.
  111. Complicated features can often be done as a series of refactorings, with the
  112. final change that actually implements the feature as a quite small patch at the
  113. end. It's wonderful when this happens, especially when those refactorings are
  114. things that improve the codebase in their own right. When that happens there's
  115. much less risk of wasted effort if the feature you were going for doesn't work
  116. out.
  117. Always strive to work incrementally. Always strive to turn the big projects
  118. into little bite sized projects that can prove their own merits.
  119. Instead of always tackling those big projects, look for little things that
  120. will be useful, and make the big projects easier.
  121. The question of what's likely to be useful is where junior developers most
  122. often go astray - doing something because it seems like it'll be useful often
  123. leads to overengineering. Knowing what's useful comes from many years of
  124. experience, or talking with people who have that experience - or from simply
  125. reading lots of code and looking for common patterns and issues. Don't be
  126. afraid to throw things away and do something simpler.
  127. Talk about your ideas with your fellow developers; often times the best things
  128. come from relaxed conversations where people aren't afraid to say "what if?".
  129. Don't neglect your tools.
  130. The most important tools (besides the compiler and our text editor) are the
  131. tools we use for testing. The shortest possible edit/test/debug cycle is
  132. essential for working productively. We learn, gain experience, and discover the
  133. errors in our thinking by running our code and seeing what happens. If your
  134. time is being wasted because your tools are bad or too slow - don't accept it,
  135. fix it.
  136. Put effort into your documentation, commit messages, and code comments - but
  137. don't go overboard. A good commit message is wonderful - but if the information
  138. was important enough to go in a commit message, ask yourself if it would be
  139. even better as a code comment.
  140. A good code comment is wonderful, but even better is the comment that didn't
  141. need to exist because the code was so straightforward as to be obvious;
  142. organized into small clean and tidy modules, with clear and descriptive names
  143. for functions and variable, where every line of code has a clear purpose.