In working on MCsla I have learned quite a few things. Obviously I had to learn the ins and outs of MGrammar, MSchema, MGraph and the various related command line tools. But that’s not really the interesting part, because that sort of knowledge is specific to a bunch of unreleased tools and so is transitory.
What is more interesting is learning about the process of building a runtime that works off metadata. Which leads to learning about what metadata is needed for a runtime. Which leads to learning about how you get that metadata – where it comes from.
In my simplistic worldview I thought I’d create a single DSL to create metadata for my runtime. And this is what I’ve done in my MCsla prototype, but it really isn’t sufficient for any long-term real effort.
Because my DSL describes business objects. It doesn’t describe details about the UI, or about the data access layer (DAL) or any data mappings into the database. In my prototype I am inferring enough information from the metadata to create a basic UI, a limited DAL and some data mappings, but this is only useful for a prototype.
The conclusion I’ve come to is that any real CSLA .NET application runtime will require a number of related metadata schemes:
- Business object description
- UI description
- DAL description
- Data mapping description
If you create a single DSL to cover all these at once I think you’ll be in trouble. The trouble will come in at least two forms. First, this single DSL will almost certainly approach the complexity of C# or other 3GLs, and at that point why use a DSL at all? Second, such a DSL would almost certainly break down walls around separation of concerns. Let me talk about this second point further.
One of the primary strengths of CSLA .NET is that it encourages clear separation of concerns. The business layer supports numerous UI layers at one time – Web Forms, WPF, ASP .NET MVC, Silverlight, Windows Forms, WCF services, Workflows, etc. Similarly, the business layer doesn’t know or care how or where the DAL gets the data, as long as the DAL can provide create/read/insert/update/delete operations.
It is a virtual certainty that you’ll need a different DSL for ADO.NET EF than for raw ADO.NET (connection/command/datareader) data access layers. Similarly, you’ll probably need a different DSL to describe a web UI, as opposed to a XAML-based UI. The technology semantics are so different that it is hard to imagine a single DSL that encompasses both UI styles (at least one that is rich enough to make the end users happy).
As a result, I suspect we need a different DSL for each technology of each layer of the application architecture. And that’s OK, because it is a good bet that Microsoft will create a DSL for ADO.NET EF (as an example), so we don’t need to. That’ll probably cover at least item number 4 in my earlier list.
The role of the “DAL description DSL” is probably to map the items in the business DSL to the items in the data mapping DSL.
Already it becomes clear that some DSLs (like any DSL for ADO.NET EF, or for a framework like MCsla) will exist in their own world, for their own narrow domain. And that’s fine, because that is the point of a DSL.
And at the same time, it becomes clear that we’ll need to create cross-DSL DSLs to bridge the gaps between different DSLs. So that hypothetical “DAL description DSL” would be specific to both MCsla and the data mapping DSL.
To put it another way, it seems to me that we’re looking at two types of DSL. “Real” domain languages, and “glue” domain languages. Domain languages that target a specific domain, and domain languages that target the gap between other domain languages.
I suspect the end result, is that to create a comprehensive runtime, the runtime will need to pull in metadata for each layer of the application, and for the description on how the layers interact. And a developer will need to learn 4 or more DSLs to describe the various layers of the application. And tooling will need to evolve to validate the various inter-connected bits of DSL code so we aren’t left catching mis-matched bits of DSL input at runtime.
To summarize: this DSL/runtime stuff is very cool, but it seems to me that it will take years of maturation before everything comes together in a really productive manner.
One caveat: clearly you could limit the flexibility of the architecture/runtime and simplify the problem space and thus this multi-DSL issue. My fear though, is then you are no different from CASE and many other similar failed concepts of the past – so that seems rather uninteresting to me.