A Django site.
August 20, 2008

Hans Fugal
no nic
The Fugue :
» MVC

A friend of mine is struggling to grok the MVC pattern. I remember when I first tried to grok it how frustrating it was. There wasn't one final "a-ha" moment when I grokked it, but one day I looked back and realized I understood it. At that moment it dawned on me just how amazingly silly this whole process is. MVC is not some magical formula that if you implement it will endow your application with magical powers. It is a paradigm. A worldview of application programming. Once you get it, you realize that everything is MVC. It's just that some of it is cleaner MVC than others. The trick is in keeping the three components separate, but they're always there. My friend is still confused after an IM conversation, because his preconceptions about the computer and probably his desire to find that something different are getting in the way. So let's use a non-computer analogy.

You've seen The Hitchhiker's Guide to the Galaxy, right? Of course you have. If not, I'll wait.

Ok, remember the scene where Trillian is at a desk with a Vogon who asks her here home planet? She says it's Earth, the Vogon can't find Earth, she tells her where it is, she says it was destroyed, and does Trillian perhaps have another home planet? Yeah, I don't do it justice. Ok, so Trillian is the user. The Vogon is the controller, the computer is the database, and there are several views in play. The first view is the Vogon telling Trillian that it was destroyed. The second view is when she turns the computer monitor around so the incredulous Trillian can see for herself the video of the Earth being blown up. The third view is authorization with Zaphod's autograph.

The nice thing about MVC, see, is that the model has no clue about the view or the controller. It just provides an interface for the controller to get and change the model's information. Likewise the view is pretty dumb. It accesses the model, or a snapshot thereof. But it doesn't make decisions. It just displays stuff. The controller is the "brains" behind the operation. It coordinates showing the user the correct view of the bit of the model that the user wants to see. It handles updating the model with new information.

Ok, still confused? Let's try another. This time the controller is your CD player. The model is a CD. The view is your amplifier and speakers, or whatever else you have plugged into the audio outputs. An oscilloscope maybe? You the user push buttons and the controller changes the view. The model and view are obviously decoupled. But this analogy isn't perfect because the view isn't accessing the model directly, as is usually the case in MVC, but is being spoonfed the data by the controller. In my opinion this distinction is irrelevant, because the whole point is to achieve decoupling and whether the controller provides the decoupleable data or the view fetches it directly from the model is irrelevant to decoupleability, as we can see with this real-world example. Also this analogy might be better if we think back to cassette tapes which allow us to change the model (by recording), whereas the CD is read-only.

Ok, so now let's bring it to the computer domain. The model is a database. Actually it's usually a wrapper around a database (which is in turn usually decoupled too), like ActiveRecord or your homegrown classes. You almost always write classes, because representing "stuff" is what OOP is good at. It doesn't have to be a real database of course, it could be just objects in RAM or a flat file. The key word for models is data.

Now, the view is almost always entirely contained in the GUI toolkit you're using. The toolkit writers figured out all that boring stuff that lets you draw widgets and pack them together in a dialog box, etc. All that stuff you wouldn't want to do manually is the view. You may have some view code which deals with setting up the widgets, etc. The view may not even be visual—it might be a file on disk or sound coming out the speakers. The key word for views is render.

The controller is everything else. Those GUI toolkits usually have some controller help too, since GUIs are interactive views and the events that the controller reacts to are coming from the view, in a sense. When you write callbacks, you're writing the controller. The controller figures out what to do in response to various events. It decides how to manipulate the views. It tells the views what data to display. The key word is event, and maybe coordination.

So you see, if you're using a toolkit or framework you're already sort of doing MVC. The real litmus test can be boiled down to the following questions. If you can answer yes to all of them, then you're doing MVC. If not, you're not.

  1. Could I render different views without duplicating control code?
  2. Could I use my model code unchanged in a completely different application, and could I switch databases (if you have a persistent model) like I switch CDs?
  3. Is my model ignorant of the rest of the program?
  4. Do I feel like MVC is making my life easier, not harder?
  5. Have I sent chocolate to Hans recently?

There you have it. I hope it was helpful.

March 26, 2008

Hans Fugal
no nic
The Fugue :
» QCad on Leopard

I finally got around to building QCad on OS X Leopard. There are two main hurdles: getting Qt3 to build and getting QCad to build.

