This code is: ‘BAD’. This code is: ‘GOOD’
This article is part of the series [Everyday Code].
TL; DR;
When providing examples in developers documentation always add the bad example, but make it stupid clear that “this is a bad example and it should not be done like this, while this is a good example and it should be done like this!”
Too long; but I will actually read it.
We are copy/paste developers. We are fighting challenging problems on tight schedules with complex frameworks running on enormous stacks and we rarely use tools designed with ergonomics in mind. When we stumble on a problem we go for an internet search, copy the first result that looks like a solution and continue. (this is also my main mode of work with nginx. I love it, but it is always so much work to get this assets through a proxy, and this server was even designed for this.). Or AWS API…
Yet, we somehow manage to deliver software platforms and most of them are in a running state. Brilliant.
One thing that we are missing in the documentation is of course the understanding of the “why”. Why things are implemented like this? What were the considerations? Why it should not be implemented in different ways? You get this in a book, but you don’t have it in the documentation.
Most of the time of course we don’t have the time to enter into the details, but I would make the argument that the more we understand the underlying problem, the more fun it is and the more satisfaction that we can get from work. Because most of the time we just can get not satisfaction. (no reference intended, but here it is – https://youtu.be/EU1t1PqASuQ?t=47)
But this brings us to the problem. When developing a tutorial for how to use your framework should you include the bad examples along with the good?
Should you include the bad examples in the documentation?
This was an issue in the early stage of our Instruction Steps Framework developed at Axlessoft.com. As a proper framework it has documentation. As it is a framework it puts some boundaries and rules on what you should do. But we’ve tried to go one step further and describe why we are doing it like this.
I’ve found it rewarding to include information about why specific decisions were taken not only what are these decisions.
Example 1 – we’ve decided not to have a central object model on which all extension are based. A central object model would simplify a lot of things and is a lot easier for many developers, but it is less flexible.
Example 2 – we’ve decided that certain event methods could return Promises, but could also not. Now why would you do this to yourself is a really good question?
In these two and other examples I have taken the time to include proper documentation and tutorials on why we are implementing a feature like this. But I failed at one place. I was including both the bad and the good examples in the documentation.
Looks at the example below for iterations from the previous article. This is an example for iterating over trees.
anArray = node.getDescendants();
// here you have all the elements of the tree in anArray
// loop over the array
anArray.forEach((a)=> {
if(a.name.includes("1")) {
print a.getDescendants().length
}
})
Here is an example without getDescendants()
anArray = []
rootNode.traverse((node)=> {
anArray.push(node)
})
See what I did here. If you came to this article looking for ways to iterate over trees it is completely unclear what is good and what is bad. Writing it right here in the text as “the first example is bad”, “the second example is good” won’t help. Who is even reading this text? So you arrive at the article, get the first iteration that is “bad iteration”, copy it and paste it in your code.
The point is – it is valuable to include the bad examples as they give people the understanding why the good examples are good. But by including the bad example a large percentage of your readers will just copy paste the bad example and continue.
My solution
Mark your examples clearly in the code as “GOOD” or “BAD”. Not in the text. We are developers, we don’t read text.
// BAD EXAMPLE - because it uses a lot of memory
anArray = node.getDescendants();
// here you have all the elements of the tree in anArray
// loop over the array
anArray.forEach((a)=> {
if(a.name.includes("1")) {
print a.getDescendants().length
}
})
Again some text that no developer is ever reading, as it is in between the examples.
// GOOD EXAMPLE
anArray = []
rootNode.traverse((node)=> {
anArray.push(node)
})
See how clear this is. I dare any developer to now copy the bad example in their code. Hope this approach could help you in time of need.
Reply
You must be logged in to post a comment.