Persistence and encapsulation

I have recently been chewing over what appears to me to be an inherent conflict between encapsulation (or more specifically, data hiding) and proper separation of persistence concerns.

Say I have a whole bunch of instances of some MyObject which encapsulates a bunch of data that I want to be able to save to file and includes many methods that operate on that data. The data is not exposed to the world because basically all the methods that need to operate on it directly are in the class, in accordance with basic OOD.

Now I want to save the data to file. An obvious option is to put some methods for doing that (or doing part of the process) into the MyObject class itself, but it seems like this conflicts with the need to separate the persistence handling code from the object itself.

The other option is, of course, to open up the object, breaking its encapsulation. Although I guess that you only have to put in get methods and not set methods so it is still sorta-kinda encapsulated.

Is there some third option I am missing? One thing that occured to me is to write an interface MyObjectPersistor with a method that accepts parameters corresponding to the data items in MyObject, and then add a method persist(MyObjectPersistor persistor) to MyObject... but it feels more like obscuring things than actually keeping them encapsulated.

Is this the type of "cross-cutting" concern that is fueling the development of aspect oriented programming?

Drake

[1500 byte] By [Drake_Duna] at [2007-10-2 15:42:44]
# 1

> I have recently been chewing over what appears to me

> to be an inherent conflict between encapsulation (or

> more specifically, data hiding) and proper separation

> of persistence concerns.

>

Difficult. One normally has to make a 'compromise'. Normally, the model object has something like a primary key in it (even if it is only an int uid). You have two other, high-level compromises to make:

> Either have service/model classes responsible for calling a DAO to create/load itself. This will push you towards static public facade factory methods on the model object such as getInstance() or newInstance() or save().

> Or (in a more tiered environment) have the service class instantiate the DAO which will return a model class to the service.

> Say I have a whole bunch of instances of some

> MyObject which encapsulates a bunch of data that I

> want to be able to save to file and includes many

> methods that operate on that data. The data is not

> exposed to the world because basically all the

> methods that need to operate on it directly are in

> the class, in accordance with basic OOD.

>

Remember, OOD is for model and service classes. DAO's and persistence classes, by their nature bridging the object-relational boundary, do not have to concern themselves as much with OO as persistence. Look at Hibernate objects, they are often simply 'data bags' or DTO's.

> Now I want to save the data to file. An obvious

> option is to put some methods for doing that (or

> doing part of the process) into the MyObject class

> itself, but it seems like this conflicts with the

> need to separate the persistence handling code from

> the object itself.

>

File serialization is, IMO, just another type of persistence. Why not create a DAO for that as well?

> The other option is, of course, to open up the

> object, breaking its encapsulation. Although I guess

> that you only have to put in get methods and not set

> methods so it is still sorta-kinda encapsulated.

>

You will have to make at least a primary key compromise. How else can an object properly update itself in the database when values change?

