Automatic Class Diagram Generation

John Tsiombikas nuclear@mutantstargoat.com

13 December 2007

Some time ago, I needed a widget toolkit that would be able to draw widgets in an existing OpenGL window. However, I also needed it to be independent of the underlying graphics library, or event system, so I could use it in conjunction to both OpenGL, and another nameless 3D graphics API, that I was forced to use at the time for reasons I won't go into right now. Anyhow, to cut the long story short, I started writing one such toolkit from scratch.

I opted for a fully object-oriented design, such as I rarely do lately, because OOP really makes sense for widget toolkits, and used C++ for the implementation.

Before long, I wanted to show what I was doing, to the rest of the team working on the project, for which I was writing the toolkit. And decided I should visualize the class hierarchy, as a quick overview of the widgets and their relations.

I didn't want to have to learn how to use vector drawing programs just for this little thing, so my first thoughts went towards ditta. An excellent little hack, by Stathis Sideris, that turns ASCII diagrams of boxes and arrows into beautiful antialiased raster images.

However, it would be too tiresome, to manually create all those ASCII boxes representing my classes. I needed something more "automatic". Finally I remembered "dot", of the "graphviz" project. Another excelent program, that takes simple text files describing graphs, and again, turns them into images. Here's what a dot input file for my class diagram would look like:

digraph class_diagram {
    rankdir=BT;
    Label -> Widget;
    Button -> Widget;
    ... and so on ...
}

Now, people who know me, know that I'm a lazy person. I’d hate to have to maintain a separate file describing my classes, and I knew that it would go out of sync soon. Then it hit me, why don't I generate the dot input file from my source files? So, I added the following rule to my makefile:

diag_file = diag.ps

.PHONY: $(diag_file)
$(diag_file):
    echo 'digraph class_diagram {' >/tmp/cdiag.dot
    echo '    rankdir=BT;' >>/tmp/cdiag.dot
    for i in src/*.h; do grep class $$i | grep ':' | sed 's/class /    /' \
        | sed 's/: public/->/' | sed 's/ {/;/' >>/tmp/cdiag.dot; done
    echo '}' >>/tmp/cdiag.dot
    dot -Tps /tmp/cdiag.dot >$(diag_file)

This is far from perfect, as it depends on my coding style to work correctly, still fine for my purposes. Here's the output it produces:

class diagram


This was initially posted in my old wordpress blog. Visit the original version to see any comments.


Discuss this post

Back to my blog