What exactly is "persistence ignorance"? - nhibernate

Persistence ignorance is typically defined as the ability to persist & retrieve standard .NET objects (or POCOs if you really insist on giving them a name). And a seemingly well accepted definition of a standard .NET object is:
"...ordinary classes where you focus on the business problem at hand without adding stuff for infrastructure-related reasons..."
However, I see people describing NHibernate as a framework that allows persistence ignorance, and yet it is a framework that cannot work on any standard .NET object, only standard .NET objects that adhere to particular design requirements, for example (source):
All classes must have a default constructor
Some features don't work unless classes are unsealed and all members are virtual
Object identity doesn't work properly unless you abuse Equals/GetHashCode
(Aside: Before anybody gets upset, I don't mean to pick on NHibernate here, it's just a frequently quoted example of a framework that supposedly permits persistence ignorance. I'm sure similar arguments could be applied to other ORMs that claim the same.)
Now although the class in itself does not have any persistence-framework-specific attributes or base classes etc., to me it is not really "persistence ignorant" because it must follow a set of design guidelines to facilitate use by the chosen persistence framework. You must design and implement the class with the requirements of the persistence framework in mind; if you are ignorant of it the class may not work with it.
Where I'm having trouble with the definition of "persistence ignorance"/"POCO" is that I don't see how, conceptually, this is really any different to adding attributes such as [Serializable] or [DataContract] or [XmlType] or any other persistence-framework-specific annotations that facilitate the persistence and retrieval of the entity using that framework.
So, what exactly is "persistence ignorance"?
Clearly the definition of it as being able to persist "ordinary classes" is a fallacy because the NHibernate ones are only ordinary insofar as not referencing framework-specific classes, whereas they are extraordinary inasmuch as they require unusual design choices such as default constructors and all-virtual members and Equals/GetHashCode implementations on mutable types.
Is it therefore reasonable to say that "persistence ignorance" is true when objects facilitate the use of a persistence framework (either in design and structure or by use of framework-specific annotations) but do not perform any persistence logic themselves?

I would claim that, like most things, its a sliding scale. There are things that we make that want to have the property of persistence. On one end of the scale is this thing having all of the guts, dependencies, and code that is custom built to persist just this one thing in its particular way. On the other end of the scale is something that just magically happens, all without us doing much more than adding a token or setting a property somewhere that causes that thing to 'just persist'. In order to get to the magical side of the scale, there are frameworks, design guidelines, conventions, etc that assist the magic in happening. I think you could argue that a tool could be produced that had fewer requirements and restrictions than NHibernate but pursued the same goal; that hypothetical tool would be further along our scale.
I don't know that I like the term 'persistence ignorance' so much; its really about an object being ignorant of the implementation, the backing store, the cache, that sort of thing - an object is typically aware of whether or not it is persistent, though. But that's just semantics.

I don't believe your understanding (or definition) of "Persistence Ingorance" is wrong.
The real issue is that of leaky abstractions. Quite simply, the existing technology makes it very difficult to implement true PI.

A persistant ignorant class, is a class that is not tied to a persistancy framework.
That is, the class has absolutely no knowledge that there's a persistancy framework present, it does not inherit from a class that is defined by that framework nor does it implement an interface that is required for that persistance framework in order to work.

I agree with Mikeb - "persistance ignorance" is a sliding scale, not a true/false property of a given ORM.
My definition of true 100% PI would be that you could persist ANY possible POCO class, no matter how convoluted and linked to other classes, without otherwise changing the class in any way.
Adding ID fields, decorating with attributes, inheriting from ORM classes, having to design your classes so they map well to the underlying tables in an RDB - all reduce the "PI score" below 100%.
This said, I've chosen to use Fluent NHibernate Automapping because it seems to have the highest PI score of any of the ORM options I've looked at.

I'd agree with your definition:
Is it therefore reasonable to say that
"persistence ignorance" is true when
objects facilitate the use of a
persistence framework, but do not
perform any persistence logic
themselves?
The code (as opposed to atributes) in your classes has no features that are intrinsic to persistence. Default constructors might be needed for persistence, but have no code that actually does persistence. The persistence layer could be changed quite substantially, different databases could be used and the business logic would remain unchanged.

While there may be certain minor constraints that any given persistence-ignorance framework requires, persistence-ignorance nevertheless remains in place.
While a class in your domain model (transparently persisted with NHibernate) must have a no-arguments constructor so that it can be constructed "dynamically," it is not required to have a certain base class dictated by the framework nor is it required to have or override certain framework-specified methods.

In my opinion, "persistence ignorance" is a property of your model (domain model, business model or whatever you might refer to it as). The model is persistence ignorant because it retrieves instances of the entities it contains through abstractions (sometimes referred to as repositories). These abstractions can be implemened by using an ORM directly, but as you state yourself this may sometimes add requirements to the objects that do not naturally belong in your model. Therefore I would not say that a model that adheres to some requirements of a specific ORM is 100% persistence ignorant.

you can implement persisrtence ignorance using a class for the domain or you application and a POCO class in the persistence, when you are going to persist the domain object map it into your persistence class and use the persistence object to store with nhibernate o other framework
your domain class must to ignore how is persisted the information, so you must no include any rules of a persistence framework like (empty constructor, virtual properties etc.)
these persistence framework rules can be in your persistence class.

Related

Are fromXYZ methods inside entities an antipattern?

I am developing a Symfony-Application but I guess my question is mostly independent of
framework-usage.
This is the situation:
I got a very lightweight entity that is actually not even managed by the ORM as it is just used to aggregate and communicate information of another entity.
I read that we should keep business-logic out of the model but I also thought that it would
proof quite useful to me if I had a fromXYZ-method in my lightweight-entity to create a SPOC for instanciation based off of the "big entity".
But technically this from-method performs logic which contradicts what I read to be good practice.
So would this be an antipattern? How would I resolve this in a more suitable way, if yes?
What are you talking about is static factory method. It's pretty ok to use it, but it shouldn't do anything fancy because it will be hard to test your code since you can't mock it.
If you feel that your method won't create any problems in testing, you can create it without any doubt. Otherwise, you can encapsulate your creation logic in a separate factory.
Your "lightweight entity" could be referred to as a DTO.
One way to keep the terminology straight.
Entities are managed by the ORM.
DTOs are unmanaged. Often used to convey a subset or aggregation of entities.
Constructing one object from another by copying its fields is not something I would consider business logic, unless there are complex transformations prescribed by business requirements.
The real problem with fromXYZ methods is that they implement a dependency on XYZ. You have to be careful about which direction such dependencies are pointing. For example, if you construct a DTO by passing it an Entity, that DTO now has a dependency on the persistence layer of your application. If you then use that DTO in a service, your service layer now has a (transitive) dependency on your persistence layer. This is referred to as tight coupling.
One way to keep business logic decoupled from persistence, view, etc., is to point dependencies in the other direction: into the services rather than out of them.

DDD: Where to put persistence logic, and when to use ORM mapping

We are taking a long, hard look at our (Java) web application patterns. In the past, we've suffered from an overly anaemic object model and overly procedural separation between controllers, services and DAOs, with simple value objects (basically just bags of data) travelling between them. We've used declarative (XML) managed ORM (Hibernate) for persistence. All entity management has taken place in DAOs.
In trying to move to a richer domain model, we find ourselves struggling with how best to design the persistence layer. I've spent a lot of time reading and thinking about Domain Driven Design patterns. However, I'd like some advice.
First, the things I'm more confident about:
We'll have "thin" controllers at the front that deal only with HTTP and HTML - processing forms, validation, UI logic.
We'll have a layer of stateless business logic services that implements common algorithms or logic, unaware of the UI, but very much aware of (and delegating to) the domain model.
We'll have a richer domain model which contains state, relationships, and logic inherent to the objects in that domain model.
The question comes around persistence. Previously, our services would be injected (via Spring) with DAOs, and would use DAO methods like find() and save() to perform persistence. However, a richer domain model would seem to imply that objects should know how to save and delete themselves, and perhaps that higher level services should know how to locate (query for) domain objects.
Here, a few questions and uncertainties arise:
Do we want to inject DAOs into domain objects, so that they can do "this.someDao.save(this)" in a save() method? This is a little awkward since domain objects are not singletons, so we'll need factories or post-construction setting of DAOs. When loading entities from a database, this gets messy. I know Spring AOP can be used for this, but I couldn't get it to work (using Play! framework, another line of experimentation) and it seems quite messy and magical.
Do we instead keep DAOs (repositories?) completely separate, on par with stateless business logic services? This can make some sense, but it means that if "save" or "delete" are inherent operations of a domain object, the domain object can't express those.
Do we just dispense with DAOs entirely and use JPA to let entities manage themselves.
Herein lies the next subtlety: It's quite convenient to map entities using JPA. The Play! framework gives us a nice entity base class, too, with operations like save() and delete(). However, this means that our domain model entities are quite closely tied to the database structure, and we are passing objects around with a large amount of persistence logic, perhaps all the way up to the view layer. If nothing else, this will make the domain model less re-usable in other contexts.
If we want to avoid this, then we'd need some kind of mapping DAO - either using simple JDBC (or at least Spring's JdbcTemplate), or using a parallel hierarchy of database entities and "business" entities, with DAOs forever copying information from one hierarchy to another.
What is the appropriate design choice here?
Martin
Your questions and doubts ring an interesting alarm here, I think you went a bit too far in your interpretation of a "rich domain model". Richness doesn't go as far as implying that persistence logic must be handled by the domain objects, in other words, no, they shouldn't know how to save and delete themselves (at least not explicitely, though Hibernate actually adds some persistence logic transparently). This is often referred to as persistence ignorance.
I suggest that you keep the existing DAO injection system (a nice thing to have for unit testing) and leave the persistence layer as is while trying to move some business logic to your entities where it's fit. A good starting point to do that is to identify Aggregates and establish your Aggregate Roots. They'll often contain more business logic than the other entities.
However, this is not to say domain objects should contain all logic (especially not logic needed by many other objects across the application, which often belongs in Services).
I am not a Java expert, but I use NHibernate in my .NET code so my experience should be directly translatable to the Java world.
When using ORM (like Hibernate you mentioned) to build Domain-Driven Design application, one of good (I won't say best) practices is to create so-called application services between the UI and the Domain. They are similar to stateless business objects you mentioned, but should contain almost no logic. They should look like this:
public void SayHello(int id, String helloString)
{
SomeDomainObject target = domainObjectRepository.findById(id); //This uses Hibernate to load the object.
target.sayHello(helloString); //There is a single domain object method invocation per application service method.
domainObjectRepository.Save(target); //This one is optional. Hibernate should already know that this object needs saving because it tracks changes.
}
Any changes to objects contained by DomainObject (also adding objects to collections) will be handled by Hibernate.
You will also need some kind of AOP to intercept application service method invocations and create Hibernate's session before the method executes and save changes after method finishes with no exceptions.
There is a really good sample how to do DDD in Java here. It is based on the sample problem from Eric Evans' 'Blue Book'. The application logic class sample code is here.

FluentNHibernate Unit Of Work / Repository Design Pattern Questions

I think I am at a impasse here. I have an application I built from scratch using FluentNHibernate (ORM) / SQLite (file db). I have decided to implement the Unit of Work and Repository Design pattern. I am at a point where I need to think about the end game, which will start as a WPF windows app (using MVVM) and eventually implement web services / ASP.Net as UI.
Now I already created domain objects (entities) for ORM. And now I don't know how should I use it outside of ORM. Questions about it include:
Should I use ORM entity objects directly as models in MVVM? If yes, do I put business logic (such as certain values must be positive and be greater than another Property) in those entity objects? It is certainly the simpler approach, and one I am leaning right now. However, will there be gotchas that would trash this plan?
If the answer above is no, do I then create a new set of classes to implement business logic and use those as Models in MVVM? How would I deal with the transition between model objects and entity objects? I guess a type converter implementation would work well here.
To answer the first part of your question, yes your business logic and validation should go in your entities. The point of NHibernate is to let you design your entities to be persistence ignorant. That means that you should, whenever possible, be designing your entities as you would if you didn't care about persistence. This isn't entirely feasible as you'll soon find out (you'll need to make your properties virtual in order to support lazy loading and if you want to use NHibernate Validator you'll be decorating your properties with validation attributes), but for the most part NHibernate does a good job of staying out of your way.
As for whether to use your entities as the models, you'll get mixed reviews on that. Ideally, you would create separate viewmodel classes and map from your entities to the viewmodel so that your views will only access to the bare minimum of information they need. This also goes a long way in preventing N+1 access issues. However, doing so is often a huge pain. Granted, there are tools like AutoMapper that will make it easier from transposing your entity properties to a viewmodel.

Making OR/M loosely coupled and abstracted away from other layers

In an n-tier architecture, the best place to put an object-relational mapping (OR/M) code is in the data access layer. For example, database queries and updates can be delegated to a tool like NHibernate.
Yet, I'd like to keep all references to NHibernate within the data access layer and abstract dependencies away from the layers below or above it. That way, I can swap or plug in another OR/M tool (e.g. Entity Framework) or some approach (e.g. plain vanilla stored procedure calls, mock objects) without causing compile-time errors or a major overhaul of the entire application. Testability is an added bonus.
Could someone please suggest a wrapper (i.e. an interface or base class) or approach that would keep OR/M loosely coupled and contained in 1 layer? Or point me to resources that would help?
Thanks.
It sounds like you are looking for the repository pattern. If you need more decoupling, you can inject the data dependencies with an Inversion of Control container.
Service Facade Pattern is one name. Simple contracts between business logic and data layer.
Service classes or beans (call it what you want) define and implement the contract, and orchestrate the lower data layer, often handling the transactional logic across data objects.
In Spring, you define an Interface, and then implement it. One implementation might be an OR/M, another might be raw JDBC or ADO.NET. In some frameworks, Aspect Oriented Programming allows you to inject declarative transactional logic without writing any code. It saves a lot of headache.
One caveat: When dealing with some OR/Ms like Hibernate, there is the use of proxy classes. This does pollute things, because there are a few instances where the proxy classes cause problems. In my opinion, that is an implemtation detail that should not escape the service layer. But with Hibernate, it does. Not sure about the .NET implementation.

Should entities have behavior or not?

Should entities have behavior? or not?
Why or why not?
If not, does that violate Encapsulation?
If your entities do not have behavior, then you are not writing object-oriented code. If everything is done with getters and setters and no other behavior, you're writing procedural code.
A lot of shops say they're practicing SOA when they keep their entities dumb. Their justification is that the data structure rarely changes, but the business logic does. This is a fallacy. There are plenty of patterns to deal with this problem, and they don't involve reducing everything to bags of getters and setters.
Entities should not have behavior. They represent data and data itself is passive.
I am currently working on a legacy project that has included behavior in entities and it is a nightmare, code that no one wants to touch.
You can read more on my blog post: Object-Oriented Anti-Pattern - Data Objects with Behavior .
[Preview] Object-Oriented Anti-Pattern - Data Objects with Behavior:
Attributes and Behavior
Objects are made up of attributes and behavior but Data Objects by definition represent only data and hence can have only attributes. Books, Movies, Files, even IO Streams do not have behavior. A book has a title but it does not know how to read. A movie has actors but it does not know how to play. A file has content but it does not know how to delete. A stream has content but it does not know how to open/close or stop. These are all examples of Data Objects that have attributes but do not have behavior. As such, they should be treated as dumb data objects and we as software engineers should not force behavior upon them.
Passing Around Data Instead of Behavior
Data Objects are moved around through different execution environments but behavior should be encapsulated and is usually pertinent only to one environment. In any application data is passed around, parsed, manipulated, persisted, retrieved, serialized, deserialized, and so on. An entity for example usually passes from the hibernate layer, to the service layer, to the frontend layer, and back again. In a distributed system it might pass through several pipes, queues, caches and end up in a new execution context. Attributes can apply to all three layers, but particular behavior such as save, parse, serialize only make sense in individual layers. Therefore, adding behavior to data objects violates encapsulation, modularization and even security principles.
Code written like this:
book.Write();
book.Print();
book.Publish();
book.Buy();
book.Open();
book.Read();
book.Highlight();
book.Bookmark();
book.GetRelatedBooks();
can be refactored like so:
Book book = author.WriteBook();
printer.Print(book);
publisher.Publish(book);
customer.Buy(book);
reader = new BookReader();
reader.Open(Book);
reader.Read();
reader.Highlight();
reader.Bookmark();
librarian.GetRelatedBooks(book);
What a difference natural object-oriented modeling can make! We went from a single monstrous Book class to six separate classes, each of them responsible for their own individual behavior.
This makes the code:
easier to read and understand because it is more natural
easier to update because the functionality is contained in smaller encapsulated classes
more flexible because we can easily substitute one or more of the six individual classes with overridden versions.
easier to test because the functionality is separated, and easier to mock
It depends on what kind of entity they are -- but the term "entity" implies, to me at least, business entities, in which case they should have behavior.
A "Business Entity" is a modeling of a real world object, and it should encapsulate all of the business logic (behavior) and properties/data that the object representation has in the context of your software.
If you're strictly following MVC, your model (entities) won't have any inherent behavior. I do however include whatever helper methods allow the easiest management of the entities persistence, including methods that help with maintaining its relationship to other entities.
If you plan on exposing your entities to the world, you're better off (generally) keeping behavior off of the entity. If you want to centralize your business operations (i.e. ValidateVendorOrder) you wouldn't want the Order to have an IsValid() method that runs some logic to validate itself. You don't want that code running on a client (what if they fudge it. i.e. akin to not providing any client UI to set the price on an item being placed in a shopping cart, but posting a a bogus price on the URL. If you don't have server-side validation, that's not good! And duplicating that validation is...redundant...DRY (Don't Repeat Yourself).
Another example of when having behaviors on an entity just doesn't work is the notion of lazy loading. Alot of ORMs today will allow you to lazy load data when a property is accessed on an entities. If you're building a 3-tier app, this just doesn't work as your client will ultimately inadvertantly try to make database calls when accessing properties.
These are my off-the-top-of-my-head arguments for keeping behavior off of entities.