Edgewall Software

Version 3 (modified by cboos@…, 19 years ago) ( diff )

Finished the first draft of the proposal

Trac Object Model Proposal

Introduction

Trac is a a minimalistic approach to web-based software project management. To that end, it features an enhanced wiki and issue tracking system. In addition, it also features:

  • An overview of all the events that happened in the project, by the way of the Timeline
  • A structured definition of the Roadmap for future evolutions of the software
  • A sophisticated Subversion repository browser
  • A search facility that covers all the text content of Trac

The tight and coherent integration of these features is achieved by several means:

  • tracking of a single software repository
  • using a simple relational database to store all the informations about tickets, milestones, changesets and wiki pages.
  • using a unified language to talk about objects in the system, by the way of a wiki syntax (TacLinks) which can be used nearly everywhere:
    • in Subversion commit log messages
    • in Ticket descriptions and comments
    • in Wiki pages and change descriptions
    • in attachments descriptions
    • … This unique approach enables a powerful structuring of the information in the system, yet this can be achieved in a very flexible and informal way thanks to that feature.

In this light, Trac is a semi-structured Wiki, where one can create and modify objects and talk about them

In the following, I'll try to show how those Trac objects are variations on a same theme, both from the data point of view and from the behavioral point of view.

Trac Objects

What can be consider as being a Trac object (TracObject) are:

  • a wiki page (WikiPage)
  • a changeset (Changeset)
  • a ticket (Ticket)
  • a milestone (Milestone)
  • an attachment (Attachment)

Current State

Today, the various Trac objects are quite distinct objects. There is no code sharing between what defines objects and also not so much in the related Modules that manipulates objects.

Indeed, those objects have distinct features. But some degree of unification would actually make sense, both in term of increased functionality and in term of decreased code complexity.

Toward an Unification

What would be a generic Trac object?

  • It would have a unique identity in the system
  • It would have some wiki syntax to describe it (a canonical form and also a shortcut form if possible)
  • There would be obviously a Wiki description of it
  • There would be some properties attached to it:
    • Some would be universal:
      • an author
      • a time of creation
    • Some would be always there for the particular type of object considered
    • Some would be custom properties
  • One would want to be able to attach files to that object
  • After the main wiki content, there could be a change history, a sequence of summary of commented property changes (or just comments)
  • The Wiki content of the object could be modified, so there would be an history of changes, the possibility to make diffs between revisions of wiki (see also TighterSubversionIntegration)

Let's compare these generic feature with those of current Trac objects, and see what additional functionality and usages it would provide.

WikiPage

  • The unique identity is the Wiki page name.
  • The wiki syntax is the one described in WikiPageNames.
  • The Wiki description would be actually the content of the Wiki page itself.
  • Only a few properties are relevant:
    • The universal properties (author and creation time) are there,
    • There's no need for specific properties for a WikiPage (except maybe a readonly attribute?)
    • custom properties could make sense, but as usual with custom properties, their presence and pertinence would be site-dependant.
  • Wiki attachments are there
  • The change history would be contributed comments only, but that would make sense. That feature is mentionned in the MacroBazaar page.
  • Wiki history and revision diffs are there

