I have a simple object like this
public class Book { public List Chapters { get; private set; } public TableOfContent BookTOC { get; set; } public string Identifier { get; private set; } public string Title { get; private set; } public string Publisher { get; set; } public string Rights { get; internal set; } public DateTime PublishingDate { get; internal set; } private IBookRepository _repository = null; public Book(IBookRepository bookRepository) { _repository = bookRepository; } public Book Load(string bookid) { //Load book from repository } public Chapter GetNextChapter(string chapterId) { //Load Chapter from repository } }
In this domain (actually anywhere in the world!), book has chapters and book has ToC. In our application, there would be two possible implementations of repository i.e. the book object may either be loaded from Xml or be loaded from database. These books are pretty large in size i.e. two-four hundred thousand chapters (This is all about book metadata, content is separate but out of question for now)
My problem is that when the book is loaded from database, I want to leverage database capabilities of querying and indexes etc. For example, in the GetNextChapter, when I am using database repository, I can locate just the specific chapter and find next of it. However in case of Xml, since I don't want to traverse xml over and over again, I would like to keep it loaded at one time initially and the cache it upstream so that I can find the next chapter just from the object itself. As you can see, these two implementations by nature are different, but at any given time we will be using only one of those. I am not able come up with a uniform interface of operations that both these implementations can follow. Let's say if I decide to have operation GetNextChapter implemented in both, then for database repository, I just need the chapter ID, whereas in the Xml repository, I need the whole book object or at least list of chapters (and even that has nothing to do with xml actually because that's just in memory filter).
Can anyone help in deciding how do I uniform these two through a single interface having two implementation? Or are they not meant to be uniformed via a single interface and deserve a separate way of implementation?
EDIT To clarify further, if I add GetNextChapter method in the interface, Database implementation needs only the chapterID as parameter, whereas Xml implementation would need the book object. Similarly the LoadBook method will return full object (with chatpers and toc) for XMLImplementation (so that I don't have to traverse xml over and over) whereas it will only return partial object (without chapters and toc) in case of DatabaseImplementation (for obvious performance reasons).
So how will these two go against a single interface?
interface
. It's also the pre-conditions, post-conditions, and expected return values. In other words, if your XML implementation doesn't return the same data, clients will likely need to type check because you've broken Liskov's substitution principle.