January 30th, 2008
Becoming a Better Programmer
The Internet’s software development stratosphere is forever spewing forth lists of N steps to becoming a better programmer. Among those touting their personal take on the road to code nirvana, I’ve noticed a single step that seems to be almost ubiquitous: read other people’s code. Since reading the perfectly distilled common sense of Steve McConnell’s Code Complete a few years back, I’ve always considered this to be a stylistic thing: when you read other people’s code, you do so to improve your own aesthetic.
McConnell’s book encouraged readers to (and I’m paraphrasing here) take what they found in the code of others and evaluate it. I took that at face value at the time (and I have ever since), and used others’ code as a judge of good style. If somebody’s code was easy to read, I’d integrate elements of their style into my own. If the code was … uh … labyrinthine … well, I’d tend to lean away from the styles in play. Easy.
The Goal is to Grok
Some time ago it struck me that maybe, after all this time, I’ve been quite wrong about what I should be focusing on when looking at others’ code. I think the one thing I’ve dearly undervalued in all my years of programming is this: reading code is just a step on the long path to understanding it. That is, don’t strive to merely “read” the individual statements in a source file. Develop a general understanding of how the system fits together as a whole and at multiple levels of granularity. My narrow-minded approach was never going to be nearly as effective as truly understanding more complex code bases.
Style is doubtlessly important, but there’s more to be gained from reading code than merely what works stylistically. There is really so, so much more to take from the nitty gritty of the implementation details of even the most poorly constructed software systems. By all means, discard the stylistic abortions of programmers who don’t care for aesthetics or code of a language which doesn’t necessarily lend itself to the problem at hand. But damn it, play with it. Become familiar with how all the little ugly parts of a system fit together. Step through the interesting bits in a debugger, watch the data move around, watch the state changes. Read the documentation back to front. Know the libraries, know the subsystems. Come to know the code, the software and the domain at a level you never thought possible when you first started playing with it. Understand it! Again, I guarantee you’ll learn as much from all the bad code you encounter as you do from the good – but only if you take the time to fit the pieces together.
Finding direction
Having said that, slogging through code for software you find mundane or boring is going to both test your patience and limit your potential for learning something new. Pick an open-source project (or two) that interests you and spend a few weeks or months tinkering with it. For example, you might be interested to learn how Pidgin/Gaim protocols and plugins are handled internally, or how JEdit’s editor component is rendered. How does Glade work? Delve into the source code behind your favourite libraries like wxWidgets, GTK+ and Qt/KDE and see how user interface libraries are built. How do Mono’s C# compiler and Python’s internals tick? How do you implement a robust HTTP server like Apache?
There’s a lot of code out there, so much to learn and a lot of smart people. Don’t be afraid to get your hands dirty with non-trivial projects, even when it’s initially frustrating to understand the basics of an unfamiliar domain. Understanding complex software systems will make you a better programmer and help you grow as a professional.
Categories: Software Development |
1 Comment
January 24th, 2008
I just upgraded my wordpress installation and set up a new theme. Please let me know if you encounter any issues with the site.
Categories: Uncategorized |
No Comments
January 23rd, 2008
I’m still somewhat in holiday mode, so this entry is probably going to feel a little cheap for those of you following my more technical posts. I’m a big fan of GTK+ for user interfaces. If you don’t have the option or desire to use the Java platform and Swing, GTK+ is one of the better cross-platform user interface toolkits out there.
It’s high-level enough that it is easy to build quick, effective GUIs but low-level enough not to get in your way when you need to start messing around at the pixel level. GUIs can be built by hand using code, or designed using Glade and exported to an XML document to be loaded at runtime by any GTK+ binding. Currently it runs on Windows and Linux (the toolkit actually has its roots in GNOME) and has bindings for most popular programming languages. The only major downer is that Mac users are left out in the cold unless they go to the (herculean) effort of getting X11 up and running.
All the little differences between the various GTK+ bindings out there tend to get my goat when I move from one language to another. You would think that a GTK+ example in C could easily be translated to other languages without referencing documentation right? For one reason or another, the GTK+ bindings for other languages tend to diverge from the pleasant consistency of the C API to varying degrees. This post is all about those little differences that crop up even in the simplest applications: GTK’s take on “Hello World” in a few different languages.
C
C, being the language GTK+ is actually written in, is probably the most consistent with function naming across the different objects … the GTK_* and G_* macros are quite ugly though.
#include <gtk/gtk.h>
int main (int argc, char **argv) {
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello, World");
g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
gtk_widget_show_all (window);
gtk_main();
return 0;
}
C#/Mono
GTK# adds stuff like the Application object and delegates to produce a “Hello World” example I had to go digging around in documentation for. Not too bad on the whole, though.
using Gtk;
using GtkSharp;
public class HelloWorld {
public static void Main(string[] args) {
Gtk.Window window = new Gtk.Window();
window.Title = "Hello, World";
window.DeleteEvent += delegate { Application.Quit(); };
window.ShowAll();
Application.Run();
}
}
Ocaml
The Ocaml bindings diverge from the original C API much more so than the other languages listed here, most likely due to design decisions that had to be made to provide a C binding to a functional language. My only real grumble is the inconsistency with window#event#connect vs window#connect. I’m guessing there was a technical reason for that, but it still irks me every time I see it.
let delete_event evt = false
let destroy () = GMain.Main.quit ()
let main () =
let window = GWindow.window in
let _ = window#set_title "Hello, World" in
let _ = window#event#connect#delete ~callback:delete_event in
let _ = window#connect#destroy ~callback:destroy in
let _ = window#show () in
GMain.Main.main ()
;;
let _ = main () ;;
Perl
Although I find writing Perl to be painful for everything but processing text files in a terminal, I found the Perl GTK bindings to be relatively straightforward.
use strict;
use Gtk2 '-init';
my $window = Gtk2::Window->new;
$window->set_title("Hello, World");
$window->signal_connect('delete-event', sub { Gtk2->main_quit; });
$window->show_all;
Gtk2->main;
Python
I’m more familiar with PyGTK than with other bindings, so this was a snap. Why they chose GtkObject.connect over GtkObject.signal_connect is a mystery and the pygtk.require(’…’) crap is a little weird, but aside from that there should be nothing surprising here (this is a good thing!).
import pygtk
pygtk.require('2.0')
import gtk
window = gtk.Window()
window.set_title('Hello, World')
window.connect('delete-event', gtk.main_quit)
window.show_all()
gtk.main()
Ruby
RubyGNOME provides a GTK+ binding for Ruby. Take an almost 1:1 port of the C API, take away the ugly casting macros, mix in closures for handling signals and Ruby really is one of the nicest ways to get intimate with GTK+.
require 'gtk2'
window = Gtk::Window.new
window.title = 'Hello, World'
window.signal_connect(:delete-event) { Gtk.main_quit }
window.show_all
Gtk.main
That’s all for now. There are many more language bindings for GTK+ out in the wild for languages like Lisp/Scheme, C++, Haskell and Erlang. If you’re looking around for a GUI toolkit, be sure to give GTK a go. There’s plenty of documentation available for all the bindings listed here, often with some very detailed and easy to follow tutorials.
UPDATE: Miguel and she suggested some changes to the C#/Mono and RubyGNOME examples.
UPDATE 2: Aristotle suggested an easier way to initialize the Perl GTK bindings.
Categories: C, GTK, Ocaml, Python, Ruby, Software Development |
11 Comments