As an aside, I do think there is a way around this in 1.5. I have not fully fleshed-out the idea, but you could write your persistence classes (DAO's) as generics. These would return model objects normally (e.g., the type parameter of the generic methods would be the model object or a superclass of model objects), but would internally retain primary keys and other persistence related information. Again, the above is vague, but the idea keeps intriguing me enough to mention it at least.

> Is there some third option I am missing? One thing

> that occured to me is to write an interface

> MyObjectPersistor with a method that accepts

> parameters corresponding to the data items in

> MyObject, and then add a method

> persist(MyObjectPersistor persistor) to MyObject...

> but it feels more like obscuring things than actually

> keeping them encapsulated.

>

Encapsulate your model object as best you can. Make the DAO the ugly duckling.

> Is this the type of "cross-cutting" concern that is

> fueling the development of aspect oriented

> programming?

>

> Drake

Somewhat. I would think of it more as IoC and dependency-injection, ala Spring, than aspects per se. Aspects are used frequently in transaction demarcation. But not for persistence as a whole (at least not that I am aware of).

- Saish

Saisha at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

After the comprehensive reply from Saish, I donot have much left to say except for that in order to properly understand the data access layer, it would be helpful to look at

Row Data Gateway pattern

Table Data Gateway Pattern

and

Data Mapper

This would take you a great way in understanding the whole concept.

kilyasa at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 3
You might want to look at Memento pattern. Or you might think about your Model as an object holding State (which can be persistent): http://dkrukovsky.blogspot.com/2006/02/persistence.htmlDenis Krukovsky http://talkinghub.com/
dkrukovskya at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

Well, I have been reading about the DAO pattern on the web, and I hate to say it but... I don't understand it too well. If there is anybody who knows of a site with a good tutorial on it that does not bombard me with acronyms I do not know, I would appreciate it.

Let's take a simple example. I have some little critters called fuzzies represented by a class called Fuzzy. They are really simple. All they have is a method for feeding them food, a method for spraying them with chemicals, and a method for returning the color of their fur, which changes depending on what you feed them and what you spray them with. The effects might be different depending on how old the Fuzzy is, or something, as determined by how many times it has been interacted with by way of its public methods.

public class Fuzzy {

public void feed(Food toEat) {

//...

}

public void spray(Spray toSpray) {

//...

}

public String getColor() {

//...

}

}

The current fuzzy image (I crack me up) that I have of DAO is that the Fuzzy would not actually have instance members like "color", "age", or the like, but would instead sit on top of an instance of some other class implementing an interface like this one:

public interface FuzzyDAO {

public int getAge();

public void setAge(int newAge);

public String getColor();

public void setColor(String newColor);

}

In effect, all the data of the Fuzzy is moved out to the DAO. The actual instantiated DAO is apparently supposed to be returned from a factory of some kind.

Is that right?

Another thing that is making me scratch my head is how this works in a traditional one-machine environment using plain old flat files. Presumably the functionality to save into a flat file on the local machine would just be another bit pluggable into a properly designed DAO pattern, but where does the "save" command come down from? I guess it is not coming through Fuzzy. Is it coming through the factory that created all the DAOs?

Drake

Drake_Duna at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

That is one implementation. I would be more tempted to pursue that kind of persistence class if I was using an O/R mapper ala Hibernate with a newer data model.

Generally, I would implement FuzzyDao as:

public class FuzzyDao {

public Fuzzy select(final int uid);

public int insert(final Fuzzy target);

public void update(final Fuzzy target);

public void delete(final int uid);

}

The above assumes Fuzzy is identified by a sequence in the database.

- Saish

Saisha at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 6
The above would obviously not compile. I was lazy and put semi-colons instead of empty braces. But you get the idea. :^)- Saish
Saisha at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 7
a very good thread on the subject http://forum.java.sun.com/thread.jspa?threadID=720853&messageID=4159169#4159169
kilyasa at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

I think OOD principles hold always, but the common ideas may not apply in all situations.

I think data hiding is relative. You can't hide from your persistance classes. You can sneak in the back door with reflection I believe.

I agree that many things are abstract, but there must always be a point of reference between two communicating entities.

_dnoyeBa at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

> I think OOD principles hold always, but the common

> ideas may not apply in all situations.

>

Really? So, a Struts FormBean could not equally (and validly) be implemented with all public instance variables rather than JavaBean accessors and mutators?

> I think data hiding is relative. You can't hide from

> your persistance classes. You can sneak in the back

> door with reflection I believe.

>

Sneaking in the back door with AccessibleObject#setAccessible(true) is not OO. The method itself is a violation of OO. :^)

> I agree that many things are abstract, but there must

> always be a point of reference between two

> communicating entities.

Fair point.

- Saish

Saisha at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 10

It has been a day or two since anybody posted to this thread, but just to let you know, it was very useful to me. I spent a lot of time beating my head against the wall trying to get the exact right image of the DAO pattern before finally figuring out that I was stressing form over function and just coming up with my own design... which appears to have ended up being basically DAO anyway. I learned a lot in the process, so thanks.

Drake

Drake_Duna at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...
# 11
Glad we could help Drake. Lot's of ways to skin a digital cat. Best of luck.- Saish
Saisha at 2007-7-13 15:31:12 > top of Java-index,Other Topics,Patterns & OO Design...