Beyond Domain-Driven Design

Inheritance problems

DSL doesn't allow inheritance which fits most OOP developer's mental model. While DSL has IMPLEMENTS keyword which is used for "standard inheritance" only objects outside DSL can be inherited in this way. DSL supports mixins for code reuse in the small and is has-a inheritance model with can-do interface implementation.

Aggregates should be modeled using composition, so for example Person, Employee, Waiter objects should be modeled as:

module Inheritance
{
    root Person
    {
        string Name;
    }
    root Employee
    {
        date StartedWorking;
        Person *Person;
    }
    root Waiter
    {
        Employee *Employee;
    }
}

which is standard relational modeling (actually we would model this slightly differently, but that's beyond the point). Using the snowflake concept these relations can be flattened into an expected object and results in an actual object in the mind of the OOP programmer

module Inheritance
{
    snowflake WaiterObject from Waiter
    {
        Employee.Person.Name;
        Employee.StartedWorking;
    }
}

When we want to use this WaiterObject to do something we usually want to register an event with him which would look like

module Inheritance
{
    event ServeTable
    {
        WaiterObject Waiter;
        string Table;
    }
}

In the back-end we want to attach event processor to this event and process it accordingly.

Data context interaction

This kind of pattern can be recognized in the DCI paradigm. Person plays a role of a Waiter in WaiterObject context. We are reasoning about its interaction with the system through the ServeTable domain event. We are modeling interaction with the system with objects appropriate for that interaction.

In the DCI paradigm aggregates would be recognized as Data, snowflake would be recognized as Context and domain event would be recognized as Interaction.

Model view presenter

DSL has extensive support for MVP paradigm with fully functional implementation on top of WPF. Problem with MVP inside DSL is that while you can create fully functional applications this is mostly useful for business line applications.

With time we will expose more and more of the MVP DSL to allow developers even greater integration with existing MVC-like frameworks.

Reporting

DSL has support for Report, Olap cube, Linq, Sql and many more concepts which expose powerful data access and report generation features.

Very complex reports can be created with few lines of simple DSL and integration with powerful third party reporting engines.

Report and Olap cube concepts don't use unsafe code, so they can be used even in basic packages.

To create a generated PDF document one must define report data and template. Data is defined by sending it from client and running LINQ queries with specifications to find other data. Template is defined in Templater library which was part of the Platform, but was separated into another product.

List of waiters that started working after specified date can be created as:

module Inheritance
{
    report WaiterList
    {
        date After;
        WaiterObject[] Waiters 'it => it.StartedWorking >= After';
        templater CreateReport 'Waiters.docx' pdf;
    }
}

Since Templater has similar philosophy, Waiter.docx template is as simple as it could be, but not simpler ;)