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.
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.
Thank you.
Would be lovely to have a blog post on how you do it. I'm sure others will benefit from your knowledge and experience.
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.
That's a good point. I should have probably made it clear that my criticism is towards those that use rather recent code (Mojolicious, for example, requires Perl 5.10) but refuse to use CPAN. If you use something that requires an relatively updated version of Perl, you can opt for CPAN.
The situations you describe will usually involve old interpreters, old environment, old everything. In that case, you won't be able to use Mojolicious or the likes of it anyway.
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.
The point was: Mojolicious (since we're still on that, as a good example) is *quite* modern, and is likely used by people who are not technically constrained to sticking with old infrastructure, which prevents them from going to CPAN as well.
So saying they're able to use it but not the rest of CPAN implies lack of knowledge and experience, rather than the possible technical constraints Adrian was speaking of.
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.
Of course you're satisfied, Otherwise you wouldn't keep using it. :)
In the specific case of Mojolicious, I've explicitly specified that it won't suffer a lot of ailments other projects do because of the skilled developers - so that's obviously not something I'm going to contend.
I've seen a lot of closed-source no-deps projects, in many companies (not just those I've worked at) and they always had at least one problem or the other which was caused but lack of dependencies or could have been fixed by allowing dependencies.
I'm sure there are examples on CPAN, but I won't be able to point at them because I don't use "no-deps" projects. I'm sure others could.
Excellent example for a situation I actually encountered quite a bit. A few previous workplaces required CentOS.
In this case you either don't count on the OS (and you can set up Mojolicious/Catalyst/Dancer/Moose/whathaveyou) or count on the OS and be afraid of using a lot cool things - Mojolicious being just an example.
I've seen way more sysadmins that say "it's too modern" than "meh, it's zero deps, we can use it".
Now, if you change them to "it's okay, it's zero deps", then you're empowering the problem that Ovid mentions: the sentiment of using something *only because* it has no deps and halting there from using other things.
If you change them to "it being modern is a GOOD thing, stop being so fucking afraid", then you got them using it and able to use additional features, plugins, and functionality that is based on more CPAN modules. Hell, even maybe other stuff on CPAN that are beyond the scope of their web framework or web chrome over their app.
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.
Dear god, where do you work?
I don't understand what you mean... what switch has no other framework managed to do? Require 5.10 (thanks to a good backport)?
I think other frameworks simply don't *require* newer Perls.
Then again, this might actually be a selling point for Mojolicious. "Hey, we only use modern shit. Update your fucking Perl, grand{p,m}a!"
I would totally buy into that. I am NOT kidding. :)