Posts tagged with ironcow
For some reason, for the last year or so, I received occasional notifications about forum posts on my .NET projects over at CodePlex, but never anything about new issues being reported… well, I recently had a look at the issue tracker and found, horrified, that I had dozens of issues that had been sitting there for several months, untouched. Sorry about that. I guess the lessons are:
- For me: check the notification settings on any code hosting website.
- For CodePlex: maybe you guys could add the current number of open issues next to the “Issue Tracker” link in the navigation menu, just like what GitHub and BitBucket do.
Anyway, most of the bugs and feature requests were easy enough, and in a couple days I solved most of them (only 1 got rejected). This included mostly Textile.NET and IronCow. To celebrate this, I also got Textile.NET migrated to a Mercurial source control.
milkify.com domain recently expired, and I didn’t really feel like renewing it. If you look at the (absence of) recent commits in either IronCow or Milkify, it’s easy to understand why: I’m not really working on those projects anymore. And that’s because I’m not using Remember The Milk anymore either.
To be fair, IronCow is pretty stable already – most of the latest changes were configuration management stuff and upgrades to Visual Studio 2010 – so it’s still usable. I’ll be available for bug fixes, of course, but if the guys at Remember The Milk add new features, I would probably not know about it and it wouldn’t be ported to IronCow unless somebody forks the project and submits a patch.
Milkify, however, won’t see any improvements unless somebody picks it up. It’s just not worth it to work on a tool I’m not using myself.
This means I get more time to focus on my new home projects like PieCrust and a couple of other bigger ones in progress.
I created 2 experimental branches for future versions of IronCow.
Check them out!
- “IronCow Mobile” is a branch that adds support for the .NET Compact Framework. Thanks to jwboer for the initial patch.
- “IronCow Local Search” is a branch that adds local search for tasks. We basically cache all the tasks in memory, and handle search queries locally, instead of sending a request to the RTM server and parsing the response markup. The lexical analysis and AST building of the search query is a bit dodgy, as I can’t get a proper tool like ANTLR to work with RTM’s search grammar (probably me doing something wrong), but it’s not too much of a problem right now since search queries tend to be quite short, and we already are significantly faster than a web request.
The source code for IronCow and Milkify are now hosted directly on Codeplex. Anybody can therefore checkout the latest source code and submit patches!
IronCow is a library that wraps the Remember The Milk (RTM) web services. The “upper layer” of the IronCow API is an object model that stays in sync with the server and is designed with data binding in mind.
Of course, one of the things that went into IronCow’s design was testability. IronCow ships with a suite of unit tests that, well, test that the API is working fine. However, there’s another testability aspect: how the clients of your API are going to test their stuff. These are 2 different things:
The easy way to make an API testing friendly is to put everything behind interfaces. This way, the client can replace your stuff with test objects. But for some reason, I don’t feel like adding this kind of complexity to IronCow. It’s a pretty small API, with an object models that contains less than a dozen of classes, and hiding everything behind interfaces would triple the number of classes, add a couple of abstract factories, and more generally confuse clients that would otherwise expect a straightforward API.
- Within IronCow, “design for testability” means I have to be able to mock the underlying client that communicates with the RTM REST API. Then, I can manipulate my objects and check that the correct requests are sent, and that those objects behave correctly according to the responses I give.
- From the point of view of a client, though, “design for testability” means they have to be able to make IronCow behave a certain way, and test that the rest of their application behave accordingly.
Therefore, right now, to use IronCow in a test environment, you can disable the “syncing” behaviour like this:
Rtm rtm = new Rtm(); // You can also pass in your apiKey and
// sharedSecret here but it doesn’t matter.
// From now on, there’s no requests being sent.
When syncing is disabled, the IronCow object model just acts like a “dumb” object tree. Setting the name of a task or adding a new contact won’t trigger a request to RTM. Instead, it will just modify the objects locally, as if it was just a classic simple in-memory object model.
Note that you can’t reenable syncing.
The problem with this is that although the complexity of the public interface stays the same, the complexity of the internal code increases. I find it doesn’t increase nearly as much as when I tried to hide everything behind interfaces though. The other bigger problem is that it’s more complicated for clients to do behavioural testing. For example, if they want to test what happens in their application when a certain action makes IronCow throw an exception, there’s nothing to help them do that… In that case, they have to mock the IRestClient class, and use it with their Rtm instance. There are helper classes and methods to build RTM XML responses, but it’s not what you would call super user friendly (check the IronCow.UnitTests assembly source code for examples of how to use it).
So is this fine? No? Should I bite the bullet, add interfaces, and make this simple API be 3 times bigger and more complex? Is there a third option?