Never use Your ORM Directly

ORMs are great for helping a startup create a product quickly. The downside is that they make it incredibly easy to litter your codebase with code like this:

post = BlogPost.objects.get(id=post_id)

This seems relatively innocent at first, but, as your codebase grows you'll find it suffers from a few problems:

  • When you need to refactor how you access your blog posts you will need to do a search across all your code for any usage of BlogPost and check to see if it needs changing
  • Suppose you want to check if an index in your database is still needed. You would have to do a search across the entire codebase and check a lot of irrelevant uses of BlogPost
  • What if you wanted to completely change your ORM? All the places you used BlogPost will need changing, and there will be a lot of these places because of how you've used the ORM

Fortunately, it's easy to avoid this kind of problem by creating another layer between your ORM and the rest of your code - an internal API of sorts.

def get_blogpost_by_id(post_id): BlogPost.objects.get(id=post_id)

Then the example above becomes:

post = get_blogpost_by_id(post_id)

This will make your life easier when the codebase has grown and you need to refactor.

  • Changing how getting by ID works requires searching only for get_blogpost_by_id which will always be exact matches that you are interested in
  • Finding out about index usage is easy - you only need to check the code in your internal API (and check that the API is used)
  • A complete change of your ORM can be made transparent to the rest of your application - they still call the same methods and the API handles the switch

This kind of approach also makes it easier to reason about how you access your data - all the access paths are in one place for you to look over. It also lends itself to exposing a real API to the rest of the world.

To summarise, never use your ORM directly.


blog comments powered by Disqus

Colin Howe

I'm Colin. I like coding, ultimate frisbee and startups. I am VP of engineering at Conversocial