So I have been exploring the idea of de-coupling some of the Athena components from the framework. In other words, make some of them optional and not installed by default. E.g. one of the framework services has a constructor like:
def initialize(
@serializer : ASR::SerializerInterface,
@validator : AVD::Validator::ValidatorInterface,
@annotation_resolver : ATH::AnnotationResolver,
); end
The approach I was thinking of was, say the validator component was optional, that parameter could be typed as AVD::Validator::ValidatorInterface? = nil and would be able to detect that that component is installed to wire it up so it can be provided to the constructor.
However, the problem with this is of course is if that component isn’t installed then the AVD::Validator::ValidatorInterface is not going to exist and the compiler would error because of the unknown type. My original plan to handle this was to have the framework just stub out the type so it exists but doesn’t have any implementation, nor be used as a marker that the component is installed so the @validator would be nil. The main con of that is I’d need to keep track of what types need to be stubbed, might get complicated when they’re not modules due to needing to also stub superclass, etc.
Another idea I thought of, not entirely sold on it as of yet either, is the idea of adding an annotation that would suppress the unknown type error. E.g. @[SomeAnnotationName] @validator : AVD::Validator::ValidatorInterface? = nil would not error if that type is missing at compile time, and just resolve to nil. This approach would be a bit more straightforward and obvious that the type is optional.
EDIT: Or maybe instead of an annotation, could be its own syntax? @validator : ?AVD::Validator::ValidatorInterface? = nil? ![]()
Yet another approach would be to of course leverage {% if ... %} macro to define a constructor that just entirely excludes that parameter if the component isn’t installed, but this just feels less than idea due to how verbose it would have to be, esp if more than one parameter is optional.
Curious what others thoughts are on how to best handle this!