I am working on a desktop application that deals (among others) with applying read / write permissions to confidential documents (MS Word).
For a document, multiple permissions can be defined. For example:
Also, the set of permissions for a document should be retrievable in order to be presented on the user interface.
Furthermore, the document can be signed (with a certificate) by the current user of the application (the author of the documents).
Recently (after having some behaviour-less domain objects and some business / application services), I have come up with the following:
interface IConfidentialDocument {
void AddPermission(Permissions permission);
BunchOfPermissions Permissions { get; } // all defined permissions
void Sign(User currentUser);
... other operations (like ShareToUsers, SendViaEmail)
string Path { get; }
}
class Permission {
User User { get; private set; }
PermissionType Type { get; private set; } // Read, Write, Full etc.
... other members (for time bounds etc.)
}
The problem is that the IConfidentialDocument has to be implemented using the Word Interop library. I could not figure a nice way to wrap the Word Interop functionality and hide its corrupt design under a simpler model, as the one presented above.
I was thinking of implementing IConfidentialDocument as a WordDocument that delegates the work to a Microsoft.Office.Interop.Word.Document. The latter would be passed in the constructor of the WordDocument. This one would be created by a ConfidentialDocumentFactory.Create(string path). The concrete factory would depend on Microsoft.Office.Interop.Word.Application and so on...
The business is actually slightly more complex. It also involves sending documents to their permitted users (via email) etc. What I've done until now is relying on a set of business services and application services to perform most of the logic - the ConfidentialDocument thus being quite behaviour-less. But, as I have said, I am searching for a better design.
Any idea is welcome :)
Thank you!
Some references (not enough reputation to add the links):
The question is too much general, and I don't understand why WordDocument : IConfidentialDocument is bad. It can be allocated in the separate module and considered to be an adapter.
Ok, I'll try to express my thoughts.
With respect to DDD you should make your own model clear as possible.
MS Word uses its own model containing notions such as User, Permission and Document. So it is necessary to make model translations between your entities and ones presented by MS. There are some points of interest that should be considered.
What relations exist between your model and MS Word model? For example, if someone modifies permissions of MS Word directly (bypassing your app), can your app always properly react to this changes? And vice-versa. So, at first I would determine relations between models and infer some restrictions.
Does your app supports any other document types/vendors (OpenOffice)? You can analyze details depending on concrete document vendors and separate it from your own model.
Should you always load "real document" in memory when creating your app document object? I consider, no. Hence, proxy fits good.
Are there some basic document fields or states which are common for all documents regardless to physical document type? If yes, than basic abstract class "PhysicalDocumentState" as a field of document object will fit that good.
I propose something like this:
I use words like "Service", "State", "Facade" for referencing to corresponding patterns.
Probably, you need not to implement WordDocument, WordPermission, but:
The only problem now is in determintaion of simple and transparent interface of WordFacadeService and in separating of restriction control responsibilities between WordState and WordFacadeService.
Finally, I have no idea why you should use Anemic Domain Model in described case.
I will be glad if it helped.