Cartoon avatar of Charles Sprayberry
cspray.io

Annotated Container v2.2

In the first few weeks after I released Annotated Container v2 I was able to continue making good progress with the library. I wound up releasing a v2.1 and a v2.2 version. The 2.1 release isn't particularly exciting from an end-user's perspective. The v2.2 release includes a few interesting pieces that I'm excited about getting into the codebase and improving in the future. This article looks into those features and what they mean for the future of Annotated Container.

Validate Your Container

One of the things I've thought about since I decided to use attributes, and again when I changed caching from JSON to XML serialization, is adding the ability to validate conditions on your container. I'm super excited that v2.2 adds the foundation for this functionality with a new CLI command! If you run...

./vendor/bin/annotated-container validate

Your ContainerDefnition will have a variety of logical constraints applied to them and any violations will be output to your terminal. A logical constraint violation is where your container configuration is highly probable of having an error. Severity of errors aren't equal to one another and neither are logical constraints. Right now, there are 3 levels of constraint violation.

  • Critical

    When there is a very high level of confidence that a configuration will result in a fatal error that is likely to throw an exception. You should not ignore these constraint violations and fix them ASAP.

    An example of a Critical violation could be having multiple definitions for the same service. This might happen if the #[Service] Attribute is added and the same service is added with the functional equivalent.

  • Warning

    When an error has a possibility of causing undefined or ambiguous behavior but may not cause an exception we mark the violation as a warning. I would treat these violations similar to Critical violations and prioritize fixing them quickly.

    An example of a Warning violation could be having many services implementing a shared interface and all marked as primary. In this situation Annotated Container could not guarantee how alias resolution would occur.

  • Notice

    If a violation doesn't cause a fatal error nor results in undefined behavior, but still represents some misunderstanding or misuse of the framework, it will be marked as a notice. These type of violations shouldn't cause errors when running your app, but it likely means there's a misunderstanding about how your container is configured.

    An example of a Notice violation could be marking a static method for service preparation. The method will still be invoked properly, however methods attributed with #[ServicePrepare] are invoked on an object instance and not a class method.

Right now, there are a handful of checks for low-hanging fruit. I have a lot of plans for improving this portion of the framework. Including adding more checks, allowing custom checks, and improving robustness of validation code. For now, it is exciting to start moving forward with the beginnings of a static analysis tool for verifying your container!

Adding a Third Supported Container

Unlike basically all of my other projects I actually want to have other people use Annotated Container. I've put a lot of time and effort into this project. I also believe that there's real value here. I also believe that Annotated Container will never reach its full potential without an active community that includes more than 1 person in it. It is why this subject dominates my blog activity, and I've even screencast creating a microframework with the project. I'm still learning how to do this self-marketing thing and have a lot to improve.

One thing I know for certain, the project will never get any real traction without supporting Laravel and Symfony. These 2 frameworks dominate the ecosystem and if you'd like your project to get used, ignore them at your own peril.

That's why I'm really excited that v2.2 brings support for the illuminate/container library! This is the same container used by Laravel, and is a huge step towards supporting that framework. At some point, I'm planning on writing another library that will integrate Annotated Container with a Laravel-powered app in an idiomatic way a Laravel developer would expect.

In addition, the next container I play on supporting is Symfony. I've already started digging into how their container is built and hope to have support in v2.3 or v2.4.

Improving Custom Parameter Stores

This is a subject that deserves its own blog post. If you checked out "Autowiring and Annotated Container", one of the examples includes an attribute that looks like: #[Inject('...', from: 'env')]. When you define an inject attribute with a from: parameter you're specifying a ParameterStore implementation that the value should be pulled from at runtime. There's a built-in parameter store for retrieving environment variables, and you can provide your own implementation.

Previously, providing your own implementation of a ParameterStore was a bit clunky if it has constructor dependencies. Providing a ParameterStoreFactory in these situations didn't feel intuitive and could be a lot better. Now there's a DelegatedParameterStoreFactory that improves that experience and lays the foundation for continued improvements with developer experience.

Looking Forward to v2.3

I'm starting to narrow down what I expect to deliver in v2.3. I expect Symfony support, better caching, and improved logical constraints to be the highlights. I'm really excited about this project. I expect to put out more blog articles and screencasts as I work on getting v2.3 ready for a release.