Skip to content

RFC: definition DSL

Jiří Pudil requested to merge definition-dsl into master

I've implemented some small changes to make the definition file more idiomatic. It already feels almost like a proper DSL, and the last remaining bits such as new ClassDefinitionBuilder() bugged me, so I've taken it one step further. Or maybe even too far 😅 waiting for your thoughts @jkuchar1 @dkurowski

Step 1: define()

The proposal is to introduce a define() function which hides the builder instantiation:

return [
    define(UserAccount::class)
        ->field('username', 'string')
        ->decorate(new ConstructorWithPromotedPropertiesDecorator())
        ->decorate(new GettersDecorator())
        ->build(),
];

The function can also accept an instance of ClassDefinitionBuilder. This allows application code to provide custom factories that nicely fit into the definition DSL, e.g.:

function valueObject(ClassDefinitionBuilder|string $class): ClassDefinitionBuilder
{
    return define($class)
        ->decorate(new ConstructorWithPromotedPropertiesDecorator())
        ->decorate(new GettersDecorator());
}

return [
    define(valueObject(UserAccount::class)) // <-- 🤩
        ->field('username', 'string')
        ->build(),
];

Step 2: build()

As the next step, the generator infrastructure can accept a ClassDefinitionBuilder and automatically convert it to the resulting definition, so that we can omit the build() call:

return [
    define(valueObject(UserAccount::class))
        ->field('username', 'string'),
];

Step 3: rename 'em all

Finally, I've added aliases to the builder methods so that the whole definition reads like natural language:

return [
    define(valueObject(UserAccount::class))
        ->thatImplements(\JsonSerializable::class)
        ->withField('username', 'string')
        ->decoratedBy(new JsonSerializableDecorator()),
];

I'm just not sure if they should be aliases and the original methods should be deprecated, or if we should rename them for good. We're already making quite some BC breaks in the next release (!40 (merged)), so it's a good time to do another one, but I'm afraid it might require too much effort when upgrading this package in applications.

Edited by Jiří Pudil

Merge request reports