Keeping Your Model Reusable

Introduction

Catalyst's MVC (Model/View/Controller) structure gently guides us to
separate the code handling the various aspects of our application, without
insisting that we do the right thing.

Good advice, and an oft-heard refrain, is to avoid creating fat controllers.
What makes a controller fat? The inclusion of code concerned with doing
the work your application is built to do. If you were building an app to
translate text from one language to another, the code performing the
translation logic should be neatly wrapped up in a model, not stuck in
the controller.

This approach improves your life in a variety of ways. The resulting code
is easier to understand, easier to debug, and easier to test. Taken one
step further, it also makes it trivial to re-use. Let's see how this can
work by looking at the example of Gitalist.

Gitalist

Gitalist began as a project to implement gitweb (the Git web viewer) as a
Catalyst application. While the main aim was to produce a web application,
we knew that we'd want to be able to write other, non-web tools that had
access to the same functionality.

With this in mind, we needed our Catalyst model (Gitalist::Model::GitRepos)
to serve as a thin layer of glue connecting our plain model (Gitalist::Git)
into the application. Fortunately, this is incredibly easy.

The Plain Model

First, we implement the plain model. In Gitalist, we needed to represent
both an individual git repository (a Project), and the directory containing
a collection of Projects (a Repo; though we don't like this class name, and
it changes in the next release).

While the actual code is more complex, there's no trace of Catalyst in
sight - exactly as it should be! This class can readily be used in
other applications, and is very easy to test.

The Catalyst Model

If all our actual logic is contained in the plain model, it follows that
our Catalyst model will contain none. Sure enough, we do the minimum
amount of work required to create an instance of Gitalist::Git::Repo.

The Controller

With the model in place, the controller is straightforward. If we've done
everything right, we shouldn't even notice that our model exists outside
Catalyst. An action like this will do just what you expect: