A small web application is relatively easy to understand. It does
less stuff. That makes the application easier to understand: the UI
(or REST web service) is smaller, and the codebase too.

But sometimes we need larger web applications. Morepath offers a
number of facilities to help you manage the complexity of larger web
applications:

Morepath lets you build larger applications from multiple smaller
ones. A CMS may for instance be composed of a document management
application and a user management application. This is much like how
you manage complexity in a codebase by decomposing it into smaller
functions and classes.

Morepath lets you factor out common, reusable functionality. In
other words, Morepath helps you build frameworks, not just
end-user applications. For instance, you may have multiple places in
an application where you need to represent a large result-set in
smaller batches (with previous/next), and they should share common
code.

There is also the case of reusable applications. Larger applications
are often deployed multiple times. An open source CMS is a good
example: different organizations each have their own installation. Or
imagine a company with an application that it sells to its customers:
each customer can have its own special deployment.

Different deployments of an application have real differences as every
organization has different requirements. This means that you need to
be able to customize and extend the application to fit the purposes of
each particular deployment. As a result the application has to
take on framework-like properties. Morepath recognizes that there is a
large gray area between application and framework, and offers support
to build framework-like applications and application-like frameworks.

The document App Reuse describes the basic facilities Morepath
offers for application reuse. The document
Organizing your Project describes how a single application
project can be organized, and we will follow its guidelines in this
document.

This document sketches out an example of a larger application that
consists of multiple sub-projects and sub-apps, and that needs
customization.

Our example large application is a code hosting site along the lines
of Github or Bitbucket. This example is a sketch, not a complete
working application. We focus on the structure of the application as
opposed to the details of the UI.

We could try to implement settings, issues and wiki as views on
repository, but these are complicated pieces of functionality that
benefit from having sub-URLs (i.e. issues/12 or
...wiki/mypage), so we model them using paths as well:

This approach works perfectly well, and it’s often the right way to
start, but there are some problems with it:

The URL patterns in the path are repetitive; for each sub-model
under the repository we keep having to repeat
{user_name}/{repository_name}.

We may want to be able to test the wiki or issue tracker during
development without having to worry about setting up the whole outer
application.

We may want to reuse the wiki application elsewhere, or in multiple
places in the same larger application. But user_name and
repository_name are now hardcoded in the way to get any sub-path
into the wiki.

We could have different teams developing the core app and the wiki
(and issue tracker, etc). It would be nice to partition the code so
that the wiki developers don’t need to look at the core app code and
vice versa.

You may want the abilitity to swap in new implementations of a issue
tracker or a wiki under the same paths, without having to change a
lot of code.

We’re going to show how Morepath can solve these problems by
partitioning a larger app into smaller ones, and mounting them.

The code to accomplish this is more involved than simply declaring all
paths under a single core app as we did before. If you feel more
comfortable doing that, by all means do so; you don’t have these
problems. But if your application is successful and grows larger you
may encounter these problems, and these features are then there to
help.

Let’s split up the larger app into multiple sub apps. How many
sub-apps do we need? We could go and partition things up into many
sub-applications, but that risks getting lost in another kind of
complexity. So let’s start with three application:

path='{user_name}/{repository_name}/issues': We are mounting it
on that path. All sub-paths in the issue tracker app will fall under
it.

app=IssuesApp: We are mounting IssuesApp.

The mount_issues function takes the path variables user_name
and repository_name as arguments. It then returns an instance of
the IssuesApp. To create one we need to convert the
user_name and repository_name into an issues id. We do this
by looking it up in some kind of database.

The variables function needs to do the inverse: given a
IssuesApp instance it needs to translate this back into a
repository_name and user_name. This allows Morepath to link
to a mounted IssuesApp.

We can now reuse the issue tracker app in the sense that we can mount
it in different apps; all we need is a way to get issues_id. What
then if we have another Python project and we wanted to reuse the
issue tracker in it as well? In that case it may start sense to start
maintaining the issue tracker it in a separate Python project of its
own.

