I have Document
and ExternalDocument
classes in my system, where ExternalDocument
extends Document
. The main distinction is that ExternalDocument
holds onto externalDocumentId
and externalEventId
data in order to correlate with the external system.
Documents may be overwrote calling document.overwrite(a, b, c)
. When overwriting external documents I want to track the externalEventId
that triggered the change and this is where the design falls apart.
According to the LSP I shouldn't strengthen preconditions in document.overwrite
. I could implement an document.externalOverwrite
operation and throw an exception when document.overwrite
is called directly, but that stills violates the LSP.
The language I use doesn't support generics so I can't go for Document<T>
either where T
defines the override contract parameter.
I could solve the problem by not inheriting from Document
at all and use composition instead, but it feels weird given ExternalDocument
still is a Document
specialization.
Any guidance?
EDIT:
Just to give a little more context, local documents can be overwrote by a local/user process. External documents are a reflection of documents existing in an external system. I want to communicate the fact that we do not have authority over external documents. The state of those documents is updated in response to remote system events and I want to be able to correlate every state change with a corresponding externalEventId
.
Note that some local document operations remain valid on the external ones though, like assigning the document, etc. I'm also trying to keep the business logic within the model as much as possible to avoid an anemic domain model.
After thinking a little more about it I think I may have conflated both "overwrite" operations as one although overwriting a local document & external document are actually distinct processes. I think we could make a parallel between this and having multiple kinds of locks: they can all be opened, but all in very different ways that would be hard to generalize.
Therefore, so far the most logical route seems to be splitting the current concrete Document
into Document
(abstract base class) and LocalDocument
. The overwrite
operation would be implemented on both LocalDocument
and ExternalDocument
. Both implementations could leverage an internal overwrite
implementation living in the Document
abstract class for parts of the process that are similar.
Obviously clients would have to know what type of document they are dealing with in order to process an overwrite
.
Any new suggestions in light of those precisions?