The following is for every one who’s had to spend all their working hours fighting metaphorical fires instead of fulfilling their own initiatives.
The month behind her had gone, leaving nothing but the blank of dead time. It had gone into the planless, thankless work of racing from emergency to emergency, of delaying the collapse of a railroad – a month like a waste pile of disconnected days, each given to averting the disaster of the moment. It had not been a sum of achievements brought into existence, but only a sum of zeros, of that which had not happened, a sum of prevented catastrophes – not a task in the service of life, but only a race against death.
Ayn Rand, Atlas Shrugged
I’m not a huge Rand fan but, that paragraph resonates with my experiences in manufacturing and software maintenance.
Tell me how and, I’ll forget. Tell me why, and I’ll remember – sablobsimus
This Google Tech Talk is well worth the hour it takes to view the entire presentation.
Here are my notes:
- Start with a really small spec. Small specs are more likely read by a wider audience. A set of interfaces in a programming language allow uses-cases to be coded up immediately. Writing to the API increases confidence in the API design.
- Write to the API early in the process and continue to do so throughout the API’s development. These become example programs.
- Same as above for SPI’s but, even more so. Need to actually write to the evolving SPI three times, with three different provider implementations to create a good SPI.
- Don’t attempt to make every stakeholder 100% satisfied. Don’t let 1 stakeholder be 0% satisfied.
- Expect the API to evolve. So start small and, don’t box yourself in.
- Important rule #1: When in doubt, leave it out (of the API). Applies to types, methods and parameters. The API is going to evolve, you will likely get a chance to add it later.
- Use idioms of the platform’s own APIs so developers familiar with the platform will more easily learn your API.
- Warning sign: Classes, methods, fields etc… that are hard to name. Indicates a lack of clarity in the design.
- Re-using interfaces is important way to make the conceptual weight (learning overhead) less.
- Implementation shouldn’t leak in to the API. Implementation visibility will lead to undesired coupling.
- Exceptions cited as a possible example of how implementation details may leak.
- Don’t specify things you don’t need to.
- Leaks like this can occur when implementing an interface under time pressure.
- Minimize accessibility of methods, fields, classes, interfaces. Minimized accessibility will reduce coupling.
- Names matter.
- Poorly named items confuse programmers and cause trips to documentation.
- Example code should read like prose.
- Documentation! Essential for your API to be (re)used:
- Specify the design by contract stuff: preconditions, post conditions and side effects
- Specify the state space of mutable objects (see minimize mutability)
- For parameters: specify ownership: Does caller relinquish ownership of the parameter?
- Format and units of parameters and return values should be specified.
- Performance: usually good API design leads to good performance. (limiting mutability is an example)
- Minimize Mutability.
- Completely immutable objects are thread safe
- Fewer objects created
- If you can’t make it immutable, make it as immutable is possible – limit the state-space of the class.
- Subclass only when there is a “is-a” relation
- Inheritance violates encapsulation so, take care. Document when sub-classing is expected. In Java, use ‘final’ when it is forbidden.
- Document “self use case” of a class.
- fragile base class problem
- Important rule #2: Don’t make the client do what the module could do itself!
- promotes bug prone, boiler-plate code
- Principle of Least Astonishment: Methods should do what their names suggest. No decoys.
- Fail fast:
- Static typing to catch errors at compile time
- At runtime, fail on first method call (not some time later)
- Every thing made available as a String, should be made available as more specific types to prevent clients from parsing string. If they write parsing code, the string format is now a de facto part of specification.
- Overload with care:
- Ambiguous overloading is bad. Better to have implementation do a run time type check and then do the right thing rather than leaving possibility of an insufficiently down-cast parameter causing the wrong method to be invoked.
- Sometimes, just making a uniquely named method is better.
- Return Types and Parameters
- Use interfaces for inputs – flexibility
- Avoid Strings – they are cumbersome and slow.
- Use consistent parameter names and parameter ordering across methods, across the API, and even across the platform
- Short parameter lists – break up methods or, use helper class to hold many parameters
- Avoid special return values (like null) when some other object (empty collection for example) would be easier for the caller.
To meet a 1 hour time limit, the presenter skipped over some material on exceptions that I would love to have heard.
[kml_flashembed movie="http://video.google.com/googleplayer.swf?docid=-3733345136856180693" width="400" height="326" wmode="transparent" /]
The other night I watched this tutorial:
[kml_flashembed movie="http://www.youtube.com/v/D16Egf419YY" width="425" height="350" wmode="transparent" /]
…and it inspired me to create this: