11

We have two in-house projects, A and B, developed by different teams with B dependent on A. Since source code for both projects is stored in git, I've included project A as a submodule into project B and configured the build system to build both in right order. An alternative solution would be to consume A via a binary repository manager such as Artifactory or Nexus.

I wonder about pros and cons of depending on source code vs depending on binary artifacts. When is one better than the other? So far I managed to come up with following factors, but I am really keen on hearing other opinions.

Depending on source code is better

  • if you don't have a binary repository manager
  • if you need to depend on pre-release version of another project
  • if you need to patch another project
  • because it is easier to browse dependency source code in IDE

Depending on binaries is better

  • to minimize build time
  • to avoid the hassle of setting up another project's build environment
1
  • 1
    In my experience, the possibility to patch another project is key. Sometimes patches are not even to be pulled back to the master (project-specific extensions/modifications). In such cases you'll need to set up a build environment for the dependent project anyway. So, we use source code dependency. But, of course, it depends on your processes/architecture.
    – proskor
    Commented Jul 9, 2014 at 10:45

2 Answers 2

5

I would always recommend binary dependencies over source dependencies. Most of the pros you list for source code can be easily incorporated into binary dependencies as well.

First, it is very quick to set up a Nexus repo on some local server. The benefits of having a binary repo far outweigh the setup effort/cost. This is almost a pre-requisite for the rest of my answer :)

For pre-release versions, your projects should be deploying -SNAPSHOT versions into the artifactory. There can be a nice and clear distinction between versions, such as:

  • projectA-3.2.0-SNAPSHOT : Active development, may change at any time
  • projectA-3.2.0-RC1 : Release candidate
  • projectA-3.2.0 : Production release

All these versions can be stored together in your artifactory. Your projects would know exactly what they are compiling against.

For patches, git is your friend. Fork the repo and put in a patch version number, such as projectA-3.2.1-FOR_PROJ_B. Notice the .1 showing a patch release and also the descriptor. This will also make it easy for the project to pull in those changes back to the master later.

For source code, you can configure your build tool to generate a "source jar" and deploy it alongside the binary jar in the artifactory. Most IDEs can look-up the source jar name and automatically download the source for you.

Another big reason to stay away from source code is that you are tied to the build system, tool-chain and compile-time dependencies of Project A. If you see a build failure in Project B, you have to first investigate if Project A or Project B caused an error. If it was Project A, you have go track down people from that project to fix their build. This adds a lot of overhead to your build cycle.

1
  • Fair enough except for the last point. A git submodule implies that you depend on an exact version of another project. Since dependencies are never updated together with other changes, it is always obvious whether changes to project A or to project B have caused havoc. Thanks for your answer!
    – mkalkov
    Commented Jul 9, 2014 at 8:35
1

I would go for binary dependency, because almost none of your considerations favouring me is without critic:

  • if you don't have a binary repository manager: that is ok, but I do not think it is that difficult to stablish one. In the most basic level, a shared folder where only the people in charge to deciding which version use can write.

  • if you need to depend on pre-release version of another project: metacubed already covered it. Either with source code or binary dependencies, you should stick to a well-stablished version, even if it is pre-release. Of course, when developing against a pre-release, odds are that you will need switch to an updated version often due to bug solving.

  • if you need to patch another project: do you mean that your team is going to patch the project made from another team in the same house? I would say the most sane strategy is tell the other team the issues you have with their project.

  • because it is easier to browse dependency source code in IDE: You should not need to snoop into the inner workings of your dependencies, because it will mean:

    • project A is poorly documented
    • your coders will end using "undocumented features" of project A that may disappear without previous warning at any update.
4
  • 1
    Patching in-house projects: well, it's a planning issue. In our case "in-house" means same organization but different departments and different geographical location. Imagine project A devs introducing a new (buggy) feature. We (project B devs) plan a new release that depends on that feature and in the middle of process discover a bug in it. Our options are (a) patch the bug, make release on time and send the patch upstream, or (b) report a bug upstream, wait until they fix it next sprint, and make our release one sprint late. Sometimes option b is acceptable, sometimes it is not.
    – mkalkov
    Commented Jul 9, 2014 at 8:43
  • I also find myself browsing JDK source code quite often because it makes me better coder, and because sometimes even world-class documentation is not enough. However, this doesn't mean I use undocumented JDK features. The same logic applies to dependency source code. I agree though that this leaves room for misuse. Thanks for your other points!
    – mkalkov
    Commented Jul 9, 2014 at 8:49
  • Regarding your first comment, it seems your system may lead to a scenario where team A launches "Project A 2014 v1", and team B launches "Project B 2014 v1" that includes a "Project A 2014 v1" which is not quite the same than team A launched...
    – SJuan76
    Commented Jul 9, 2014 at 10:54
  • 1
    It's more like "team A releases projectA-1.2.3, and team B releases projectB-4.5.6 which includes projectA-1.2.3-patch1".
    – mkalkov
    Commented Jul 9, 2014 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.