Edgewall Software

Changes between Version 3 and Version 4 of TracObjectModelProposal


Ignore:
Timestamp:
Mar 11, 2005, 6:26:53 PM (19 years ago)
Author:
cboos@…
Comment:

Rewritten and simplified, after the having worked on #1242

Legend:

Unmodified
Added
Removed
Modified
  • TracObjectModelProposal

    v3 v4  
    44== Introduction ==
    55
     6=== What is Trac? ===
     7
    68Trac is a ''a minimalistic approach to web-based software project management''.
    79To that end, it features ''an enhanced wiki and issue tracking system''.
    8 In addition, it also features:
    9  * An overview of all the events that happened in the project, by the way of the ''Timeline''
    10  * A structured definition of the ''Roadmap'' for future evolutions of the software
    11  * A sophisticated Subversion repository browser
    12  * A search facility that covers all the text content of Trac
    1310
    14 The tight and coherent integration of these features is achieved by several means:
    15  * tracking of a single software repository
    16  * using a simple relational database to store all the informations
    17    about tickets, milestones, changesets and wiki pages.
    18  * using a unified ''language'' to talk about objects in the system,
    19    by the way of a wiki syntax (TacLinks) which can be used nearly everywhere:
    20    * in Subversion commit log messages
    21    * in Ticket descriptions and comments
    22    * in Wiki pages and change descriptions
    23    * in attachments descriptions
    24    * ...
    25    This unique approach enables a powerful structuring of the information
    26    in the system, yet this can be achieved in a very flexible and informal way
    27    thanks to that feature.
     11The tight and coherent integration of its features is achieved by several means,
     12but most notably by the consistent use of a unified ''language'' to talk about
     13objects in the system (the TracLinks).
     14   
     15This unique approach enables a powerful structuring of the information
     16in the system, yet this can be achieved in a very flexible and informal way.
    2817
    2918In this light, Trac is a semi-structured Wiki, where one can create and modify
     
    3120
    3221
    33 '''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.'''
     22=== Trac Object Model ===
     23
     24In the following, I'll try to show that Trac is a manager for typed pieces
     25of informations: the Trac ''objects''.
     26
     27There are many advantages to gain by refactoring the internals of Trac
     28to acknowledge this reality:
     29 * more consitency, less redundancy, code simplication
     30 * spreading the features available for one object to the other objects
     31
     32This updated revision is made in light of the experience gathered
     33while working on the #1242 patch.
     34
    3435
    3536
     
    3738== Trac Objects ==
    3839
    39 What can be consider as being a Trac object (''TracObject'') are:
     40What can be consider as being a Trac object (''TracObj'') are:
    4041 * a wiki page (''!WikiPage'')
     42 * a ticket (''Ticket'')
    4143 * a changeset (''Changeset'')
    42  * a ticket (''Ticket'')
    4344 * a milestone (''Milestone'')
    44  * an attachment (''Attachment'')
     45 * a report (''Report'')
     46 * a source (''Source'')
     47
    4548
    4649
     
    6164
    6265What would be a generic Trac object?
    63   * It would have a unique identity in the system
    64   * It would have some wiki syntax to describe it
    65     (a ''canonical'' form and also a ''shortcut'' form if possible)
    66   * There would be obviously a Wiki description of it
    67   * There would be some properties attached to it:
    68     * Some would be universal:
    69       * an author
    70       * a time of creation
     66  * It would have a unique identity in the system -- {{{id}}}
     67  * It would have some wiki syntax to describe it
     68    * {{{shortcut_regexp()}}}
     69    * {{{canonical_regexp()}}}
     70  * It would be displayed in several ways:
     71    * a ''canonical'' form -- {{{canonical_name()}}}
     72    * a ''shortcut'' form -- {{{name()}}}
     73  * There could be one or several Wiki text attached to the object.
     74    Each would be a '''facet''' of this object.
     75    Some facets are:
     76    * '''content''', appropriate for a !WikiPage and a Changeset
     77    * '''description''', appropriate for a Ticket, a Report and a Milestone
     78    * '''comment:n''' for the n^th^ comment
     79    * '''attachment:file''' for the attachment name ''file''
     80  * There would be some fields attached to it.
    7181    * Some would be always there for the particular type of object considered
    7282    * Some would be ''custom'' properties
    73   * One would want to be able to attach files to that object
    74   * After the main wiki content, there could be a change history,
    75     a sequence of summary of commented property changes (or just comments)
    76   * The Wiki content of the object could be modified, so there
    77     would be an history of changes, the possibility to make
    78     diffs between revisions of wiki (see also TighterSubversionIntegration)
     83  * One would want to be able to attach files to any object
     84  * One would want to be able to comment on any object, just like for a Ticket
     85  * One would want to see the history of the modification of the object
     86    * the edit history of the main facet (see also TighterSubversionIntegration)
     87    * the change history of the value of the fields
    7988
    8089Let's compare these generic feature with those of current Trac objects,
     
    8392==== WikiPage ====
    8493
    85  * The unique identity is the Wiki page name.
     94 * The unique identity is the Wiki page name. -- {{{s/page_name/id}}}
    8695 * The wiki syntax is the one described in WikiPageNames.
    87  * The Wiki description would be actually the content of the Wiki page itself.
    88  * Only a few properties are relevant:
    89    * The universal properties (author and creation time) are there,
    90    * There's no need for specific properties for a !WikiPage
    91      (except maybe a ''readonly'' attribute?)
    92    * ''custom'' properties could make sense, but as usual with ''custom''
    93      properties, their presence and pertinence would be site-dependant.
     96   -- currently present in source:trunk/trac/WikiFormatter.py
     97   {{{r"(?P<wikihref>!?(^|(?<=[^A-Za-z]))[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+(?:#[A-Za-z0-9]+)?(?=\Z|\s|[.,;:!?\)}\]]))"}}}
     98   and in source:trunk/trac/Search.py {{{r = "((^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)"}}}
     99 * The main facet would be ''content'', i.e. the content of the Wiki page itself.
     100 * The relevant fields:
     101   * author and creation time
     102   * a ''readonly'' boolean field
    94103 * Wiki attachments are there
    95104 * The change history would be contributed comments only, but that would make sense.
    96    That feature is mentionned in the MacroBazaar page.
    97105 * Wiki history and revision diffs are there
    98106
    99107==== Changeset ====
    100108
    101  * The unique identity is the revision number
    102  * The wiki syntax is {{{changeset:XYZ}}} or {{{[XYZ]}}}
    103  * The Wiki description is the original commit log entered in Subversion.
    104    This is normally not meant to change, though it can sometimes be
    105    handy to fix a typo (therefore the occasional use of the
    106    {{{svnadmin setlog}}} command). There are 3 possibilities:
    107    * Keep it as it is (read-only)
    108    * Enable ''trac-only'' modifications
    109    * Provide the functionality of {{{svnadmin setlog}}}
     109 * The unique identity is the revision number -- {{{s/rev/id}}}
     110 * The wiki syntax is {{{r"(?P<changesethref>!?(\[\d+\]|\br\d+\b))"}}}
     111 * The main facet is 'content', which is the original commit log entered in Subversion.
     112   See #781.
    110113 * Changeset properties:
    111    * The universal properties (author and creation time) are those
    112      of the commit information.
    113    * The properties specific to a Changeset could be the list of node changes
    114      corresponding to that revision.
     114   * author and creation time are those of the commit information.
    115115   * Custom properties could be used for many things, as a way to
    116116     annotate the revision. Some ideas are:
     
    123123     could be attached.
    124124   * patches that applies to that revision
    125  * A change history for a Changeset, wouldn't be that extreme?
    126    Actually, the contributed comments could be used for code reviews,
    127    another long standing request (#YYY TODO)
    128  * Wiki history and diffs would be usefull if the changelog is to be modified
     125 * A change history for a Changeset, wouldn't that be cool?
     126   Actually, the contributed comments could be used for code reviews
     127   The history and diffs for the commit log are useful once the
     128   changelog becomes modifiable
    129129 
    130130==== Ticket ====
    131131
    132 Introducing an object hierarchy was indeed the initial motivator for this proposal.
    133 While thinking about request for ''MasterTicket''s (#886), it struck me
    134 that ''Milestone''s could be seen as a kind of tickets.
    135 
    136 (I explained elsewhere (#919) the reasons why I think a categorization of tickets
    137 can be important. However, the approach taken in that proposed patch, is,
    138 well, just a patch.)
    139 
    140 A hierarchy of ticket classes would better serve the purpose of a categorization.
    141 It can achieve a better repartition of the specific properties.
    142 The relationships between these categories could also be done in a modular way.
    143 
    144 First I'll describe the generic ticket as I did above for the other Trac objects,
    145 then I will describe a hierarchy of tickets.
    146 
    147  * The unique identity for a ticket is its number
    148  * The wiki syntax is {{{ticket:XYZ}}} or #XYZ
    149  * The Wiki description for that object is the Ticket description
    150  * The ticket properties:
    151    * The universal properties (author and creation time) also apply here
    152    * The specific properties would be:
    153      * The short summary
    154      * The keywords
    155      * An optional due time
    156      * Assigned to...
    157      * Cc field
     132 * The unique identity for a ticket is its number -- {{{id}}}
     133 * The wiki shortcut syntax is {{{r"(?P<tickethref>!?#\d+)"}}}
     134 * The main facet is ''description''
     135 * The ticket fields:
     136   * author and creation time
     137   * milestone and component
     138   * The short summary
     139   * The keywords
     140   * An optional due time
     141   * Assigned to...
     142   * Cc field
    158143   * Custom properties as usual
    159144 * Attachments for tickets are there
     
    161146 * The wiki history and diff would be usefull if the description is to be modified
    162147
    163 A generic event can be used to dispatch some information immediately,
    164 or to indicate some future event (this needs to be coupled to
    165 #ShowFutureEventsInTimeline -- oh, by the way, what about #TicketAliases ?)
    166148
    167 Then, I would propose the following subclasses:
    168  * a !TaskTicket: ''something to be done about something''
    169    * Additional specific properties:
    170      * Severity: ''what is the impact of this task?''
    171      * Priority: ''what's the most urgent task among the urgent tasks?''
    172      * Milestone: ''to what Milestone'' object does it relate?
    173      * The related component(s) ''(well, a Component could also be a Trac object...)''
    174      * Status (opened/closed)
    175      * Resolution: ''in which way the task has been completed''
    176  * !ProblemReportTicket would be a simple subclass of !TaskTicket
    177  * !EnhancementRequestTicket would be a simple subclass of !TaskTicket
    178  * !MilestoneTicket: ''a collection of Tasks that will happen sometime (due time either set or opened)''
     149==== Source ====
    179150
    180 Other possible Ticket types:
    181  * Information: ''just to pass some news around (its due time is present)''
    182  * Deployment: ''a specific build has been made available''
    183 
    184 ==== Attachment ====
    185 
    186  * The unique identifier for an attachment would be its filename,
    187    plus the unique identifier of the object it is attached to.
    188  * There's currently no wiki syntax associated to an attachment,
    189    though in #944, I propose the {{{attachment:filename}}}.
    190    This currently works only from the Wiki of the parent object,
    191    the one to which the file is attached. What would be needed would be:
    192    {{{attachment:<TracLink>:filename}}}, where !TracLink would specify
    193    the parent object.
    194  * The Wiki content would be the optional file description
    195  * Properties:
    196    * The universal properties also apply for attachment
    197    * The specific properties would be:
    198      * The size
    199      * The mime-type
    200  * Ok, attachments for attachments. Now ''that'' does not make sense...
    201  * Change history would probably be overkill
    202  * Wiki history and diff would probably be overkill here too
    203 
    204 But have a look to the TighterSubversionIntegration proposal
    205 to see that those last features would in some cases prove usefull...
    206 
    207 ==== Component ====
    208 
    209 This would be a subtype of a !WikiPage.
    210 Therefore it would share most of what has been said for !WikiPage.
    211 
    212 In addition, there would be specific fields,
    213 like a list of repository paths describing the component
    214 in term of software artifacts.
    215 
    216 This would allow the following features:
    217  * automatically relate a Changeset to the affected components.
    218  * filter the Changesets in the Timeline to those belonging
    219    to a component
    220 
    221 This is just an example of a new type of Trac object.
    222 It may or may not sounds like a good idea, but by the way of the
    223 object model, its implementation would essentially focus
    224 about how it would interact with the Changeset and Timeline modules.
    225 
    226 See also TracReleaselist for the Release object...
    227 
    228 
    229 === Summary ===
    230 
    231 The above correspond to the following hierarchy:
    232  * !TracObject
    233    * !WikiPage
    234      * Component
    235    * Changeset
    236    * Ticket
    237      * Task
    238        * !ProblemReport
    239        * !EnhancementRequest
    240      * Milestone
    241      * Information ''*''
    242      * Deployment ''*''
    243    * Attachment/File
     151 * The identifier for a file or directory is its path
     152 * There's no facet attached to a source
     153 * Fields
     154   * author, creation date
     155   * The size
     156   * The mime-type
     157   * dynamical svn properties
     158 * attachments for files... Why not? One could already do it with
     159   Subversion anyway ({{{svn pset prop -F attachment source}}})
    244160
    245161
     
    249165there would be a corresponding {{{Module}}} subclass
    250166(see TracPluggableModules).
     167That is, some modules would use some kind of Trac objects:
     168 * The !WikiModule is using the !WikiPage object.
     169 * The !TicketModule and the !NewticketModule are using the Ticket object
     170 * The Browser and Log modules will be using the Source object
     171 * etc.
    251172
    252 Therefore, the Trac object hierarchy outlined above will closely corresponds to a
    253 hierarchy of Python Module classes:
     173For the object-relational mapping, I would suggest having
     174a table for each class, with common column names where appropriate
     175(at the very least, the {{{id}}} column).
    254176
    255  * Module (much of the current Ticket code would be moved here)
    256    * Wiki
    257      * Component
    258    * Changeset
    259    * Ticket
    260      * Task
    261        * !ProblemReport
    262        * !EnhancementRequest
    263      * Milestone
    264    * Attachment/File  (see TighterSubversionIntegration)
    265 
    266 But not only that, the Trac object hierarchy will also correspond to a specific
    267 object model for the schema in the database.
    268 
    269 There is essentially two approaches for the object-relational mapping:
    270  * For a class, have multiple tables, one for each level in the
    271    hierarchy, and join them on the shared identifier.
    272    The root level contains also the type of the object.
    273  * Have a table for each class, with common column names
    274 
    275 Each solution has its pros and cons. I will adopt the first approach here,
    276 to get things started.
    277 
    278 Common to all the Trac Objects, there would be a main table
    279 and some auxilliary tables:
    280 
    281 {{{
    282 #!sql
    283 
    284 -- TracObject
    285 -------------
    286 
    287 CREATE TABLE trac_object (
    288        id               text PRIMARY KEY,
    289        type             text,
    290        time             integer,        -- the time it was created
    291        author           text,
    292        description      text,
    293 );
    294 
    295 -- for the change history of any TracObject
    296 -------------------------------------------
    297 
    298 CREATE TABLE object_change (
    299        id               text,
    300        time             integer,
    301        author           text,
    302        field            text,
    303        oldvalue         text,
    304        newvalue         text,
    305        UNIQUE(id, time, field)
    306 );
    307 
    308 -- for the custom fields associated to any TracObject
    309 -----------------------------------------------------
    310 
    311 CREATE TABLE object_custom (
    312        id               integer,
    313        name             text,
    314        value            text,
    315        UNIQUE(id,name)
    316 );
    317 
    318 CREATE TABLE object_custom_multi (
    319        id               integer,
    320        name             text,
    321        value            text
    322 );
    323 }}}
    324 
    325 Each Trac object would eventually have an extension table,
    326 to represent its specific fields:
    327 
    328 {{{
    329 #!sql
    330 
    331 -- Ticket (or Milestone)
    332 ------------------------
    333 
    334 CREATE TABLE ticket (
    335        id               text,
    336        summary          text,
    337        keywords         text,
    338        duetime          integer,
    339        owner            text            -- who is this ticket assigned to
    340 );
    341 
    342 -- Task (or PR/ER)
    343 ------------------
    344 
    345 CREATE TABLE task (
    346        id               text,
    347        severity         text,
    348        priority         text,
    349        milestone        text
    350 );
    351 
    352 -- Report
    353 ---------
    354 
    355 CREATE TABLE report (
    356        id               text,
    357        title            text,
    358        sql              text
    359 );
    360 
    361 -- WikiPage
    362 -----------
    363 
    364 CREATE TABLE wiki (
    365        id               text,
    366        readonly         char(1)
    367 );
    368 
    369 }}}
    370 
    371 Note: the Changeset doesn't need anything in addition to the TracObject fields.
    372 
    373 
    374 Finally, there would be auxilliary tables for some objects:
    375 
    376 {{{
    377 #!sql
    378 
    379 -- For Changeset
    380 ----------------
    381 
    382 CREATE TABLE changeset_node_change (
    383        id               text,
    384        path             text,
    385        change           char(1)
    386 );
    387 
    388 -- For Component
    389 ----------------
    390 
    391 CREATE TABLE component_path (
    392        id               text,
    393        path             text
    394 );
    395 }}}
    396 
    397 
    398 == Summary ==
    399 
    400 This proposal aims both at a simplification of the current Trac implementation,
    401 which contains a different data representation for each Trac object, and at
    402 enhanced functionalities, because the rich functionality that is currently
    403 available for Ticket (attachments, change history, custom fields)
    404 would be also available for !WikiPage, Report, Changeset, Attachment/File and of course,
    405 subtypes of Tickets, like Task and Milestone.
    406 
    407 This does not mean that all these objects are interchangeable, or that any
    408 specific functionality would be lost in the process. Quite to the contrary,
    409 each module could focus on what makes it unique, and in which ways it
    410 can interact with the other modules, leaving to the generic {{{Module}}}
    411 all the shared functionality.
    412177
    413178