Friday, January 18, 2013

Building SOLID Databases: Introduction

The SOLID design approach is a set of principles developed in object-oriented programming.    This series will explore the applicability of these principles to Object-Relational databases, and contrast the way in which they manifest from the way in which they manifest in the application layer.

You can't program a database like you'd program an application.  The database essentially serves two twin functions:  a persistence store, and a model of information derivable from that store.  The ACID consistency model therefore limits what sorts of programming you can reasonably do in the database because it is a bad idea, outside of logging, to mix transactional and non-transactional side effects.

As an information model, the approach taken by applying these approaches then is relatively different.  One way to think of it is that if object oriented design might be seen as a triangle, applying this in the db requires turning that triangle upside down so you have a flat base to build your application on.

This series will look at applying SOLID principles to object-relational database design, comparing and contrasting the way in which the principles get applied to that of general software development.  Many aspects of relational design in fact play into these topics and so one ends up with a very different mix than one might have with pure object-oriented design.

In general this series continues to look at relations as sets of objects rather than sets of tuples.  This means that the question is how we define data structures and interfaces so that we can bridge object and relational worlds in the database.  The SOLID principles are good starting points but the sort of logic done is fundamentally different and so they are applied in different ways.

Welcome to the series.  I hope you enjoy it.


  1. I think its best to stick to looking at relations as sets of tuples rather than changing it to sets of objects. Object orientation can be integrated quite well into the relational model without taking away anything relational. Objects are just syntactic sugar for supporting arbitrary types and operators on them, same as the relational model already does. Its just the same thing from perhaps slightly different angles.

    1. This brings up something that I perhaps should be more clear about. There are many cases where object-relational modelling is a real win, but typically if you are sacrificing too much relational math for the abstractions it will fail.

      Additionally, if you think of relations as storing application objects, this breaks both good object-oriented and good relational design rules. The basic thing is that the responsibilities of the application and database layers are quite different and so they change for different reasons.

      But let me give you a common example where this can be helpful. In general, I use table inheritance in PostgreSQL to reflect a "has a" (compositional) relationship rather than an "is a" (classical inheritance) relationship and thus it provides a way to track, for example, certain kinds of common fields, like notes. Such a compositional approach avoids antipatterns like global notes tables, and it allows what are essentially dynamic catalogs of values in these common fields.

      So largely I think I agree with you when you say "Object orientation can be integrated quite well into the relational model without taking away anything relational." I hope this will become clearer as we go through the series.

      One final note. Because the responsibilities of application (behavior) and database (information model) code are fundamentally different, the SOLID principles interact with databases in kind of funny ways. Normalization, for example, can be seen as an approach to ensuring single responsibility in relations (and in some higher normal forms like 6NF also addresses dependency inversion in some ways, but dependency inversion and single responsibility are closely tied concepts).

    2. As a second point, one thing one can further do is create methods (calculated fields) on all tables with those common fields. For example, if all notes are in English, we can create a method to extract an English tsvector from all notes, which can then provide a common search interface for full text searches. That can then be indexed. Alas, functional foreign keys are not yet supported declaratively though triggers would work (you can't declare a foreign key of an ip_assignment table such that network(ip_address) = cidr_block.block_def).

  2. Hi
    We want your permission to translate this series of articles on (phrase obtenue par google tranlation!!!)