aboutsummaryrefslogtreecommitdiff
path: root/blog/dependency-hell-2014-11-20.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'blog/dependency-hell-2014-11-20.markdown')
-rw-r--r--blog/dependency-hell-2014-11-20.markdown105
1 files changed, 105 insertions, 0 deletions
diff --git a/blog/dependency-hell-2014-11-20.markdown b/blog/dependency-hell-2014-11-20.markdown
new file mode 100644
index 0000000..f9eab55
--- /dev/null
+++ b/blog/dependency-hell-2014-11-20.markdown
@@ -0,0 +1,105 @@
+---
+title: Dependency Hell
+date: 2014-11-20
+---
+
+Dependency Hell
+===============
+
+A lot of the problem that I have run into when doing development with
+nearly any stack I have used is dependency management. This relatively
+simple-looking problem just becomes such an evil, evil thing to tackle.
+There are several schools of thought to this. The first is that
+dependencies need to be frozen the second you ever see them and are only
+upgraded once in a blue moon when upstream introduces a feature you need
+or has a CVE released. The second is to have competent maintainers
+upstream that follow things like semantic versioning.
+
+### Ruby
+
+Let's take a look at how the Ruby community solves this problem.
+
+One job I had made us need to install **five** versions of the Ruby
+interpreter in order to be compatible with all the different projects
+they wrote. To manage the five versions of the Ruby interpreter, they
+suggested using a widely known tool called
+[rbenv](https://github.com/sstephenson/rbenv).
+
+This isn't actually the full list of rubies that job required. I have
+decided not to reveal that out of interest of privacy as well as the
+fact that even Gentoo did not ship a version of gcc old enough to build
+the oldest ruby.
+
+After all this, of course, all the dependencies are locked using the gem
+tool and another helper called bundler. It's just a mess.
+
+There are also language design features of ruby that really do not help
+with this all that just make simple things like "will this code run or
+not" be determined at runtime. To be fair, Python is the same way, as is
+nearly every other scripting language. In the case of Lua this is
+*beyond vital* because of the fact that Lua is designed to be embedded
+into pretty much anything, with arbitrary globals being set willy-nilly.
+Consequently this is why you can't make an autocomplete for lua without
+executing the code in its preferred environment (unless you really just
+guess based on the requires and other files present in the directory).
+
+### Python
+
+The Python community has largely copied the ruby pattern for this, but
+they advocate creating local, project-specific prefixes with all of the
+packages/eggs you installed and a list of them instead of compiling an
+entire Python interpreter per project. With the Python 2-\>3 change a
+lot of things did break. This is okay. There was a major version bump.
+Of course compiled modules would need to be redone after a change like
+that. I think the way that Python handles Unicode in version 3 is ideal
+and should be an example for other languages.
+
+Virtualenv and pip is not as bad as using bundler and gem for Ruby.
+Virtualenv very clearly makes changes to your environment variables that
+are easy to compare and inspect. This is in contrast to the ruby tools
+that encourage global modifications of your shell and supercede the
+packaged versions of the language interpreter.
+
+The sad part is that I see [this pattern of senseless locking of
+versions continuing
+elsewhere](https://github.com/tools/godep) instead of proper
+maintenance of libraries and projects.
+
+### Insanity
+
+To make matters worse, people suggest you actually embed all the source
+code for every dependency inside the repository. Meaning your commit
+graphs and code line counts are skewed based on the contents of your
+upstream packages instead of just the code you wrote. Admittedly,
+locking dependencies like this does mean that fantastic language level
+tools such as [go
+get](https://golang.org/cmd/go/#hdr-Download_and_install_packages_and_dependencies)
+work again, but overall it is just not worth the pain
+of having to manually merge in patches from upstream (but if you do
+think it is worth the pain contact me, I'm open for contract work)
+making sure to change the file paths to match your changes.
+
+### The Solution
+
+I believe the solution to all this and something that needs to be a
+wider community effort for users of all programming languages is the use
+of a technique called [semantic
+versioning](http://semver.org/). In
+some lanaguages like Go where the [import paths are based on repository
+paths](https://golang.org/doc/code.html#PackagePaths), this may mean that
+a new major version has a different repository. This is okay. Backward
+compatability is good. After you make a stable (1.0 or whathaveyou)
+release, nothing should be ever taken away or changed in the public API.
+If there needs to be a change in how something in the public API works,
+you must keep backwards compatabilty. As soon as you take away or modify
+something in the public API, you have just made a significant enough
+change worthy of a major release.
+
+We need to make semver a de-facto standard in the community instead of
+freezing things and making security patches hard to distribute.
+
+Also, use the standard library more. It's there for a reason. It doesn't
+change much so the maintainers are assumed to be sane if you trust the
+stability of the language.
+
+This is just my \$0.02.