Changeset

  • The unique identity is the revision number
  • The wiki syntax is changeset:XYZ or [XYZ]
  • The Wiki description is the original commit log entered in Subversion. This is normally not meant to change, though it can sometimes be handy to fix a typo (therefore the occasional use of the svnadmin setlog command). There are 3 possibilities:
    • Keep it as it is (read-only)
    • Enable trac-only modifications
    • Provide the functionality of svnadmin setlog
  • Changeset properties:
    • The universal properties (author and creation time) are those of the commit information.
    • The properties specific to a Changeset could be the list of node changes corresponding to that revision.
    • Custom properties could be used for many things, as a way to annotate the revision. Some ideas are:
      • a boolean compilable flag (true by default, could be set to false to indicate that this revision can't be built)
      • a field indicating the % of successful test cases
      • a QA status
  • Attachments for a changeset also make sense:
    • in case of a build failure, the corresponding errors from the compiler could be attached.
    • patches that applies to that revision
  • A change history for a Changeset, wouldn't be that extreme? Actually, the contributed comments could be used for code reviews, another long standing request (#YYY TODO)
  • Wiki history and diffs would be usefull if the changelog is to be modified

Ticket

Introducing an object hierarchy was indeed the initial motivator for this proposal. While thinking about request for MasterTickets (#886), it struck me that Milestones could be seen as a kind of tickets.

(I explained elsewhere (#919) the reasons why I think a categorization of tickets can be important. However, the approach taken in that proposed patch, is, well, just a patch.)

A hierarchy of ticket classes would better serve the purpose of a categorization. It can achieve a better repartition of the specific properties. The relationships between these categories could also be done in a modular way.

First I'll describe the generic ticket as I did above for the other Trac objects, then I will describe a hierarchy of tickets.

  • The unique identity for a ticket is its number
  • The wiki syntax is ticket:XYZ or #XYZ
  • The Wiki description for that object is the Ticket description
  • The ticket properties:
    • The universal properties (author and creation time) also apply here
    • The specific properties would be:
      • The short summary
      • The keywords
      • An optional due time
      • Assigned to…
      • Cc field
    • Custom properties as usual
  • Attachments for tickets are there
  • The change history is there
  • The wiki history and diff would be usefull if the description is to be modified

A generic event can be used to dispatch some information immediately, or to indicate some future event (this needs to be coupled to #ShowFutureEventsInTimeline — oh, by the way, what about #TicketAliases ?)

Then, I would propose the following subclasses:

  • a TaskTicket: something to be done about something
    • Additional specific properties:
      • Severity: what is the impact of this task?
      • Priority: what's the most urgent task among the urgent tasks?
      • Milestone: to what Milestone object does it relate?
      • The related component(s) (well, a Component could also be a Trac object…)
      • Status (opened/closed)
      • Resolution: in which way the task has been completed
  • ProblemReportTicket would be a simple subclass of TaskTicket
  • EnhancementRequestTicket would be a simple subclass of TaskTicket
  • MilestoneTicket: a collection of Tasks that will happen sometime (due time either set or opened)

Other possible Ticket types:

  • Information: just to pass some news around (its due time is present)
  • Deployment: a specific build has been made available

Attachment

  • The unique identifier for an attachment would be its filename, plus the unique identifier of the object it is attached to.
  • There's currently no wiki syntax associated to an attachment, though in #944, I propose the attachment:filename. This currently works only from the Wiki of the parent object, the one to which the file is attached. What would be needed would be: attachment:<TracLink>:filename, where TracLink would specify the parent object.
  • The Wiki content would be the optional file description
  • Properties:
    • The universal properties also apply for attachment
    • The specific properties would be:
      • The size
      • The mime-type
  • Ok, attachments for attachments. Now that does not make sense…
  • Change history would probably be overkill
  • Wiki history and diff would probably be overkill here too

But have a look to the TighterSubversionIntegration proposal to see that those last features would in some cases prove usefull…

Component

This would be a subtype of a WikiPage. Therefore it would share most of what has been said for WikiPage.

In addition, there would be specific fields, like a list of repository paths describing the component in term of software artifacts.

This would allow the following features:

  • automatically relate a Changeset to the affected components.
  • filter the Changesets in the Timeline to those belonging to a component

This is just an example of a new type of Trac object. It may or may not sounds like a good idea, but by the way of the object model, its implementation would essentially focus about how it would interact with the Changeset and Timeline modules.

See also TracReleaselist for the Release object…

Summary

The above correspond to the following hierarchy:

  • TracObject
    • WikiPage
      • Component
    • Changeset
    • Ticket
      • Task
        • ProblemReport
        • EnhancementRequest
      • Milestone
      • Information *
      • Deployment *
    • Attachment/File

Implementing Trac Objects

For processing Trac objects and for the logic associated to them, there would be a corresponding Module subclass (see TracPluggableModules).

Therefore, the Trac object hierarchy outlined above will closely corresponds to a hierarchy of Python Module classes:

But not only that, the Trac object hierarchy will also correspond to a specific object model for the schema in the database.

There is essentially two approaches for the object-relational mapping:

  • For a class, have multiple tables, one for each level in the hierarchy, and join them on the shared identifier. The root level contains also the type of the object.
  • Have a table for each class, with common column names

Each solution has its pros and cons. I will adopt the first approach here, to get things started.

Common to all the Trac Objects, there would be a main table and some auxilliary tables:

-- TracObject
-------------

CREATE TABLE trac_object (
       id               text PRIMARY KEY,
       type             text,
       time             integer,        -- the time it was created
       author           text,
       description      text,
);

-- for the change history of any TracObject
-------------------------------------------

CREATE TABLE object_change (
       id               text,
       time             integer,
       author           text,
       field            text,
       oldvalue         text,
       newvalue         text,
       UNIQUE(id, time, field)
);

-- for the custom fields associated to any TracObject
-----------------------------------------------------

CREATE TABLE object_custom (
       id               integer,
       name             text,
       value            text,
       UNIQUE(id,name)
);

CREATE TABLE object_custom_multi (
       id               integer,
       name             text,
       value            text
);

Each Trac object would eventually have an extension table, to represent its specific fields:

-- Ticket (or Milestone)
------------------------

CREATE TABLE ticket (
       id               text,
       summary          text,
       keywords         text,
       duetime          integer,
       owner            text            -- who is this ticket assigned to
);

-- Task (or PR/ER)
------------------

CREATE TABLE task (
       id               text,
       severity         text,
       priority         text,
       milestone        text
);

-- Report
---------

CREATE TABLE report ( 
       id               text,
       title            text,
       sql              text
);

-- WikiPage
-----------

CREATE TABLE wiki ( 
       id               text,
       readonly         char(1)
);

Note: the Changeset doesn't need anything in addition to the TracObject fields.

Finally, there would be auxilliary tables for some objects:

-- For Changeset
----------------

CREATE TABLE changeset_node_change (
       id               text,
       path             text,
       change           char(1)
);

-- For Component
----------------

CREATE TABLE component_path ( 
       id               text,
       path             text
);

Summary

This proposal aims both at a simplification of the current Trac implementation, which contains a different data representation for each Trac object, and at enhanced functionalities, because the rich functionality that is currently available for Ticket (attachments, change history, custom fields) would be also available for WikiPage, Report, Changeset, Attachment/File and of course, subtypes of Tickets, like Task and Milestone.

This does not mean that all these objects are interchangeable, or that any specific functionality would be lost in the process. Quite to the contrary, each module could focus on what makes it unique, and in which ways it can interact with the other modules, leaving to the generic Module all the shared functionality.

ChristianBoos

Note: See TracWiki for help on using the wiki.