Skip to content

Dependencies

Craig Andera edited this page Jan 24, 2012 · 8 revisions

Dependencies

As mentioned elsewhere, this project depends on Clojure, Ring, Compojure, Enlive, ClojureScript and Domina. Running lein deps will get most of these dependencies, in the usual way, but ClojureScript and Domina are handled a bit differently. Running lein bootstrap will get all of the dependencies as described below.

The problem with releases

The software release process needs a bit of a reimagining. There are several problems with the status quo.

The first problem is that naming releases is hard. In the past we have struggled to impose some kind of meaning on the names that we give to releases of our software. The one common problem with all previous approaches is that, in the end, they are arbitrary. There is a disconnect between changes made to the source code and the name that the new version is given.

This disconnect points to another problem. It is difficult to audit changes between versions. Most of the time we are dependent on a change log which may or may not be accurate. Many businesses will not allow arbitrary binaries to be downloaded from the internet and used in a project without extensive testing and an audit of the changes that have been made. This is currently a very difficult process.

As the user of a library, it is difficult to experiment with the code in the context of the project where it is being used. This is the place where it makes the most sense to do experiments. Depending on the build process for a project, it can be difficult to make a change and then add the changed version as a dependency to our project. Although this can be done, it is usually just hard enough to prevent us from doing it.

Related to this is the difficulty in testing changes which library authors have made but which are not yet released. For software to maintain high quality, changes need to be tested by as many users as possible. Because of the barrier imposed by the release process, busy developers don't have the time to do this important job.

When using a library, if a problem is found, it is time consuming to fix. We have to make the change to the library and then depend on our changed version until the change is accepted into the main project and released.

Finally, we are dependent on the project authors to actually release the software on a schedule that we are happy with. From the author's perspective, they have to struggle with how best to release things so as to upset the least number of people.

Something must be done.

ClojureScript releases

ClojureScript has taken a non-traditional approach to releases.

There is only one source of truth for ClojureScript, the ClojureScript repository. This repository contains a complete history of every change that has ever been made to ClojureScript and who made each change.

Each commit made to this repository creates a new version of ClojureScript.

It is helpful to give names to versions. Names allow us to refer to and depend on specific versions. A Git repository gives each commit a unique name, the SHA. The problem with these names is that they don't have an order. You can't tell from the names which version is newer than another version.

In ClojureScript, ordered version names are generated automatically without being arbitrary. The names are the number of commits on the master branch from the beginning of the project. Occasionally the repository will be tagged with a name like r957. This tag marks the 957th commit to this project.

What we want

For Clojure-based projects there are several things that we have come to expect from our build tools when managing dependencies:

  1. flexible specification of dependent versions
  2. installation on the classpath
  3. portability
  4. automatic retrieval of transitive dependencies

There are also many things we have not been able to easily do:

  1. update library code in our running application
  2. try our projects with changes made to a library
  3. audit changes to a library
  4. contribute changes back to a library

It would be nice if we could have it all.

Git Dependencies

ClojureScript One depends on ClojureScript and Domina as Git dependencies. The install process for ClojureScript One is

git clone [email protected]:brentonashworth/one.git
cd one
lein bootstap

lein bootstrap will get all dependencies for this project. Running lein bootstrap has the same effect as running the two commands:

lein deps
lein git-deps

ClojureScript and Domina are retrieved by cloning their git repositories into the .lein-git-deps directory and then checking out the version configured in project.clj.

The project.clj file for ClojureScript One shows how to configure Git dependencies.

:git-dependencies [["https://github.com/clojure/clojurescript.git"
                    "329708bdd0f039241b187bc639836d9997d8fbd4"]
                   ["https://github.com/levand/domina.git"
                    "c0eb06f677e0f9f72537682e3c702dd27b03e2e4"]]

A Git dependency is a URL for a repository and then, optionally, a tag, commit or branch. Directories that should be on the classpath have to be manually configured:

:extra-classpath-dirs [".lein-git-deps/clojurescript/src/clj"
                       ".lein-git-deps/clojurescript/src/cljs"
                       ".lein-git-deps/domina/src/cljs"
                       "src/app/cljs"
                       "src/app/cljs-macros"
                       "src/lib/clj"
                       "src/lib/cljs"
                       "templates"]

Notice that tasks like trying a branch, testing your project with the latest version of master, working from a fork and contributing changes back to the project are now trivial tasks supported by Git.

The one thing that this approach is missing is the ability to automatically calculate and retrieve transitive dependencies.

ClojureScript One will follow the same model as ClojureScript for releases. If you would like to depend on this project in your own projects then adding a Git dependency as we have done here is the recommended method.

Benefits

The benefits of working with version controlled source code instead of binaries are numerous. Think of the tools that could be created to automate things like testing to determine the newest version of the library that the project will work with or finding out the newest versions of each library that are compatible with each other.

Instead of a mysteriously named black box, every library becomes the source of a tremendous amount of information about the code that you depend on.

Maven

If you don't see any value in the above approach then you may add ClojureScript as a dependency in the usual way.

:dependencies [[org.clojure/clojurescript "0.0-927"]]

Domina and ClojureScript One will also have standard jar releases at some point in the future.

Clone this wiki locally