How I ended up rewriting the MediaWiki SubPageList extension:
At the beginning of this year, it was still somewhat controversial in the Wikidata development team that concepts such as the Single Responsibility Principle, Inversion of Control and Interface Segregation are generally a good idea and practical to implement without creating more problems then they solve. Parts of the MediaWiki community reject those principles in a rather fanatical religious way, and certainly at that time, no one was supporting them very openly.
As I was still pretty new to these ideas and had never “gone all the way” with them, the resistance of nearly everyone in my direct environment caused me to be extra careful in adopting them. I decided to do a breakable toy project, in which I could blatantly ignore the sceptics and try out these practices in full. That way it would be evident if they where practical in the context of MediaWiki development, and it would show if the result would be as clean as I was hoping, or as opaque as the sceptics where predicting.
As breakable toy project I picked creating a redesign of the SubPageList extension. The moderate size of the extension was one factor in this decision. Another was the bad sate it was in. It had started as a rewrite of the SubPageList3 extension. And while initially it was certainly cleaner, the code ended up rotting quite badly over time. A reason for this was the main code residing in a single transaction script like class, that just grew and grew with various options, ending up with insane complexity. Other reasons including lack of tests, and contributions from people not well versed in software design (me). Doing a rewrite project would thus end up fixing this mess, assuming it went well.
The rewriting process
I started with the rewrite in February. My main interest at the time was finding out if full dependency injection was feasible in an extension that hooks into MediaWiki at multiple locations, and how this could be done in a clean way.
After doing the initial high level design and implementing the dependency injection mechanisms, I lost interest in this toy project for quite some time. It took till June before I picked it up again and finished most of the data access and domain layer implementations.
The old version of the extension was using the ParserHooks class, provided by the ParamProcessor library. This class is very poorly designed and had been deprecated. I’d been thinking of creating a nicer alternative, and decided to do just what as part of this toy project. The result was the ParserHooks library.
All what was left to do was implementation of presentation layer code, which is not my favourite thing in the world, so I ended up not working on the code for another few months. This month I re-discovered the rewrite once again and figured I really ought to get it finished now. So I threw myself on the presentation layer code to be written.
Surprisingly this turned out to be quite a bit of fun. This is probably due to my approach in which I just turned domain objects into wikitext based on services which I created in test driven fashion. Which allowed me to create all the functionality without ever loading a wiki page in my browser.
This was a quite educational little project for me. I’m quite happy with the result – even though it contains a lot of first attempts at certain approaches, the resulting design and code quality are generally good (at least by my current understanding).
There are a few things that are markedly sub-optimal that I’d do different now, and are prime candidates for improvements later on. Those are however not critical, local, and easy to fix, hence I have not bothered with them yet. Compared to the issues before the rewrite, these are really just nitpicks though.
After 7 months of on-and-mostly-off work and 123 commits, I finally merged in my development branch into master yesterday. It is nearly fully backwards compatible (I dropped some silly features), fully tested, and in such a sate that adding new features to the extension ought to be a breeze from now on. This means you can try out the beta version of SubPageList 1.0 now, by getting the latest master. I will be writing an actual release announcement in the near future, detailing the user relevant changes.