Lost in LoC


Google AppEngine and Separation of Concerns

Posted in Development,Google AppEngine,Python by Ryan Baldwin on October 25, 2009
Tags: , , ,

In the world of writing software there are 2 challenges every developer must face: how to keep your concerns separate, and how to survive the impending deadly boredom of writing all your data CRUD (Create, Update, Retrieve and Delete) functionality. There are a gazillion solutions out there for both. In the realm of functional isolation much has been written, studied, and practiced for separating your program’s concerns. You can adhere to various design patterns; you can establish a pattern and an engine to manage that pattern yourself; you can use one of the several freely available frameworks that already exist (such as Spring). This is good.

In the realm of CRUD management (and boy, is it a crappy job… ba-da-dum!) there’s a plethora of available frameworks for almost every language. These object persistence frameworks handle all the boring, lowdown, uninteresting CRUD functionality that developers loath (but which is a necessary evil). This is also good.

What’s bad, however, is the interoperation of these two challenges rarely seems “natural”. The reason is that object persistence frameworks can really mess with your separation of concerns. The domain classes you write can suddenly become the transport means in your data access layer, thus blurring the lines of what code goes where.

A week ago I started a new application that uses Google AppEngine. Google AppEngine provides an object persistence framework as part of its platform. It also provides a Model-View-Controller type of framework for writing all your web apps. From day one my colleague Kevin Pierce and I have struggled to determine how to separate domain logic from data logic. In AppEngine, your “onion” from the outermost layer to the innermost looks more or less like the following:

[Template] (html/js/css) -> [View] -> [Model] -> [DataStore]

The problem with the above onion is between the View and the Model. Without having something in between your views can (and will) become enormously bloated, full of miscellaneous helper modules, and will operate directly against the Model/Datastore, thus blurring the lines of responsibility in your application. This will eventually make your life a living hell. Kevin and I decided to throw in an intermediary layer between View and Model, called Domain, which houses all the business logic of our application.

[Template] -> [View] -> [Domain] -> [Model] -> [DataStore]

The idea is that the View layer will only ever directly interact with the Domain layer, and never directly against the Model layer. For example, if the View needs to retrieve a Person from the DataStore, instead of going directly using the Model, the View will ask the Domain for an object that’s responsible for retrieving a Person from the DataStore and interact with that object (a classic Factory). Because Python is a dynamic language, in which everything is an object (including classes, functions and modules) this becomes extremely easy. Take the following example:

# in myapp.models.person module
from google.appengine.ext import db
class Person(db.Model):
	first_name = db.StringProperty()
	last_name = db.StringProperty()

def get_person_by_id(person_id):
	return Person.get_by_id(person_id)

# in myapp.domain.person
class PersonProxyFactory(object):
	def create(self):
		from myapp.models import person
		return person

# some_view.py
def get_person(request, *args, **kwargs):
	from myapp.domain.person import PersonProxyFactory
	factory = PersonProxyFactory().create()
	factory.get_person_by_id(request.GET.get('person_id'))
	# return some template

In the above example the View has no direct knowledge of the Model; the only layer the View explicitly knows about is Domain. The Domain has knowledge of the Model, and because in python a module is just another object, the Domain’s factory can return the actual person module. The View need not be aware of what the returned object actually is, instead it need only understand what the interface of that object is.

This separates the concerns nicely while still allowing us to use the persistence framework, but it poses some difficult questions. To what extent must we wrap functionality? Is it appropriate for layers above the Model layer to assume that a Person class know how to save itself (via an instance method of save() or put())? Where do we draw the lines with this solution?

How have you tackled the dichotomy of object persistence frameworks and the separation of concerns?

4 Responses to 'Google AppEngine and Separation of Concerns'

Subscribe to comments with RSS or TrackBack to 'Google AppEngine and Separation of Concerns'.

  1. Tony Arkles said,

    I think the Active Record pattern fundamentally results in code that has poor Separation of Concerns. In fact, if I could go back in time and try to convince the Google guys to do anything different, I’d try to persuade them to use the Data Mapper pattern (http://martinfowler.com/eaaCatalog/dataMapper.html) instead of the Active Record pattern for datastore access.


  2. One way to achieve better separation of concerns is Depend in the Direction of Stability (as opposed to the direction of layers), from the SOLID principles. Your Domain classes wouldn’t know about either View or Model, but instead would depend on interfaces, to be implemented by the model or the view.

    This technique helps you out to make sure your domain logic really is separated and abstracted away from concrete things like databases, UI, message queues, and it can make your domain logic more readable and unit testable.

    • Ryan Baldwin said,

      That’s a great point Todd. I guess I have 3 questions and perhaps you can help me out.
      1. How does one formally implement an interface in Python? If you have any kind of techniques or magic for this I would love to hear them, as not having a formal Interface makes me sad panda.
      2. What would be responsible for constructing the domain instance with the proper concrete dependencies? In django/webapp, the request comes into a view class. Does that view class divert to some domain factory which returns an instance of a domain concrete object with all the concrete dependencies injected?
      3. At what point does one say “enough is enough!” with regards to what’s being injected? What are some techniques to remove the symptoms of injection exhaustion?

      Thanks for the comments man!


      • 1. I don’t think you need to formally define your interfaces in python. I guess you could make a class where every method is “pass”, but only if it makes you a happy panda. The more important idea is that everything else depends on the domain code and it doesn’t depend on anything. This should make your test setup real easy too.

        Could you change your model from app engine to a django database without editing the file with the domain class in it? Could Future Ryan read the domain classes and figure out what the code is doing?
        That’s really all I meant.

        I should have worded it using the proper phrase “Depend on Abstractions not Concretions”.

        2. That’s probably what I would do.

        3. Hmm… that’s a good one. To me, it’s the lesser of evils. In the past I’ve found some really bizarre results from the layers approach that I consider worse:
        a. Someone writes the same test over and over on each layer, just transporting a field value from one layer to the next. Slap! Use a functional test to ensure code is wired up correctly.
        b. The opposite problem. Someone uses functional tests to cover every path. This works ok, especially in django, but your setup can get so long, and it’s tough to figure out what’s the difference between each test.

        In both cases, it can be hard for Future Ryan to figure out *what this code does*, which is more time consuming than too much injection. If your code is easy to figure out, then that’s one fewer reason for you to do it this way. Maybe ask someone unfamiliar with the code to figure out what it does, then you’ll know.

        To me, transporting data back and forth can use layers/functional tests, while domain logic can be refactored to SOLID-OO/unit tests once it becomes substantial enough to bother. Let TDD guide you – when your tests get too rough, factor out a new domain class. Then write a comment that says “To Future Ryan, I suffered through injection exhaustion just for you. I hope you enjoy reading this class. Love, Past Ryan.”


Leave a Reply