24 September 2010

Trying to use Trac...

So, in part because at work we have a need for task/issue management software, I've tried to get educated on the various open-source options in that area. It seems like there are two main choices: Trac or Redmine (I also ran across one with a beautiful user interface called Integria IMS but because of various internationalization issues I didn't explore it much).

Trac is the standard issue tracker in the Python open source world, and since I'm blessed to be able to spend virtually all of my time writing code in Python these days, it was the first thing I looked at. Naturally, like almost all issue/bug/task trackers, Trac has all the standard features like entering a ticket, having types, statuses, and so forth. From the fact it's widely used and the fact that it's implemented in Python, it was definitely my default choice. Whatever system we use at work we'll probably spend a lot of time customizing, so the Python thing is big.

Then a co-worker here in Japan mentioned Redmine. Redmine is newer than Trac but has a lot of the same features (as do the others). In general the interface to Redmine feels a lot more up-to-date than Trac's (it's not that Trac's interface is bad, it's just a pre-Web-2.0 kind of feeling, whereas Redmine used a lot of more interactive widgets in it's UI).

When I started looking realistically at what we would need to do in order to adopt either one of these company-wide for managing the tasks of 300 people, I realized that a lot of the things we needed were related to scale. While open source projects can have scale in terms of users, I don't think either project is really set up for creating thousands of tasks per month. In particular, we clearly need to have:
  • Ability to create new tasks by importing from spreadsheet (it just doesn't make sense for anyone to have to click "Create New Task" 1200 times)
  • Ability to batch edit tasks (when the above goes wrong, you have 600 tasks to change from "New" to "Assigned")
  • GANTT charts (i.e., a graphical representation of tasks over time). Open source projects are notoriously lax about schedules. We work in production, and our production managers need good ways to see exactly what's going on.
  • Task dependencies. If you know about about CG production, it's very pipelined: the animation can't start until the layout is done, etc., so you want a way to declare that Task F depends on Task C.

None of the above are particularly specialized; they're certainly all features that have been implemented in project management software (e.g., Microsoft Project or FastTrack Scheduler) for decades. But, surprisingly, Trac has zero of the above features (Redmine by default has all except the import).

To be fair to Trac, Trac pushes a plug-in philosophy, and there are sure enough plugins for all of the above (more about that in a minute). I read through several discussions on the Trac site where every one of the above features was pooh-poohed by a Trac developer as "just not important enough to be in core." There are two big problems I had with that.

Issue Management Should Have Scale

Seriously? Ability to multi-select items is considered "not core"?

Maybe it's just because Trac comes from the world of tracking open-source projects; it's fair to say that they probably rarely need to create 600 tickets at once, or update the status of 150 of them. But that's not actually an unusual thing to want to do if you're tracking short-term tasks for a group of 300 people. Those basic, simple software features like multi-select/batch edit or the ability to establish relationships are absolutely central.

I'm totally understanding of the fact that time and attention are limited, and if it was simply a case of "we haven't gotten to that yet" I would have no problem. But a lot of the Trac core developers seem to think they *shouldn't* actually have standardized way to establish a relationship between two issues, which is insane.

Plug-ins Are a Terrible Way to Standardize Architecture

None of that would really matter if Trac's plug-in approach worked well enough, to be honest. OK, sure, you have to download some plug-ins, but hey, all the functionality is there, right?

There are a lot of cases where that would be true. But it's not true in real life, because the core architecture of a system needs to provide the base data items for the plug-ins to manipulate.

Here are the specific ways Trac fails to provide enough common infrastructure to actually make plug-ins to support core features useful:
  • For batch edit, the most common batch edit plug-in only works with custom queries. If you just go to the normal "Show me the isssues" default query you can't do a batch edit. This is because there's no extensibility of the individual item UIs.
  • For issue dependencies, Trac doesn't provide the plugins a standard way to store relationships between issues. Because of this, the plugins try to work around this by using the custom field support which Trac does have. Unfortunately, the custom field support doesn't include a type system, it's easy to fail data integrity (your list of dependent tasks is being stored as a comma-separated text field; there's no way to use the real relational data model).
  • For the spreadsheet-import feature, again, because Trac doesn't provide a type mechanism for custom fields, while the import plug-in does its best to try and support custom fields, there's no way for it to know what the type of the fields added by other plug-ins is. Thus, when you try to import a spreadsheet which records that your task is dependent on Task #1, the text field "1" gets interpreted as a float and becomes "1.0" which then fails the referential integrity check. Your bug tracker is now broken and cannot be repaired from the UI; it's MySQL Query Browser time for you.
  • A group here in Japan called Shibuya Trac wrote a GANTT chart generator for Trac. Unfortunately, it's out-of-date for versions so you'll be Googling for awhile if you want to install it, and for a longer while if you don't read Japanese, the native language of the developers.

Oh and, It's not based on a real ORM

When I actually started looking through the Trac database schema and source code to see why some of the above things were true, I got much more depressed. I realized that just because of history, the Trac project is old enough that it had to grow its own solutions to a lot of problems. They have their own ORM, their own templating system, their own database abstraction layer, etc.

I've spent a lot of time writing apps against Django, the absolutely awesome Python database toolkit. Especially when used with South, Django is a complete Python equivalent to Ruby on Rails. The ORM problem (how to map Python classes to a relational database), the database schema migration problem, and the database backend problem are completely and throughly solved by Django (as they are by Ruby on Rails). And the templating problem is pretty well laid out too. For Trac, they were building an app, so they've solved all those same problems but not as elegantly or cleanly as Django. Their database adapter isn't quite as complete, the ORM is a little more manual, and of course none of those subsystems are as well documented ("Look at the code" is frequently mentioned in the Trac developer docs; Django has awesome documentations even without looking at the code, which I'm now convinced is one of the best signs of quality in a piece of open source software.

Looks like Redmine from here

While Redmine doesn't have spreadsheet import built in, they in general have taken a much more expansive view of what is "core": they treat multi-select as a core UI ability, they treat the ability to declare relationships between issues as a core data structure item (although the core package doesn't specify what type of relationship it is); and they have always had time-oriented views into the data.

I really wish I could use Trac, among other reasons because I don't have any particular desire to use Ruby (nothing against it, I just already know Python very well). But the well-integrated easy-to-support features in Redmine and the lack of same in Trac mean it's just not practical. Either Trac needs to make a much more realistic set of decisions about what features are "core" to their stated mission, or they need to significantly beef up their core data infrastructure so that independently developer plug-ins can truly build on each other without dozens of referential integrity problems cropping up. Given that Trac is a relatively successful project, whose core developers seems pretty happy with the way it works now, I guess I'll have to learn a little Ruby.

1 comment:

Matěj Cepl said...

I know the post is a year old, but let me comment on it anyway for sake of somebody else:

a) If you are talking about the project of this size and this number of issue, you are talking bugzilla, not trac (or redmine). I am working for Red Hat and I can see clearly that bugzilla scales (both in terms of software and user interface) quite well.
b) for creating hundreds of bugs and similar tasks you don't import Excel spreadsheets but run scripts dealing with the issue tracker over XML/JSON-RPC. Both trac and bugzilla can do it just well. There are even python bindings for bugzilla (https://fedorahosted.org/python-bugzilla/, ironically managed by trac ;)).