Tuesday, February 07, 2006

Persistence

Currently for me persistence is one of biggest difficulties in software engineering. One of reasons for it, I believe, is desire to make our business objects independent from persistence. This desire comes from recommendations of most respectful people in software like Martin Fowler. Many times I have read serious books on software design where author recommends: "There should be three layers like Persistence layer, Business Logic layer, and UI layer, and would be good to have Business Logic independent from Persistence because this way we’ll be able to switch from no persistence to file persistence or RDBMS persistence". "Good" I think. "Let’s make business logic independent from persistence".

First thing to note is that in most cases we don't need this flexibility, and trying to achieve it from start is against agile methodology and can cost us time.

Then we can ask what "Business Logic" actually is. When we write in requirements words like "New message from the User should be saved in the database" – is it business requirement or business logic or what? And we can agree that our categorization is pretty subjective - one can say "It’s a business requirement", and another can say "It’s persistence logic".

What I found is we can easily make business logic independent from persistence, but only when we have no word about persistence in our requirements. We model real world requirements in software, and having our persistence and business logic closely mixed in our requirements we can expect to have difficulties trying to model business logic independent from persistence.

Then I found that our business logic lifecycle actually starts from persistence. When our program starts, one of things it does first is it reads state stored in the database and initializes business logic with it. "What if I model my business objects like holding state given to them in constructor?" – I thought.


Persistence frameworks

I’m unhappy with today’s popular persistence frameworks. One of reasons for it is a fact that existing frameworks require my business entity to have getter / setter for every state data I want to have persisted. What should I do if I have some data I don’t want to have setter to, and moreover if I consider having public setters harmful?

Let’s take a quick example. Say I have Message entity which should maintain last modified date. First move would be to have lastModified Date field, have some update() method which will set lastModified field to current date / time, and call update() from setText() and other meaningful setters. This easiest approach would not work because my update() method will be called each time Message is retrieved from the DB! I will have to do some tricks to find out - do I need to update my last modified date, or it’s the persistence framework that calls the setter and initializes my object? Or worse – I will have to move lastModified management out of Message to some other object like UI controller.


So the idea is to have business objects to work with provided state. I will be testing this idea for persistence. Business objects can be made having no idea if the state is going to be persisted or no – yes, this way I can make them independent from persistence! State is responsible for persistence. It will persist itself as it decides to.