Design Note 1: Extensibility and sharing knowledge

Coordinator
Sep 3, 2014 at 7:22 PM

Sharing Knowledge

In this post I'm trying to discuss and analyze the various approaches we can take to implement this functionality, in particular in this post I would address the options we have to share knowledge from CSD to a custom code generator, so I explain some thoughts with pros and cons, as always any feedback is appreciated.

To share knowledge from CSD to a custom code generation strategy (say for example a T4 text template) we have to choose between 2 main ways of doing this: a strongly typed fashion, or a weakly typed fashion.
Following I try to address these ways explaining pros and cons.

Strongly Typed Fashion

Use CSD Domain classes
CSD already have its own domain classes to represent our model, this code is generated for us by the DSL tools and we could share domain knowledge with this model.

Pros:
  1. We don't have to write any additional code and the classes are generated by the DSL
  2. We can share same model between Default code generation strategy (the Code DOM one) and a Custom code generation strategy
  3. Versioning should be easy (if you don't remove anything from the model, the client code should never break)
Cons:
  1. The model is comlicated by DSL concepts (in base classes) that should not interest the developer
  2. We should deploy in some way the dll containing domain model classes (figure out how) because the client should reference this dll from it's project
  3. The developer should add this dependency to the project even if this is only a Design time dependency (Note this may not be an issue in VS14 or never version because I think MS is working on some sort of design time dependency vs run time dependency, but is definitely an issue on older versions)
  4. Actually the dll containing the domain model classes contains a lot of other classes so the developer experience is definitely not nice
Use a Custom Domain Model library
We can create a simplified domain model library containing only the meaningful classes to share domain knowledge to custom code generation strategy

Pros:
  1. The developer experience consuming the model could be quite nice, maybe the better one at all
Cons:
  1. We have to create and keep in sync this library with the DSL generated domain model
  2. Mapping code is tricky and error prone (Automapper mitigates a bit this area)
  3. We have different model between various code generation strategy
  4. We have to carefully look at breaking changes and how to handle them
  5. all points 2, 3 and 4 from previous mode still applies.
Use CodeDOM
We can use CodeDOM to share domain knowledge to custom code generation strategy

Pros:
  1. We already build a CodeDOM model from our model in current code generation strategy
  2. Developers of custom code generation strategy does depend on other assemblies
  3. We don't have to figure out how to deploy/version custom assembly
  4. CodeDOM is around since .NET Framework 1.1 so this can be used across various (read supported) Visual Studio versions.
Cons:
  1. The developer experience is at least ugly and Extract info from CodeDOM is really painful
Use Roslyn
We can use Roslyn to share domain knowledge to custom code generation strategy, in fact our domain is about managed code generation and Roslyn is the latest and greatest Microsoft technology about dealing with managed code (even if maybe is not well suited for source code generation scenarios)

Pros:
??

Cons:
  1. We should build a Roslyn model from CSD model
  2. The developer experience is not as bad as using CodeDOM but definitely not good at all
  3. It's not clear whether or not Roslyn is supported in Visual studio versions prior VS14
  4. To me seems like take a hammer to crack a nut

Weakly Typed Fashion

Use XML
We can use XML to share domain knowledge to custom code generation strategy

Pros:
  1. Everybody knows XML and .NET Framework provides a pretty decent set of XML apis
  2. There are nothing to deploy outside of the plugin
  3. Breaking changes effect is a lot mitigated (e.g adding a property on a model and consequently add a new element or attribute to an xml node should not break existing client code)
Cons:
  1. XML is verbose
  2. We have to serialize our model to XML
  3. Client experience is not good as with a strongly typed approach
Use JSON
We can use JSON to share domain knowledge to custom code generation strategy

Pros:
  1. There is great support for JSON in .NET ecosystem (I was thinking about JSON.NET)
  2. There are nothing to deploy outside of the plugin
  3. Breaking changes effect is a lot mitigated (see point 3 of XML pros)
Cons:
  1. We have to serialize our model to JSON
  2. Client experience is not good as with a strongly typed approach
Personally the idea I like the most is using JSON and create a strongly typed dll on client machine by deploying a set of sources (the classes that builds the strongly typed model) but there are some edges I have to inspect.

These are a first bunch of ideas on how we can share knowledge with custom code generation strategy, of curse there are a lot of others ways (and definitely smarter ones) so I'm asking some feedback on this.

Regards, Max
Coordinator
Sep 4, 2014 at 7:18 PM
Max,

This is a very thorough analysis. Many thanks! I've been researching and diagramming the whole CSD solution source code to better see how everything interacts. Once complete (soon), I will be better prepared to provide feedback on your suggestions. I hope others with DSL knowledge will take a look at your analysis as well and provide some of their own feedback.

I'm also going to include my solution analysis documents to this project to help others get a better grasp of this project.
Coordinator
Sep 11, 2014 at 2:03 PM
Max,

The whole process that represents how this extension functions is pretty complex, so it might help to explain some basics. I will try to summarize at a high level, but it is likely you are more familiar with this process than I am (based on your original and well thought out post). Please add corrections if I am wrong.

[In the extension code itself]
  • We have a DSL model that defines the domain classes that all CSD models will be based from. This includes relationships, constraints, elements of the CSD designer (ConfigurationSection, Comment, etc).
  • This DSL model is passed to code generators (T4) to generate these domain classes.
  • These classes are compiled and will be used to hold data about the user's CSD model.
[For Developer]
  • The domain classes (from above) are filled with data from the developer's .CSD model.
  • The code generators use data from these classes to generate the code, schema, etc.
In your original post, you are describing the process where the domain classes are filled with CSD data to be used (shared knowledge) for code generation? I just want to make sure I understand correctly.
Coordinator
Sep 11, 2014 at 6:25 PM
Hi andym

First, I'm not an expert on custom dsl, but I've looked into code for some time so I think I have a higher level idea about what is happening and when, first of all we have our custom tool which VS trigger when file generation is needed (the class is CsdFileGenerator registered with the main package ConfigurationSectionDesignerPackage).
In order to work properly when you create a new csd file, the file should have the CsdFileGenerator set as a custom tool so visual studio knows which generator invoke.

At this moment we generate 3 different kind of output : cs/vb, xsd, config (note that .diagram are handled by the DSL tools) with 2 different kind of generators: cs/vb is generated by a CodeDOM generator, xsd and config are generated through a T4 template.

When we start to generate code we load our model using the dsl api, our generators use our model, so the whole point of the post is to find the best possibility to pass our domain knowledge to custom code generator (note that pass out model to custom code generator requires that the client developer should add a reference to the dsl dll)
Coordinator
Sep 12, 2014 at 2:35 PM
That makes perfect sense. Thank you for the clarification Max.