0

I am about to implement a document generator. I am insisting on following the Open-Closed Principle, what brings me some trouble. The requirements are as follows:

  • there will be multiple document types (i.e. agreement, the power of attorney)
  • there will be multiple document formats (i.e. XML, JSON, HTML, PDF)
  • each document type requires a different set of data to be present on the document (i.e. client details, plenipotent details)

Due to my choice of following Open-Closed Principle, I would strongly like to avoid using switch statements. That means I need to introduce some abstractions and implementations for particular types of documents and types of formats.

Is it necessary to provide m x n class implementations, where m is the number of document types and n is the number of document formats? I feel that this is the wrong way of doing it. Could you, please, give me some hints how to design such document generator properly?

Vijayanath Viswanathan
  • 8,027
  • 3
  • 25
  • 43
Dawid
  • 763
  • 1
  • 8
  • 17
  • I never think about always respecting a certain principle. You shouldn't be so focused on O/C or any other _guideline_, you should be focused on understanding the Domain and design based on that . Value objects and proper aggregates are the key here. – MikeSW Oct 05 '17 at 17:55
  • What do you mean by saying "proper aggregates"? Could you, please, provide some example? – Dawid Oct 06 '17 at 09:08
  • 1
    Proper aggregates means you need to identify correctly each document model as seen by the domain. Basically you need to understand each detail of each document with its own constraints and rules. It has nothing to do with code, OOP, SOLID etc. You need to understand how the domain thinks and approaches things, i.e you need to become a domain expert, at least on this specific topic. Think like the domain, using the domain's own language. No classes, functions etc in sight. – MikeSW Oct 06 '17 at 16:10
  • Did you consider Acyclic Visitor pattern? https://stackoverflow.com/a/11437892/1168342 – Fuhrmanator Oct 08 '17 at 04:28
  • 1
    m x n modules comes from OCP. Like @MikeSW says, getting the domain right is better. I'd make it work properly, then consider refactoring to something that is less fragile if a new format or document type comes out. – Fuhrmanator Oct 08 '17 at 04:31

2 Answers2

0

As the behavior of each format is completely different the good design would be to create different classes for each by implementing a common interface, say 'IFormatter'. You can inject the interface 'IFormatter' to the client class which needs to call document formatter. You can do the responsibility of object creation in different ways. One would be a simple factory method (Personally I am not a big fan of factory method). Another way is with the chain of responsibility. You can chain the object creation when a match found it will create that corresponding object.

In either way, once you build the client class you would never need to modify it again. If you want to format document to another format then it is as easy as creating a new class by implementing 'IFormatter' interface.

Vijayanath Viswanathan
  • 8,027
  • 3
  • 25
  • 43
0

I will give you some hints

  • If every document type uses at least one different concept and has different business constraints, create one class for each type. Don't sweat about DRY. The only reusables should be the value objects used to encapsulate each detail of the document.
  • Html, PDf etc are import/export formats. At best , metadata associated with the actual document. If it's important, you can have a Value object like FormattedContent which has 2 properties: Format and Content

About switch.. you have rather weird constraints. But you can use a dictionary instead, no switch! And perhaps an Abstract Factory.

MikeSW
  • 16,140
  • 3
  • 39
  • 53