Has anyone ever tried creating a complete code documentation first, before actually writing the code? I was thinking about this earlier because I thought it would help to write a concrete interface and would make sure your initial design wasn't floored by making you think about how classes interact. Is this a good idea? Has anyone tried it? Ell
closed as primarily opinion-based by Greg Burghardt, gnat, 8bittree, JimmyJames, Robert Harvey♦ May 11 '18 at 0:48
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.
It gets you thinking about what, exactly, your code is supposed to do. The idea is that you could start with any part of the code and know exactly what needs to be done to complete that module.
It's also easier fix something on the drawing board than in the IDE.
There are two ways of thinking about it:
1) Documentation as in Word documents, Wiki, etc. By definition you cannot have a complete code documentation because you don't have a code to document. You can try to document hight level design, assumptions, interfaces and contracts first.
2) Documentation as executable tests. There is a school of thought that states that executable unit tests is the best documentation. This school of thought also advocates this kind of documentation before writing the code (TDD). At the same time you don't write all the tests for the whole system right form the start. You break it down by use cases first, then you do tests and code per use case.
Starting with the documentation is classic waterfall model, and has all the pitfalls associated with that model. Broadly, the more you document the more you have to update when the requirements change. One benefit of starting with user documentation is that you might get feedback (and hence changes) sooner. But experience shows that most people are bad at mentally mapping documentation to actions. So we use prototypes instead, which allow people to actually use the software and give feedback that way.
One variation on "documentation first" is literate programming. Start by writing a description of what the program will do from a programmers perspective. Keep tweaking that until it compiles. Voila, a literate program.
I personally find it better to use diagrams (such as UML) to do simple modeling to show the flow of things. This is much quicker than documenting things out in words and if done right can be just as descriptive. I would be hesitant to do Full Documentation though because personally I haven't ever had a project I've worked on that hasn't changed through the course of programming it.
EDIT: Some documentation though should be done as you go a long. This makes it easier to do the full documentation later.
Joshua Bloch discusses this very point in his interview for the book "Coders at Work".
Contrary to more orthodox and academic views, he advises something to the tune of your thoughts (maybe you have read it there yourself?): that before writing the documentation you have to understand what do you want from the system and get a more "real" feeling. For this purpose he would design part of the interfaces and some client code that uses them.
The most important thing is to know what you’re trying to build: what problem you’re trying to solve. The importance of requirements analysis can’t be overstated. There are people who think, “Oh, yeah, requirements analysis; you go to your customer, you say, ‘What do you need?’ He tells you, and you’re done.”
Nothing could be further from the truth. Not only is it a negotiation but it’s a process of understanding. Many customers won’t tell you a problem; they’ll tell you a solution. A customer might say, for instance, “I need you to add support for the following 17 attributes to this system. Then you have to ask, ‘Why? What are you going to do with the system? How do you expect it to evolve?’” And so on. You go back and forth until you figure out what all the customer really needs the software to do. These are the use cases.
Coming up with a good set of use cases is the most important thing you can do at this stage. Once you have that, you have a benchmark against which you can measure any possible solution. It’s OK if you spend a lot of time getting it reasonably close to right, because if you get it wrong, you’re already dead. The rest of the process will be an exercise in futility.
The worst thing that you can do—and I’ve seen this happen—is you get a bunch of smart guys into a room to work for six months and write a 247- page system specification before they really understand what it is they’re trying to build. Because after six months, they’ll have a very precisely specified system that may well be useless. And often they say, “We’ve invested so much in the spec that we have to build it.” So they build the useless system and it never gets used. And that’s horrible. If you don’t have use cases, you build the thing and then you try to do something very simple and you realize that, “Oh my gosh, doing something very simple like taking an XML document and printing it requires pages upon pages of boilerplate code.” And that’s a horrible thing.
-- Joshua Bloch, from an interview in "Coders at Work: Reflections on the Craft of Programming" by Peter Seibel
If you're already thinking along these lines, it'd be good if you can get a hold of the book and read the whole interview. As I said, he is always very enlightening.
Some people even go further and state that a company should completely work backwards, so
- Write the press release
- Write a FAQ
- Define the customer experience
- Write the User Manual
- Start programming
Writing the complete code documentation first is probably overkill and somewhat reminiscent of the waterfall methodology. However, I've found that a more pragmatic approach is writing the README first. Here's why:
The README does not document every detail of your project. Instead, it typically contains the following info:
- Description: short "sales pitch". Tell the reader why they should keep reading.
- Quick examples: short code snippets or screenshots to support the description.
- Quick start: how to get going, install instructions, and more examples.
- Further documentation: links to the full docs and more info.
- Project organization: who are the authors, how to contribute, how to file bugs.
- Legal notices: license, copyright, and any other legal details.
Writing the "sales pitch" up front forces me to be crystal clear about why this project should exist and why developers should use it. The mere act of writing full sentences to describe the project often changes it for the better: you understand it better, develop new ideas, and uncover potential problems. It's also a great prioritization tool: anything in the "sales pitch" is a must-have!
The "quick examples" and "quick start guide" force me to think through the key use cases from the user's perspective. I've found that doing this before writing any code - before being bogged down in implementation details and tight deadlines - leads to much cleaner APIs and designs. Remember: programs should be written for people to read, and only incidentally for machines to execute (SICP).
In "further documentation", I create an outline of the pieces that will need detailed documentation, to be done later. "Project organization" lets me figure out who will work on the project and the coding practices. "Legal notices"... well, may as well get those out of the way too.
Once you have this basic README in place, you have a document that's useful for discussion, design reviews, dividing up the work, and project planning. As you work on the project, frequently check back with the README to make sure you're still on track. Also, incrementally updating the README and the "further documentation" as you go means all your documentation will be done when the code is done, which is a much more pleasant experience than having to rush through documenting everything last minute.
For more info, check out the following:
Why wouldn't you want to think about how classes interact? Why is that a bad thing? I actually think about the interactions before I even know what the classes are. That way the classes identify themselves.
You should have some idea of what you plan to do before you write the code. The issue always is how do you keep what you've coded in synch with what you've written? Some say don't try, others say forget the initial docs and keep up the comments. Of course the code is always the canonical source. The issue then becomes whether it is worth the effort to document what the code does for those who come later or use the code. Anyone can figure out what a function does. The writer's job is to help someone understand in 5 minutes what anyone can figure out in an hour. Add up the deltas and determine your path.