// Design:
//
// [... 4 paragraphs of English prose
// explaining goals and intent... ]
That's exactly the type of comment that should be at the beginning of most files! // Design:
//
// [... 4 paragraphs of English prose
// explaining goals and intent... ]
That's exactly the type of comment that should be at the beginning of most files!It still baffles me. Every programmer has to start from scratch dealing with a new codebase, and it makes improving any non-trivial program impossible unless one is willing to spend hours of archaeological examination. To open-source developers: if you want to get people contributing to a project (and make everyone's effort much more enjoyable!), these sorts of comments are essential. Not to mention they'll save everyone boatloads of time; it's a shame that every programmer has to piece together knowledge from scratch, rather than being 'tutored' by their peers' comments.
This is not to say that there aren't reasons to write large comment blocks, or architecture documents, but that they are often better written not while the system is being first built, but later, in a maintenance cycle, when someone already had wished for the comments, and has regained the knowledge the hard way. By then, it's clear which part of the system are dangerous, suspicious and unclear. Where there's more need for high quality error handling, and where thousands of lines of error handling never get hit, because the failing case that was originally considered doesn't really happen in this dimension anymore.
Writing code so that someone, even a future you, can pick it back up and improve it when it's needed, while still delivering the code at a good pace is a kind of skill that many just don't learn, either because they are always in greenfield teams that never pay for their mistakes, or have an approach to maintenance that involves not becoming intimate familiar with a system, and instead either hack or rewrite.
But nobody looks great in a resume by saying that they are a specialist in software maintenance.
I don't think the "Lean Manufacturing" approach works here. By the time someone "pulls" you for a comment, you've already lost the most important knowledge that should go into the comments - why the code is the way it is. Maybe you'll recall it when asked, hopefully not missing anything crucial. Meanwhile, comments are extremely cheap to write as you're writing the code, and even before you're writing the code (you did spend the time thinking about what you'll write, and aren't just "coding from the hip", right?).
And writing documentation only seems like a waste of time to the developer who just finished writing the code. It wastes their time. But spending time now to write good documentation saves the organization as a whole much more of other developer's time in the long run. It's a smart investment to make, even when the collateral damage is time wasted documenting code that really is thrown out.
(But, if you actually document the code well you'll find out that you throw things out much less often.)
I disagree with what you wrote. It does not waste developers time, it wastes money of business owners. Developers are usually paid for their time even if they are reading HN instead of working.
Now question is to people who pay money if they want to pay for "something in the future maybe will be useful". They will say hell no! They want time to market to be as short as possible and as much of end user value delivered.
Now you take example of SQLite or Armin Ronacher those are exceptions. There is a lot more software that is not anything done by Armin and is not SQLite.
Sometime also a code is meant to be temporary but is later deems to useful not to be used but no resource is allocated to is maintenance (in this case we could say refactoring). It's the case of many internal tools.
I remember when I did my first internship, I was in the configuration management team and I was responsible for doing the smoke test. I made some tools for myself to speedup the process and once my manager saw how useful they were, he was interested of giving them to the QA department. I refused because it broke every few builds and I knew after my internship I wouldn't be there to maintains them and it would just create more problems. There's so many instance where it wouldn't break so often or that person wasn't considering he would no longer be there to maintains it or won't have the time.
That said, I mostly agree... I tend to favor a discoverable code base, where the directory structure is organized over features... for example a given feature may have a few controls, some actions, state logic, api client for foreign system, etc... any of the above. I organize by the feature, not the type of files/components of those features.
I tend to favor using abstractions only when they are simple enough, or make the related code much more simplified and understandable. The exception to this is needed complexity, such as an enterprise product that needs to support being deployed on oracle, sql server, etc.
Simple, replaceable code is often better. That said, when you have a broadly used produce and a piece of functionality that is well used, moderately complex and unlikely to dramatically change, this level of detail isn't a bad thing.
Code without specification is a maintenance nightmare, a pure liability, a ticking time bomb.
And sure, unless you're creating the control system of a nuclear reactor/warhead you don't have to go full Coq and CMMI5 and "high assurance" and whatnot, but spilling a few sentences as a minimal kind of pseudocode before writing what you want (a function, a class, a method, change the build system, refactor a big ball of if-s) is almost ideal. It helps you double check yourself, and it helps reviewers too. (Throwing there links to some issue tracker is also nice, but just the links are not very helpful.)
If you have to write docs later, it's hacking (reverse engineering), not engineering.
> spilling a few sentences as a minimal kind of pseudocode before writing what you want
Isn't it simply repeating the code you'll write? Which in the end, will be just as bad as the code alone or will lose time of the one that will read it afterward.
Sure it's hard to write good code, sure it's not always obvious what's bad code, but that's a big reason why the review process is there. It's not only to catch mistakes, it's also to see if someone else can understands what the code meant, the context, the decisions, etc... Sadly many just go quickly over it and just check for obvious mistakes.
I agree with your point, and I will be benefit from this style if it were the standard, too. But don't you think a good community culture can make people maintain a good git history for this purpose?
My daily job is a Linux kernel developer. I found that source codes are only the "What" part, git comments can and should state the "How/Why" part, and if all those still make no sense to me, I look for the original mailing list for the deeper "Why". Most of the time the information is sufficient.
Also, the whole point of putting something in a comment is that you have to read it when working through code around that comment. Putting a note in a commit log instead ensures that crucial information important to the code will not be visible, and most likely not read at all, when working on that code.
It seems to be easy to find plenty of projects with bad Git commits though.
IMO the big architectural guidelines and structuring and other highest level things and API contracts etc. should be in an external file (not code). The high-level details around a certain implementation in the commit logs for that file/files. Relevant implementation details and important things in the code. The lower you go, the closer to a comment line in the code you should get. This reflects also the rigidity of the code: the high-level architecture should not change often; if it does, then the architecture is not really ready.
Things should be certainly documented, but not in great detail inside the code files. The lack of documentation is in my opinion OK, the code is always the last word for how things actually work anyway. Misleading or wrong documentation are the absolute worst.
Sure, the back-and-forth on a mailing list or review system such as Gerrit can provide more of those direct links between code and explanation, but then it's often buried in a bunch of other discussion and dead ends. It's the "oh noes, comments can become out of date" times ten, so hardly a good alternative. And even when that's not the case, it's a horribly context-switchy way to get that information. Separating the explanation and the concrete expression just isn't a great idea. Funny how many people who would rather die than write a design spec also suggest that an even greater separation is a good thing.
If your "why" doesn't contains this, I have an hard time understanding why you want it in the first place.
The "why" is important to not make the same mistake. Theses others discussions and dead ends are all related to the issue, they are all questions that was asked/answered during it, they are all mistakes that may have been made.
Personally every time I only needed a tiny bits more context, the commit message was enough and if I needed more, the full related ticket was essential (and not a simple why, but the full though process that became that decision).
> Funny how many people who would rather die than write a design spec
I'd rather die than lose time over something I consider won't save time in the long term. Writing any documentation is long and if that time is longer than the few time we'll need it, it's a loss of time.
It's pretty rare that we need to go back to that information, when we do, the ticket information is enough and if it's not, doing the though process a second time isn't so bad the rare time it happens (which will provide more context by the new ticket discussion too).
For sure if your ticket just say: - Break when we enter text - FIXED
You are going to have a pretty bad time and you need to change that.
The "why" doesn't need to include every minor style nit (all the way down to variable naming) that came up during the review. It doesn't need to include every "I would have done it this way instead" comment which was in neither the original nor final version. That's noise, not signal.
> Personally every time I only needed a tiny bits more context
Lucky you. For much of the code I have read or written, that was not the case. In general it tends to be less and less the case as code climbs up the complexity/innovation scale.
> I'd rather die than lose time over something I consider won't save time in the long term.
Is that an unavoidable issue with the medium, or more of a reflection of how some people are bad at writing? I've whipped out a spec for a medium-complexity feature or component in under an hour, and been thanked for it five years later. Many times. If you've never had that experience, then I can only say I hope you'll be able to some day.
> when we do, the ticket information is enough and if it's not
Again, lucky you. Others have a different experience.
> Minor fix
> Showing 6 files with 171 additions and 203 deletions
Histories of active projects grow with age. A well maintained artifact should plateau in complexity.
The assumption is that the original author knew what he was doing, and if not, there was a code review and anyone can fix it if they see a problem.
Finally, it's code that probably won't be around anymore five years down the line, so detailed commit messages etc feel like a waste.
(Mind you, I don't agree with the above. At the same time, I don't want to do this type of meaningless throwaway work anymore)
Currently the only person in-office over Christmas on my first software dev job. Debugging a 50k LOC COBOL beast that digs into three other beast programs and ends up in a final 20k LOC uncommented piece where things are supposed to happen and be returned back.
Nothing is commented, the programs are huge and one can only debug one program at a time, requiring me to submit untested changes in one of them to the shared dev environment since I'm making changes in two, before debugging the other program.
If it just said somewhere what half of the stuff is I would save an insane amount of time getting to know the system.
my first software dev job. Debugging a 50k LOC COBOL beast
We found the real MVP. tapland, what were you thinking when taking this job!?I have no real previous development experience, only some Java and Python, since I chose an industrial engineering program at uni, and I got the offer the semester before my CS-classes (my chosen specialization) started.
Changed my university classes to equivalent distance-classes and took six months of school to get into training and a job.
I think this type of summary should not be per source file but per package/folder/module/project. A high-level developer overview with sufficient depth will also help stop repetition of philosophy in subsequent files.
In this case, I do agree with its existence though because of both the length and complexity of the file. For many files, neither are the case.
I've met more than one codebase which tried to use a big hammer pattern to open doors. Heavy indirection to do simple things because of design choices, usually caused by a forced framework - instead of easily factorizable simplicity. Patterns should be emergent not forced. Or more specifically, the choice of appropriate pattern should be based on the problem being solved, rarely one pattern can cleanly solve all problems.
Similarity is very seductive but end result is often complex and hard to reason about when followed religiously.
Design patterns can tap you easily in bad designs. Usually the lost thing is performance, big way, or actual simplicity.
When I read something saying "writing thoughtful comments is too much work" I really read this as "thinking about the code you write is too much work, it's better to write whatever crap that first comes to mind".
A tautology is a tautology.
How long is a piece of string?
If you need to read comments to understand code, you don’t know how to read code. Comments can lie, only code is the source of truth, once you gain experience you won’t bother with comments.
The file in the OP is Go. In Go, you are encouraged to write documentation and code in one place[0]. The end result is very nice, auto-generated, human readable documentation[1] which is tightly coupled to the code it documents.
If the comments are completely redundant with the code, they're bad. But you can't express as code why the some code is the way it is, and why it does what it does. After you tried to express in code every important information that's expressible as code, whatever important information remains must go into comments.
Sometimes writing the proof of why it should be like this is tricky, especially when complexity or performance is involved. (But then the tests are hard too.)
Linters are essentially constraint systems for code, but not for the program.
It's an odd feeling, having the best of both worlds.
https://github.com/torvalds/linux/blob/master/drivers/net/et...
Magic numbers and timing without explanation why. Rarely used technical descriptions such as "Lance mode". Tons of unchecked assertions on lock when kernel provides a lockdep check for this. Custom logging macros. Flies in the face of kernel "goto error" error handling convention in a few places. XXX with obvious bugs mentioned, unfixed.
And more...
Splitting it into more files wouldn't help at all.
Solution: write clear, simple, modular code that is self-documenting and does not need extensive commenting.
Key trick is writing comments as close as possible to the code they affect. Then it's hard to miss affected comments if one's not doing a shoddy job.
That also helps it show up in a PR so it may be caught in code review. Even so, IME comments get missed enough that over time I can't be as confident as we'd like that they match the code.
I think it's also worth calling out that this key trick is not being applied in the recommendation up-thread, which asks for a block comment at the top of the module.
But here are a couple of Martin Fowler quotes (from his Refactoring book) I tend to follow:
“A heuristic we follow is that whenever we feel the need to comment something, we write a method instead.”
“Whenever I have to think to understand what the code is doing, I ask myself if I can refactor the code to make that understanding more immediately apparent.”