We could for instance split our code into three separate Python
projects, for instance:

myproject.core could have an install_requires in its
setup.py that depends on myproject.issues and
myproject.wiki. To get IssuesApp and WikiApp in order to
mount them in the core, we would simply import them (for instance in
myproject.core.app):

In some scenarios you may want to turn this around: the IssuesApp
and WikiApp know they should be mounted in CoreApp, but the
CoreApp wants to remain innocent of this. In that case, you would
have myproject.issues and myproject.wiki both depend on
myproject.core, whereas myproject.core depends on nothing. The
wiki and issues projects then mount themselves into the core app.

Now that we have separate projects for the core, issue tracker and
wiki, it becomes possible for a team to focus on the wiki without
having to worry about core or the issue tracker and vice versa.

This may in fact be of benefit even when you alone are working on all
three projects! When developing software it is important to free up
your brain so you only have to worry about one detail at the time:
this an important reason why we decomposition logic into functions and
classes. By decomposing the project into three independent ones, you
can temporarily forget about the core when you’re working on the issue
tracker, allowing you to focus on the problems at hand.

Imagine a scenario where a particular customer wants exactly core
app. Really, it’s perfect, exactly what they need, no change needed,
but then ... wait for it ... they actually do need a minor tweak.

Let’s say they want an extra view on Repository that shows some
important customer-specific metadata. This metadata is retrieved from
a customer-specific extra database, so we cannot just add it to core
app. Besides, this new view isn’t useful to other customers.

What we need to do is create a new customer specific core app in a
separate project that is exactly like the original core app by
extending it, but with the one extra view added. Let’s call the
project important_customer.core. important_customer.core has
an install_requires in its setup.py that depends on
myproject.core and also the customer database (which we call
customerdatabase in this example).

Now we can import CoreApp in important_customer.core‘s
app.py module, and extend it:

frommyproject.core.appimportCoreAppclassCustomerApp(CoreApp):pass

At this point CustomerApp and CoreApp have identical
behavior. We can now make our customization and add a new JSON view to
Repository:

You can now run CustomerApp and get the core app with exactly the one
tweak the customer wanted: a view with the extra metadata. The
important_customer.core project depends on customerdatabase,
but myproject.core remains unchanged.

We’ve made exactly the tweak necessary without having to modify our
original project. The original project continues to work the same way
it always did.

Morepath lets you extend any directive, not just the view
directive. It also lets you override things in the applications you
extend. Let’s say the important customer wants exactly the original
wiki, with just one tiny teeny little tweak. Other customers should
still continue to use the original wiki.

We’d tweak the wiki just as we would tweak the core app. We end up
with a TweakedWikiApp:

frommyproject.wiki.appimportWikiAppclassTweakedWikiApp(WikiApp):pass# some kind of tweak@TweakedWikiApp.json(model=WikiPage,name='extra_info')defpage_extra_info(self,request):...

We want a new version of CoreApp just for this customer that
mounts TweakedWikiApp instead of WikiApp:

A morepath.App subclass does not need to be a full working web
application. Instead it can be a framework with only those paths and
views that we intend to be reusable.

We could for instance have a base class Metadata and define some
views for it in the framework app. If we then have an application that
inherits from the framework app, any Metadata model we expose to
the web using the path directive automatically gets its views
supplied by the framework.

Since App extends Framework, all documents published this way
have a metadata view automatically. Apps that don’t extend
Framework won’t have this behavior, of course.

As we mentioned before, there is a gray area between application and
framework; applications tend to gain attributes of a framework, and
larger frameworks start to look more like applications. Don’t worry
too much about which is which, but enjoy the creative possibilities!

Note that Morepath itself is designed as an application
(morepath.App) that your apps extend. This means you can
override parts of it just like you would override a framework app! We
did our best to make Morepath do the right thing already, but if not,
you can customize it.