Counter-productive over time

Ovid wrote a post recently on an unexpected result of Mojolicious' "no dependency" policy.

I won't go into the horror stories of people getting yelled at for saying Mojo doesn't support dependencies. Instead, I'll give my opinion on the concept of no dependency, and you could decide for yourself if it relates to Mojolicious or not. I honestly don't care. Obviously, this is not a "don't use Mojolicious" post. In fact, I think it's a cool framework and you should try it out. This post is about my general opinion on the "no dependency" idea. Mojolicious is an example, DBI is another, and there are definitely others (Moose, anyone)?

The whole "NO DEPENDENCY HEAVEN!11" approach to me seems like the PHP "we embedded the code in your HTML!11" approach. Basically, doing something that tries to handle the current situation but in a way that actually ends up counter-productive when technology advances.

Back in the day, web code printed out HTML code. That was horrible. CGI.pm tried to alleviate it by suggesting using functions instead of hardcoded HTML tags. It wasn't much better. Then PHP came along and said "hey, let's just embed the engine code inside the design code!" - everyone was happy. Then we realized HTML coding is actually outside the scope of engine coding (and vice versa), so they were separated. We created templates and had engine code render them using variables. Neat! But now PHP is actually an HTML document that only opens a PHP tag, that runs code that opens a different HTML document, which is an HTML template, and renders it to HTML. That's how all PHP applications are. Suddenly it ain't cool no more. Suddenly it's stupid.

The "no deps" camp (whether in a web framework or elsewhere) tries to handle a similar problem (which is actually temporary, and constrained by technology and willingness), which is the ability to include additional code. It's hard to change willingness (a point which Ovid expresses eloquently), but technology is more manageable. Including dependencies is no longer a hassle: you have local::lib, FatPacker, Carton, cpanminus, perlbrew and Plack. Nowadays, including additional code is actually very easy. In fact, some technologies (such as cpanminus, perlbrew and local::lib) made it extremely easy to install new code instead of bundling it. But hey, you can do both.

Mojolicious is one of the few projects that have such a skilled core team (and lead developer) that they actually can rewrite the entire core, including any required dependency from scratch, and do a damn good job. Unfortunately, this is not the case with most other developers. In fact, even very skilled developers (and there are a ton in the Perl community) prefer not to spend their time rewriting something that is already (possibly, plausibly, probably) well-written, even if they can do an incredible job at it.

This lays the beginning to the consequence Ovid mentions: people are learning from the "zero-dependency" concept to be zero-dependent. They actually start to abhor dependencies. I've seen people coming from that camp try to rewrite DBI. Yes, I really did see it. It was horrible and expectedly it failed.

So what does zero dependency really means? To me, it means you either don't support a lot of features, or have numerous possible bugs, or have rewritten a lot of things, or you don't know how to bundle your stuff, or don't know how to setup Pinto (or you don't understand the reasoning for it), or you don't understand the idea of reusability, or that you're incredibly arrogant thinking you can do better than everyone (and frankly, a few can), or... well, a lot of things which are generally not good practice, by any fair standard.

I honestly don't intend to work on projects that require me to use zero dependencies no matter what. It's a serious - in a term Ovid proliferated - code smell.

Remember, the excuses of "I don't have permissions to install new modules" or "I can only upload stuff here" are no longer relevant since we have tools to bundle stuff, pack them, install them locally and more. Those situations are no longer a problem.

In short: with time, technology changes, and we should have an approach that isn't locked on a certain approach that might change as technology advances.

20 Comments

Excellent post. At Bank of America, we use local::lib to install both our code and our deps, so they both go through the same Jenkins testing and staging process. With good test coverage, even our dependencies are stable, so there's no fear of additional dependencies to solve problems.

I agree. The zero-deps thingie is a bit silly to me, I don't like technical workarounds to social issues.

Though actually there is one tool that I think we're missing that could be a killer app: a web-based CPAN client.

@Leon: I wrote cgipan http://sourceforge.net/projects/cgipan/ many years ago and unfortunately didn't have time to update it. It only can work with Makefile.PL and you have to do the downloads of the tarfiles yourself, and if you'd want to adjust the paths to tar and make, you'd have to do it in the perl script manually. (Dependencies of a module will result in a link to the cpan search site).
But there were actually a number of people who found it very helpful. Some users of shared web space don't have shell access but still can use tools like make.

