1

I have a class Song, which has the following public methods:

String getSong();
void setSong(String);
int getId();
void setId(int);

Now I have two different ways I might want to store these songs in a database:

  1. just two columns; one for ID, one for the whole text of the song
  2. three columns; one for ID, one for line number, and one for that line

[Please ignore DB design issues; it's only important the two schema are different.]

So I need a way of swapping out how songs are written/read from/to the database. That might even mean making a runtime decision on which schema I use. What is the proper OO way of doing this? I feel like the Strategy pattern would work here, but I can't connect it all together. Some questions I've been struggling with over this:

  • Should there be a separate object for each read and each write? Or should one class implement both a read and a write?
  • How do I avoid duplicated logic? For example, method (2) means the write method splits the song on newlines, while the read method joins them. Is there a way to combine the similar logic here?
  • What if Song didn't have public setters? How does the design change?

I've been really having difficulty with solving this cleanly and in a flexible object-oriented way, so any help would be great.

  • 1
    You say to ignore database issues, but I'm a bit stuck on how 'making a schema decision at runtime' would translate to the database. Are you talking about having two separate schemas set up in the DB, and deciding at runtime which schema to save any given song to? Which would mean any retrieval would need to check both schemas for the desired song? – LindaJeanne Oct 24 '15 at 11:32
2

Perhaps, this isn't the answer you expect, but I believe strongly, that you should put more effort in your design decisions, than making bad decisions and invest most of the time in thinking about how to implement this bad design.

Now I have two different ways I might want to store these songs in a database:

1) just two columns; one for ID, one for the whole text of the song

2) three columns; one for ID, one for line number, and one for that line

Yes. These are the possibilities. But two questions coming to my mind:

1) Why do you want 2 different formats (at the same time)?

2) Does the second design even make sense?

What would be the advantage of storing the line number and the content of that line? The only case, when it might eventually somehow would make sense is, when you oftentimes have queries get me exactly line n from the song x and even then I see no justification to store text line by line as column rows. Put the text as TEXT in the DB and do whatever magic you want to do on that in-memory after you retrieved it from the DB

So I need a way of swapping out how songs are written/read from/to the database. That might even mean making a runtime decision on which schema I use. What is the proper OO way of doing this? I feel like the Strategy pattern would work here, but I can't connect it all together. Some questions I've been struggling with over this

The strategy would be a good fit for that; so you could change the strategy how to store or retrieve data at will.

Should there be a separate object for each read and each write? Or should one class implement both a read and a write?

The typical pattern for persistence is the repository. The job of the repository is to abstract away details of persitence. And it would be the repository, which would use the strategy.

How do I avoid duplicated logic? For example, method (2) means the write method splits the song on newlines, while the read method joins them. Is there a way to combine the similar logic here?

It depends on your implementation. Sure, there are ways to prevent duplication.

What if Song didn't have public setters? How does the design change?

You have to implement some way, how your song represents state.

Since you need it to set at least at object creation, you would write a constructor such, that your object is initialized in the desired way.

Letting out (public) setters, you make the object immutable which could be what you wanted. The advantage of immutable objects is simple: they are astoundingly boring; they have always the same state - which is nice in multithreaded context. There are no surprises, that state was altered unintentionally.

  • Thanks for the answer. On the "line-by-line" issue, this is a much simpler version of something I am dealing with at work, only intended to illustrate a point. We have some legacy data, and a new schema for that data, and we want to be able to write both versions and read both versions. – Query Oct 24 '15 at 17:49
  • But that doesn't change the general answer: instead of dealing with two ways of data writing, I would invest time and effort in using a common data structure. What you save now, in implementing a strategy to work with legacy and new data, might become costly over time. I would put more effort in converting data to a better structure. – Thomas Junk Oct 24 '15 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.