Thursday, June 24, 2010

Rico's Law of Documentation

Rico's Law of Documentation:
Trying to make a document that's self contained and explains everything someone needs to know about a system is doomed to failure.

Don't accuse me of being anti documentation here, because I'm not. Documentation is very important. The important thing is to not expect unreasonable things from documentation, the people trying to write it, or the people trying to read it. Think about the capabilities of an ideal person or team that is capable of producing clear, conscise, perfect and thorough documentation. Think about how much time they need to produce that documentation. Now think about what those people could accomplish if they were working on the product instead of churning out documents. Or think about what your organization could do with the money you spent producing these documents.

Let's say you have a fairly complex system that's been running for a while, and you want to bring in a new team or a new developer. You want to hand this new developer a document that describes the system, how it works, where we want to go, what its problems are, how we might solve those, and so on. Because you're a disciplined development team, you want to have good documentation. And you want to be able to hand this document over to the new people and have them ready to rock and roll on the project after reading the document.

It ain't gonna happen. If you do try to make it happen, you're going to waste a lot of time and effort. That's because either the effort will succeed, in which case you've used your best talent spending a tremendous amount of time to produce something that's obsolete by the time it's done. Or else it will fail, and you've wasted time that way. Or a mixture of both. A project where even success is a failure is a good kind of project to avoid, and there are many such endeavors available in software engineering.

Documentation is not useless. The problem is that for almost all projects, the effort involved in producing documentation that fulfills the lofty goal of being self-contained and explaining everything well is not attainable using a level of effort that is worth spending. Of course there are exceptions to this rule of not trying to document overmuch, such as systems that don't change
much or have a whole lot of engineers working on them. But for typical projects, too much documentation is a fool's errand. There area couple of reasons for this:

1. The volume of info you need to communicate is immense. For a reasonably complex system, the size of this document would be comparable to a typical complete book about a programming language. You probably have a book about a programming language on your bookshelf in sight of you right now. Look at that book and think about it. Everything that book does, your document is going to need to do. It starts from step zero, talks about the basics first-- they've put a lot of thought in to how to structure and sequence the information so that it comes in digestible chunks, where each part is understandable based on the information that has arrived before. It'll need lots of examples and diagrams. Most people learn better from doing than from reading, so it'll need lots of examples and exercises that the reader can execute.

Anyone capable of actually doing this kind of instructional design is one of your best people. Probably more than one of your best people, who will need to collaborate in order to get the right skillset together at the same time. Or more likely still, you don't even have people that can be reasonably expected to do well at this. But if you do have such people-- Think of what they could do to your system if you let them actually do real work. But it gets worse.

2. The document won't accomplish as much as you hope. How many times have you seen huge documents that nobody ever read? Maybe it's because the document was too big, there wasn't time to read it. Maybe it's because the document was too small, it wasn't complete enough. Maybe it was overwhelming. There's a million reasons why people don't read documents or why when they do it's not all that enriching. These reasons have to do with deficiencies in the reader, the document, or the writer, or difficulties and complexities in the subject matter itself.

A system that works perfectly, and whose code is simple and understandable, and doesn't need further attention: such a system probably doesn't need a whole lot of documentation anyway. So spend that time making the system work, making it trouble free, making it simple and understandable.

Documentation is a vital part of many projects, but it's not an end unto itself. Keep the docs the as small as possible, and keep your people moving the product forward.

Tuesday, February 26, 2008

How to Rip mp3's in Ubuntu 7.10

Here is the easy version:

sudo apt-get install gstreamer0.10-plugins-ugly-multiverse

Then start up the pre-installed CD Juicer application. Go to Edit/Preferences, you will now see an mp3 option there.

Note that I already had lame installed, so you might need to do that (sudo apt-get install lame).

Monday, February 18, 2008

MonoTone with FastAGI

I'm doing a lot of IVR work with MonoTone using C# under Mono deployed to Linux. I used the MonoTone library, and implemented by own FastAGI library. I'm considering releasing this as open source, but I'm not sure if anyone else would be interested. I realize there's another C# library out there, but I didn't like it much.

Mono performance with Timers

Am I just imagining things, or does a basic C# Mono application that uses Timers "leak" CPU time? I have this application that spends most of its time idle. I added in a part that triggers a timer once per day. Now the application twiddles away tiny bits of CPU time from 0.3% to 1% pretty much continuously. After a few days, it's got many minutes of CPU time accumulated.

Normally I wouldn't worry about it. But this application is running on a machine that uses Asterisk, and voice quality is of paramount importance. So I want that machine running as lean as possible.

Update: I found that I had a
#define TRACE
in my code, because I'm using a trace listener for logging. The .NET docs say that you need a #define TRACE for trace listeners to work. Turns out, you really don't. Trace listeners still work without that. And for some reason, the application takes a lot less CPU time without that, but still works.

Don't Catch Exceptions Overzealously

Software Lesson learned today: only catch exceptions you expect.
Let’s say you have a method called UserFind(userid) that looks for a user and throws an exception if not found. Don’t do this:
Try
{
User x = UserFind(userid)
}
catch
{
showError(“User not found”);
}

If something funny happens, like your database changes a column name, then you’ll never know what happened—it’ll just say user not found.
While it’s more work, you really need to create a DataNotFoundException and throw that in the UserFind.
And make it like this:
Try
{
User x = UserFind(userid)
}
catch (DataNotFoundException)
{
showError(“User not found”)
}

This way if you change a column name, you’re catching a DataNotFoundException. But if you get a SqlException, you will let it pass and crash the application.
“OMG, I don’t want my application to crash!” Well, of course you don’t. However, if someone changed a column name, you’ll find out about it a and find out the cause lot quicker in testing this way. Besides, your application shouldn’t crash anyway, it should just be crippled for that part of your program. And it already was anyway, you were just hiding the fact.

I really already knew the “correct” way to do exceptions was to make small grained exceptions and filter this way. But it just seemed like so much extra typing that I typically didn’t do it. And really I would like it if I could declare the constructor that takes a string for the exception with less boilerplate repetitive code… Ruby style metaprogramming would be great for this. I’d just say something like “declare_exception DataNotFoundException, DataException”. But then Ruby’s deal with not automatically calling the base class constructors really ticks me off…

Heap Buddy with Mono on Ubuntu

I had some memory leaks going on in a C# application, and wanted to dump the heap objects the way I used to in .NET under Windows. Here are notes of what I had to do to get Heap-Buddy working with Mono under Ubuntu 7.10:

mono c# heap dump
you want heap shot from here http://www.mono-project.com/HeapShot
to compile I needed to install:
sudo apt-get install libglib2.0-dev
sudo aptitude install subversion nant mono mono-gmcs libmono-microsoft8.0-cil libmono-system-runtime2.0-cil
sudo mv /usr/local/lib/libmono-profiler* /usr/lib

mono –profile=heap-buddy:x.out datingline.exe -a
heap-buddy x.out types

Legacy Code

I've been thinking a lot lately about C++ and its level of "cleanness" and suitability for some new projects I'm doing. I ran into this quote from Bjarne Stroustrup about legacy code:

"Legacy code" is a term often used derogatorily to characterize code that is written in a language or style that (1) the speaker/writer consider outdated and/or (2) is competing with something sold/promoted by the speaker/writer. "Legacy code" often differs from its suggested alternative by actually working and scaling.