So I too think it would be a really good idea to write a modern version of cgipan which uses cpan|cpanplus|..., and a configuration file. Some dependencies could be included so it can be bootstrapped.

I'm firmly in the pro-dependency camp for the work that I do, but I think that you're a little unfair to the folk that go the no-dependency route. There are definitely those who know how to manage dependencies - but choose not to because of various sensible reasons.

For example the 'Those situations are no longer a problem' line isn't true in my experience. There are many places that have large chunks of infrastructure tied to certain versions of perl and certain chunks of dependencies. Inserting new stuff or integrating new stuff into those environments is non-trivial. Yes we have great tools now for helping avoid those problems - but if you already have ten years of legacy code then shifting everything over to a new style is non-trivial. In those situations dependency-free set ups can be a godsend.

Yes, Mojolicious does require Perl 5.10, but there is an excellent backport for Perl 5.8. (https://github.com/jamadam/mojo-legacy) Not sure the same could be done (and maintained) for Catalyst and its dependencies with our current CPAN toolchain.

SawyerX, I'm curious if you have some real-world examples of projects that illustrate why the no-deps approach is bad in practice?

For me Mojolicious wouldn't fit in this category because the end product is actually very good and I'm a satisfied customer.

Many Perl users also seem to be restrained by enterprise Linux distributions, which only recently have started shipping Perl 5.10. The latest RHEL for example doesn't even have CPAN.pm installed by default! They usually have to repackage all their CPAN modules into RPMs and clear every new version with managers and a QA department.

Sri, the bit about "can't be done/maintained for 5.8" is pure FUD. To substantiate this I just compiled a fresh 5.8.5[1] with -Dusemorebits and -Duseithreads on linux and successfully got `cpanm Catalyst` to completion[2] under that fresh perl.

[1] Yes, Moose is *again* broken under 5.8.3. It is not due to impossibility of making it work, but due to lack of testers

[2] I had to rerun the install 3 times (no changes to command, just rerun after fail), perhaps a set of undeclared dependencies somewhere, which got pulled in afterwards. More investigation is necessary to get to the bottom of it.

In fact I got one better: the same puny 5.8.5 managed to successfully install Catalyst::Devel on top of Catalyst. Fueled by that success and by my masochistic tendencies I attempted to install MojoMojo[1] as well - that *also* (after a veeeeery long time) succeeded to install *all* of its dependencies[2] without any overrides. Afterwards the tests of MojoMojo itself all failed with what seems to be a packaging error (ERROR. Looks like you need to deploy a database. Run script/mojomojo_spawn_db.pl)

How is that for a scary unstable CPAN?

[1] A well known member of the "CPAN top heavy 100" list: http://ali.as/top100/

[2] I had all -dev C-libs installed on the system from a previous test with MojoMojo on an unrelated perl

You may have misunderstood me there, i was questioning the possibility of backporting Catalyst and all of its dependencies with the current CPAN toolchain. This is not even about Catalyst, any module with more than 100 dependencies would do as an example.

I am not entirely sure what do you mean here... Perhaps I am indeed utterly misudnerstanding. What "possibility of backporting" do you mean here, given that the *need* for such backporting doesn't even exist.

My major problem with dependencies is simple: the lawyers. They want to check everything before we can use it, and thrice before we can redistribute it.

There is a form for each distribution. If everything I need is in a single tarball, I can fill out a single form. But if I grab Moose and all its dependencies, suddenly it's a dozen or two forms I have to fill out.

Needless to say, I'm going to be submitting 100+ forms for an upcoming release. It's still better than trying to do all of this myself. There's no way I could ever replicate the functionality of DBI/DBD::SQLite/DBD::DB2 (yes, two database engines), AnyEvent, Moose, Coro, and many others.

Oh, and to get around that RH/CentOS issue (same on AIX: AIX 7 comes with perl 5.10.1), perl 5.16.1 is part of that set of 100+ forms, much as has already been suggested.

What i mean is that Mojolicious can only be "modern", as Sawyer X put it, because of the good backport. We made the switch to 5.10 over a year ago and so far no other framework has managed to do the same.

Leave a comment

About Sawyer X

user-pic Gots to do the bloggingz