Wednesday, June 26, 2013

Why I'm Giving up on Ivy (For This Project)

I have been spending a lot of my free time the last few months working on a card game for Android. By free time, I don't just mean "time when I am not at work," I mean "time while the baby is asleep, everything around the house that needs to be done is done, and I have not other social or family obligations to attend to." I have made a point to make time every week to work on it, but so far my best week has still been less than 10 hours of development time. Needless to say, I am looking for fast solutions to my programming problems, hence part of the reason I have chosen Ivy.

At work, I am a Maven guy. I was introduced to Ivy a couple of months ago by a consultant from Vaadin that visited the company I work for. What I liked about it was how easily it integrates with Eclipse, and how quickly you can pull in dependencies. I especially liked that I could pull in dependencies from the Maven repository, which I was already familiar with. A simple ivy.xml file has significantly less lines than a simple pom.xml file. At the time it seemed perfect for my goals, and for the first few weeks that I used it, I thought it was great.

Problems arose once I decided to split my application into two projects. I mostly did this for ease of testing, and because wrestling with the ADT plugin over what JUnit library I wanted to run my unit tests in somehow caused my Eclipse to break in a way that I couldn't figure out for a couple of days and eventually involved deleting my workspace and re-importing all my code in to fix. When I split my code into an Android project and a core project, I remember thinking "No problem, it should be a breeze to import my core project into my Android project with Ivy, cause Ivy's so simple!" Wrong. Let me share the issues I had while trying to achieve this that have led to me giving up on Ivy for this project.

1. Ivy Documentation - There are many complaints about the documentation for Ivy on the inter webs. In truth I thought the documentation was organized well. What makes it difficult to understand is that it is obviously written by somebody to whom English is a second language (at least, I hope that's the excuse!). At the time, I felt like this just comes with the territory of software development these days, and a documenter's ability to write in fluent English is not necessarily an indicator of how helpful the library is going to be. But now the dam is broken and the critiques are flowing. I frequently had to read sentences in the documentation multiple times to understand what was being stated.

2. ANT - Yeah, I should have seen this coming. During my honeymoon with Ivy, I found it so easy to use that I forgot it was a dependency management tool built for Ant. I wasn't thrilled about learning some Ant essentials to build my artifacts, but I had some experience and figured it was a good job skill to learn (although, I think I may have once lost out on a job opportunity partially because my one question for the interviewer during the "do you have any questions for me" section was "why are you guys still using Ant?"). A couple of friends who I complained to about this problem suggested that I use Maven to build my core jar, and import it with Ivy, but I felt dirty just thinking about that, and felt that I should use either one dependency management tool or another.

3. No SNAPSHOTS - This is where the love affair started to end. After getting my core library into my android project, and making my first change to the core library, I built my core again, and resolved my android project and.... my changes weren't pulled in. It turns out by default Ivy will not update a project, or your local cache if there is no change to the revision number. Their expectation is that for every change you make, a new artifact should be created, with a new version number. At least, that's what these paragraphs from their documentation suggest:
To optimize the dependency resolution and the way the cache is used, Ivy assumes by default that a revision never changes. So once Ivy has a module in its cache (metadata and artifacts), it trusts the cache and does not even query the repository. This optimization is very useful in most cases, and causes no problem as long as you respect this paradigm: a revision never changes. Besides performance, there are several good reasons to follow this principle... 
Some people, especially those coming from maven 2 land, like to use one special revision to handle often updated modules. In maven 2 this is called a SNAPSHOT version, and some argue that it helps save disk space to keep only one version for the high number of intermediary builds you can make whilst developing.
It then goes on to describe a property that can be added to your tags to make this work they way people from "maven 2 land" would expect it... which leads into my next point.

4. Ivy  Certainly Does Not Feel Simple - Looking back at the Ivy Home Page, it reads "Apache Ivy is a popular dependency manager focusing on flexibility and simplicity." Flexibility? Yes. There seems to be configurations for everything. Heck Ant itself feels like you're just writing a shell script in xml format. Simplicity I feel I have to disagree with. This being said, I'm not sure if a dependency management tool CAN be simple. Maven is no simple tool itself, and I recall spending plenty of hours, including weekends trying to get projects to build. Of course, at the time I was a junior developer who had never used a dependency management tool in my life. There are a lot of things that Maven does for you automatically that have to be configured in Ivy. By the time I read that in order to get my locally built artifacts to reload each time I resolve I would have to add and extra configuration, I had already had to write special configuration for things that work automatically (if not very easily) in Maven. This includes writing a special resolver in yet another xml file for resolving locally built projects (just happens in Maven), and writing up a publish task in my build.xml file to define how an artifact should be published, after writing up how to build the jar file (Maven just DOES this. It builds a jar for you and publishes it using the groupId and artifactId. And if the default way to built that jar is not to your liking, THEN you can configure it with the jar-plugin).

5. And Then There Were Source Jars...- The final straw for me was tonight when I pressed my trusty "F3" button while selecting a method from my core library. I of course expected to be taken to the source of that method, but was instead shown one of the coding equivalents of the dog from Duck Hunt laughing at you; The Source Not Found page. Oh, and no "Attach Source" button, with a brief message saying it's Ivy's fault you can't attach your own source. I spent the rest of my night looking up and reading multiple Stack Overflow questions from multiple people having similar issues on how to publish and then resolve a jar with a source classifier on it. At some point, this led me to my final reason for dropping Ivy for this project.

6. I Don't Know Ivy - Let's be honest, I hate it when people complain about a tool because they can't figure it out. Sometimes, that's not always the tool's fault. The real reason Ivy is not working for me is because I don't know it.  I could learn Ivy, but since my goal is to develop quickly, my investment in learning Ivy and Ant has long exceeded the time I was willing to budget for setting up dependency management. Later this week I will set it up using Maven because I know it, and am proficient with it (I probably could have set it up in less time then it took me to write this post).

With that thought in mind, I guess it's worth considering who Ivy is written for. I'm sure I will be corrected if I am wrong, but my understanding is that first there was Ant, then there was Maven, and then there was Ivy. I've seen some complaints about Maven, and I'm assuming that there were some long time Ant users who felt that Maven was too auto-magical for them and continued to use Ant. And now Ivy has been written for Ant users. If I'm correct in thinking this way... well, I'm not an Ant user, so I (currently) have not need to use Ivy. Maven works for my needs, and I'm more familiar with it.

I also think it's worth mentioning that I think Ivy is great for single project applications. I have every intention of continuing to use Ivy for proof of concept applications where I just need to throw together a quick, small app. As familiar as I am with Maven, I still feel it's a little verbose for small applications.

So, I tried to be as honest and fair as my experiences with Ivy could allow. Feel free to disagree in the comments, and let me know my level of ignorance for choosing to turn away from Ivy for dependency management.