As of posting this blog article I just released Annotated Container 1.5. Since publishing Introducing Annotated Container - Part 2 I've added a lot of functionality to the library.
- A comprehensive bootstrapping system
- Extensive logging of what actions Annotated Container is taking
- An event system
- Ability to implement your own custom Attributes to configure your Container
Annotated Container is turning into a feature-rich project I'm going to use in a production-like application. But, this post isn't going to be discussing features or even looking at code. This post talks about the things that I've learned along the way.
What I've Learned
The majority of my side projects start out with the intent of learning something. Of course, I want them to be useful but the primary purpose is to broaden my knowledge about software development. This project started out the same and I wanted to share what I've learned.
Statically Analyzing PHP is Hard
When this project first got started it was really an experiment in using nikic/PHP-Parser and I was interested in doing something with Attributes. Combine that with my love for Dependency Injection and the project was a natural fit to start learning. In the beginning I was trying to statically analyze everything. Even deriving values that should be put into Attributes through static analysis, without ever having to instantiate the Attribute. A somewhat misguided goal that wound up being incredibly hard to implement... good luck determining what a constant value is supposed to be through static analysis alone. That was just one of the very hard problems I was attempting to tackle. Eventually I moved to a system that was part static analysis and part runtime reflection.
Going through the exercise makes me appreciate, even more, tools like vimeo/psalm, phpstan/phpstan, and rectorphp/rector.
Dependency Injection Testing is Hard
One of the things I strive for in my professional and personal projects is for the code to be well tested. What that means is different for different apps, I'm not a strict adherent to 100% code coverage, but it should be sufficient. Testing through all the different scenarios to analyze a codebase and then recursively autowire dependencies for them is hard. It is hard in the sheer amount of fixture code that has to be written. It is hard in that a lot of the stuff that I'm doing is testing collections, which adds a lot of testing boilerplate. It is hard in that as the testing fixtures become more mature they also become more complex to emulate real-life scenarios. It is hard in that each backing container has their own, nuanced way of doing things.
All of this adds up to a complex test suite that has to be cared for as much as, if not more than, the codebase itself. This isn't especially uncommon but testing dependency injection has a unique set of constraints that makes it more difficult compared to other testing I've done.
Project I'm Most Excited For
I've created a lot of side-projects throughout my time as a programmer. Hell, I started my career in software development because of a repo for a shitty, homebrewed framework on GitHub. Most of the projects I've created have been for my own personal amusement or to learn something. For the most part I haven't really cared if other people use them or not.
This project feels different.
I think there's some real value provided by AnnotatedContainer. Functionality that, at least right now, isn't widely available in the PHP ecosystem. That functionality can help keep your codebase easier to reason with, better abstracted from vendor lock-in, and potentially more secure with proper use of the
ParameterStore functionality. Throw in the multiple ways of dealing with alias resolution and, while admittedly bias, I believe that's a helluva package right out of the gate.
As I mentioned, I'm really excited about Annotated Container. It consumes most personal project work at this point and I have a lot of plans for it. As time wears on and the basic functionality of my side projects are implemented I tend to lose interest. Annotated Container has been the complete opposite. The more I implement the more I see the potential value. I'm excited to see where I can take the project after another year working on it. The Project Roadmap will continue to act as a general guide for what's coming in the project's future.