There has been some discussion this week about forks of pieces of Mojolicious. Frustrating discussions over what is proper and how to discourage forking. It has been a long week to be honest (and thankfully the recent incident has been peacefully resolved, see postscript).

But then finally, just today, I’ve chosen to see things a different way. I’m really happy to see what lengths people are willing to go to in order to use Mojolicious. This includes addressing a perceived need for streamlining by taking a maintenance burden onto themselves and forking that code that which they need. They see the value in Mojolicious’ code, if not the value in the toolkit as a whole.

There is a definite victory for us there. Mojolicious contains code worth having and worth using. Imitation is, after all, the sincerest form of flattery.

We have seen forks of Mojo::Base (the object system), Mojo::DOM (the HTML/XML DOM parser), Mojo::JSON, Mojo::Template, Mojo::EventEmitter, Mojo::Date. There are probably others we’ve missed. We haven’t yet seen a fork of Mojo::IOLoop, which surprises me, seeing as it is my favorite part of the Mojo toolkit.

Another we haven’t seen forked is Mojo::UserAgent, which is probably the one we are asked most often to spin out. Why is that? Because to do so you’d need to first have to fork Mojo::Base and Mojo::IOLoop. You would need all the Mojo::Transaction and Mojo::Message classes and subclasses of course. Now with the message classes you would need to fork Mojo::JSON and Mojo::DOM since messages have handy access to these representative forms of their content.

To test it you would need some simple html runner class, something ultra small, not a framework per-se just a handler. The rarely discussed Mojo class fits that bill, so you could fork it too. Then since you would need to test the real-time features of Mojo::UserAgent you would need a server class, since testing nonblocking calls with true mock server is near impossible. So you would fork Mojo::Server::Daemon.

With the Daemon server and a Mojo micro-app you could now test Mojo::UserAgent, but how do you actually write the tests? You need to start a server and attach it to the user agent. It so happens that Test::Mojo can handle this for you. It would then be nice to have convenient test methods built in to simplify the testing, DOM and JSON parsing for example. Test::Mojo has these and once again you see the need for Mojo::DOM and Mojo::JSON too.

At this point you have most of the Mojolicious distribution. Mojolicious, the web framework itself, is only a few more classes on top of these building blocks.

Even for us, spinning out these modules would be hard. Not just from the sheer effort of maintaining it either. For example, recent refactoring in the transaction classes would have spanned a large number of these proposed distributions had they been separated. The time in preparing and coordinating the releases (let alone the hassle it would have taken for users of the dependent classes to uniformly upgrade) would have been incredible. As it was, I’m sure most of our users had no idea the refactoring happened, and in time they will be pleasantly surprised by the features we will be able to offer them now that we have.

Now you could accuse this of being a Majestic Monolith post, maybe it is. But as of Monday March 22, 2016 the entire Mojolicious distribution is only 8491 lines of code. It doesn’t have that characteristic quality that most people fear from monolithic projects: bulk. Indeed Mojolicious has been steadily getting smaller over time, even as the feature set has increased. This doesn’t include tests of course, because with 11237 of them it would make the framework look a lot more bloated than it is.

So yes, it may seem a bit odd to install a web toolkit just to get a JSON parser, and well, perhaps it is. But why are you using JSON? For many people it is the data interchange format of the web. Why not try out Mojo::UserAgent? It lets you do nice things like

say $ua->get('api.metacpan.org/v0/release/Mojolicious') ->res->json->{version};

This is all the more true of an HTML/DOM parser library. Surely that data came from or is going to the web. By comparison (and only to counter the idea of size), consider for example HTML::Tree and its dependencies. They total almost the same number of lines of code as the entirety of Mojolicious. Plus they require a compiler. Should you then need one, and unless you have Perl 5.14+, you still don’t have a user agent. Mojolicious really is amazingly tiny for all the features it boasts.

So now having argued that forks of all but the most peripheral classes are really out of the question for the complexity reason, we can get to our actual concern for forks: the quality of our code and yours. Sadly most of the forks of Mojolicious classes are out of date. We don’t doubt the intentions of the fork projects, but they are usually only one person. Mojolicious has a development team, a large community, and an incredible track record of bug fix speed. Downstream modules may not pick up on those as quickly.

But of course we can only respond to bug reports if we see them. Our real fear is that a critical bug may be reported to one of these forks. If the bug doesn’t get reported back to us how can we get the fix to our users too? Even if it does, the gears turn slower and it takes longer for us to address issues. This isn’t an abstract fear, both cases have happened.

Mojolicious has gotten to be the high quality code that is in such high demand because of this dedication to quality. We hope you will value this dedication more than a few bytes on your hard disk. And who knows, once you’ve installed it for Mojo::JSON or Mojo::DOM, maybe you’ll start to use Mojo::UserAgent or Mojo::IOLoop too.

Postscript:

I had written this post even as there was some controversy over a forked module. The incident has brought to light one use-case for a fork: compatibility with older Perl versions.

While we still would prefer to discourage forks, we can understand that there do remain some needs for Mojo toolkit modules on Perls older than 5.10, our current minimum support version. Indeed in the past there was a blessed fork of the entirety of Mojolicious with the goal of 5.8 support. That effort has concluded as its author no longer needed it, however, since it was only ever on GitHub and was clearly named mojo-legacy, it is unlikely that new users will confuse it for the true Mojolicious distribution. From that example, we can concede the notion that such projects have validity. But please come and talk to us first if you would like to maintain such a labor of love.

Also, it really has been a long week for me, please keep the comments civil and respectful. I’ll be moderating a bit more tightly than usual.

Nota Bene: the forks this article refers to do not include github forks, those are really a different concept and only cursorily related. We value contributors and before you can Pull Request, first you must fork. The intent is the issue; when you fork on github, you do so to merge.