Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should an object write itself out to a file, or should another object act on it to perform I/O?

NOTE: Sorry for the long question!

I'm trying to understand some key areas behind object orientation and I couldn't decide one way or another about my particular question.

Let's say I have an object full of lovely data. Class bob.

Bob myBob = new Bob("This string is data");

Let's say I want to save the contents of myBob to an xml file (bob.xml)

Should I have an object act on bob to write the contents out, or should I have myBob do this?

Case 1: Act on object

Writer myWriter = new Writer(myBob, "C:\\bob.xml");

Case 2: Save method

myBob.Save("C:\\bob.xml");

Some people are siding with option one as it means if the code for writing files is changed, it doesn't need to updated across every Save method; promoting code reuse I suppose. My problem with this is getting all the data out of objects which may have private data with no accessor.

The case for option two is that the method only acts on the data held by the object and that's the way it should be. No interference from other objects.

Or is the answer to my question one of those "case dependent" issues? If so, how do you know when one method is prefered over the other?

like image 434
Andrew Weir Avatar asked May 23 '09 13:05

Andrew Weir


5 Answers

The correct approach, in general, is your Case 1. This maintains a single responsibility for the class (whatever it does) without coupling it to a specific persistence mechanism (a disk).

You're looking at a specific case of a more generalized problem: Serialization. It's good and OK for an object to have some means to indicate how it should be serialized-- it's the only entity that knows what's necessary to deserialize it, after all. But if you make the object save itself to disk, you've tightly coupled that object to a specific implementation.

Instead, consider creating an interface that a generalized "writer" can use to "serialize" the object to whatever that writer serializes to. This way, you'll be able to serialize to disk, to the network, to memory, to whatever you actually need to serialize to. :)

like image 106
Greg D Avatar answered Nov 12 '22 09:11

Greg D


I would make Bob know how to serialize itself since it has private data. Another object (such as your Writer) would take that and put it on disk. Bob knows how to deal with its data best but it need not care about how or where that is stored. Your Writer knows how to save data best but it need not care about how that data is created.

like image 30
Colin Burnett Avatar answered Nov 12 '22 08:11

Colin Burnett


This is an example of where the Strategy Design Pattern could be used. Your myBob object could have an instance of the class that will write it out. You may want the writer to implement an interface or derive from an abstract class so that the save routine can be easily changed.
Today you are saving to xml, but you might need to eventually persist the object to a database as well. This pattern will allow you to change the save routine easily. You would even have the option to change how you save at runtime.

like image 10
Trevor Tubbs Avatar answered Nov 12 '22 09:11

Trevor Tubbs


I used to prefer option 2; however, as I have started really trying to understand and model the domains I am working on, I prefer option 1.

Imagine if your modelling Vehicles. Why would a vehicle know how to persist itself? It might know how to move, how to start and how to stop, but what is Save within the context of a vehicle.

like image 4
JoshBerke Avatar answered Nov 12 '22 10:11

JoshBerke


One other method is to use the visitor pattern. Have your object contain an Accept method that goes through the members you want to process/serialize, and have a visitor be your serializer. Whenever you update or change your serialization (plain text to xml to binary to whatever), you don't need to update the object.

We've had good experiences at work doing it this way. It's pretty powerful.

like image 2
djcouchycouch Avatar answered Nov 12 '22 09:11

djcouchycouch