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