At first I tried building Qt3 with macports, but building QCad was a royal pain with the X11 version of Qt3 on OS X, for whatever reason. So I tried to install the qt3-mac MacPorts package, but that failed. So I was on my own building Qt3.

This patch will allow Qt3 to build on Leopard, by following the instructions in the INSTALL file. Here's the diffstat:

 config.tests/mac/mac_version.test |    2 +-
 src/kernel/qcursor_mac.cpp        |    4 ++++
 src/kernel/qt_mac.h               |    2 +-
 src/tools/qglobal.h               |    5 ++++-
 4 files changed, 10 insertions(+), 3 deletions(-)

I put it in /Developer/qt3, and I wrote a script to source on demand rather than setting QTDIR and friends in my .profile or .bashrc, since I more often want Qt4 than Qt3. I configure with -static, so applications like QCad are built with Qt3 statically, which just makes things work better.

QCad needs a patch as well:

Index: qcad-2.0.5.0-1-community.src/mkspecs/defs.pro
===================================================================
--- qcad-2.0.5.0-1-community.src.orig/mkspecs/defs.pro  2008-03-26 08:46:25.000000000 -0600
+++ qcad-2.0.5.0-1-community.src/mkspecs/defs.pro       2008-03-26 08:46:48.000000000 -0600
@@ -1,6 +1,6 @@
 # $Id: defs.pro 606 2004-12-25 03:08:40Z andrew $
-QMAKE_CXXFLAGS_DEBUG += -pedantic
-QMAKE_CXXFLAGS += -pedantic
+#QMAKE_CXXFLAGS_DEBUG += -pedantic
+#QMAKE_CXXFLAGS += -pedantic

 win32 {
   QMAKE_CFLAGS_THREAD -= -mthreads
Index: qcad-2.0.5.0-1-community.src/scripts/build_qcad.sh
===================================================================
--- qcad-2.0.5.0-1-community.src.orig/scripts/build_qcad.sh     2008-03-26 08:46:06.000000000 -0600
+++ qcad-2.0.5.0-1-community.src/scripts/build_qcad.sh  2008-03-26 08:46:49.000000000 -0600
@@ -30,7 +30,7 @@ then
     export MAKE=gmake
     echo "Platform is Solaris"
     platform=solaris
-elif [ "x$OSTYPE" == "xdarwin8.0" ]
+elif [ "x$OSTYPE" == "xdarwin8.0" -o "x$OSTYPE" == "xdarwin9.0" ]
 then
     export MAKE=make
     echo "Platform is Mac OS X"

Then do

cd scripts
./build_qcad.sh notrans

It will complain about not finding qm/*.qm, but that's a nonfatal error. QCad.app will be in the qcad directory, ready for your use.

I built this on an Intel MacBook running Leopard. If you think that matches your setup, you're free to download my QCad.app and avoid building both Qt3 and QCad.

» MacPorts QTDIR

If I had a nickel for every time I had to scour the web to figure out the right setting for QTDIR on {Debian,Ubuntu,OS X}…

On OS X, if you installed the qt3 package, then the proper setting is QTDIR=/opt/local/lib/qt3. I wrote this little script to source before commencing building a Qt3 project:

#QTDIR=/usr/local/Trolltech/qt-mac-free-3.3.7
#QTDIR=/Developer/qt
QTDIR=/opt/local/lib/qt3
PATH=$QTDIR/bin:$PATH
DYLD_LIBRARY_PATH=$QTDIR/lib:$DYLD_LIBRARY_PATH

export QTDIR PATH DYLD_LIBRARY_PATH

September 4, 2007

Hans Fugal
no nic
The Fugue :
» QtRuby Arrives

I've extolled the virtues of QtRuby before. As GUI toolkits go, Qt is the best (IMHO) and as languages go Ruby is tops (again, IMHO), so naturally QtRuby has potential. QtRuby's biggest stumbling block in the past has been installation. Easy on Linux, but deep voodoo on OS X and perhaps even worse in Windows. That has finally changed.

qt4-qtruby now uses a cmake-based build system. I installed Qt4 from source on my MacBook, then followed the instructions to install qt4-qtruby and gave it a spin. Everything worked perfectly out of the box.

I can't speak for Windows, but QtRuby on Linux and OS X is now practical. (It has been since June or perhaps earlier, but I just got around to trying it out.) Celebrate!