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?

Google AppEngine PolyModels and ModelForms

Posted in Development,Technology by Ryan Baldwin on April 11, 2009
Tags: , , ,

I recently created my first PolyModel class in Google AppEngine for a new feature. The feature was pretty straight forward  - allow comments for some of the entities in our application Homebook.  We wanted each comment to be tied back to its target entity – a room, house, or image – in a 1-to-many (each entity can have many comments). Using PolyModel we found this to be pretty easy without duplicating a bunch of code.  Essentially the structure of Comment class hierarchy looked like the following:

class Comment(PolyModel):
    # bunch of common fields

class RoomComment(Comment):
    target = db.ReferenceProperty(reference_class=Room, collection_name=’comments’)

class HomeComment(Comment):
    target = db.ReferenceProperty(reference_class=Home, collection_name=’comments’)

class ImageComment(Comment):
    target = db.ReferenceProperty(reference_class=Image, collection_name=’comments’)

Really straight forward – simple class inheritance. I then created a simple factory method that would fetch the proper class type for a given instance of one of our commentable entities. Things were moving along nicely (complete with lots of beautiful unit tests – you do write unit tests, right?) and it was time to create the add_comment view.

For the most part we use Google AppEngine’s djangoforms ModelForms, a theoretically clean and easy way to create web forms based on data models. I created my standard ModelForm class (based on our parent Comment class) and the view against which the form would post, only to be blindsided by the oddest of validation errors:

  • _class
    • This field is required.

Huh? _class? What gives? Well, after a couple hours of soul searching, googling (which turned up nothing), and a few tears, my genius coworker Tony Arkles had an epiphany: The PolyModel class has a _class field which is used to keep track of the PolyModel instance’s class hierarchy. We added the _class field to our form’s exclude list and the world righted itself, cats and dogs learned to coexist, and Liz Taylor finally discovered a happy marriage.

Now the question is, why is the ModelForm rendering a field that’s not a google.appengine.ext.db model property? Can anybody from Google answer me that?