Martins Design Study

From CSSEMediaWiki
Revision as of 21:54, 10 August 2010 by MartinvanZijl (Talk | contribs)
Jump to: navigation, search

Contents

Overview

My design study is based on the "Patchwork Metrics" Eclipse plugin. This is a plugin for gathering "process metrics", such as time spent programming, time away from keyboard, amount of code written, and other useful metrics.

Patchwork Metrics runs in the background and collects metrics while the user is developing with Eclipse. From time to time, the user will want to see reports on the process metrics gathered by Patchwork Metrics. Therefore, a reporting interface was written to enable this. In this design study, I aim to redesign the reporting interface to fit the OO wisdom described in COSC 427.

I wrote the reporting interface myself, but without good OO wisdom in mind. The interface works, but is not very extensible. For instance, it would be difficult for other developers to to create new types of reports or new views and layouts without modifying the existing codebase. This violates to Open closed principle.


Categorization of Metrics

In Patchwork metrics, the metrics were divided into three main categories:

  • Activity (which activity the developer is performing). This could include testing, developing, designing, and other activities.
  • View (how much time the developer spends viewing different classes).
  • Class (metrics specific to each class, such as "how often was the class edited?", or "what is the cyclomatic complexity of this class?").


Use Cases

These are the use cases which drove the design changes I made.

Use Wizard to Create Report

The user can use a menu option or button to show a wizard (made of different pages) which allows them to create a report. There should be an option for creating any type of report mentioned above (in Categorization of Metrics).

  • There is a menu option in Eclipse called "Patchwork Metrics Report".
  • User clicks that button.
  • A "Wizard" (http://en.wikipedia.org/wiki/Wizard_%28software%29) is shown. The user navigates through the wizard and chooses the type of report they want to generate and set its parameters.
  • Once the user finishes the dialog, the results are displayed in a graphical format (a chart or graph).


Extend to Create New Report Types

A third-party developer should be able to add a new report type (and a wizard for this report) without modifying the existing codebase (following the Open closed principle).


Export Report Results to XML Format

The results displayed in the report should be exportable to XML format. Ideally, this should be extensible enough so that a third-party developer can add a new type of file format for the report to be exported to. (Sounds like the Visitor pattern).

Use Cases

The reporting interface would be used as follows:

  • The user should be able to generate a report for any date range.
  • The user should be able to generate a report for any metric defined by the plugin.
  • The user should be able to edit an existing report, by changing the date range. The report display should update to reflect the new date range.
  • The user should be able to add or remove metrics from an existing report. The report display should update to reflect the new date range.
  • The user should be able to save a report as some sort of file (XML, CSV, anything will do, really).

Initial Design

A diagram of the initial design of the reporting interface is shown below.

Martins-original-diagram.png

Flaws

The flaws in the initial design include the following:

  • There are some "support" classes which are not linked to any other classes. This surely must violate some design principles. TODO: Find these. The classes include: Support, ActivityReportTest, and ActivityReportAction.
  • ActivityCategory is not linked to the report.
  • The ActivityReportWizard class does not allow the containing of sub-forms. It is all packed into one huge form. This is inconvenient - it would be good to allow a wizard with multiple forms. It does allow for one page, but not many.
  • The ActivityReportWizard class and ActivityReportWizardPage class both contain the ActivityReport object, making changes to it. This does not smell right!
  • ActivityCategory is unused! This class is supposed to dictate which metrics appear in the report.
  • ActivityCategory should perhaps be either a Composite or a Decorator. It is neither at the moment.
  • There is no way to export to XML or any other file format. A new class should be introduced for this.
  • The showChart() method of the ActivityReport class has a terrible Switch statement smell! Here are the details:
public void showChart() {
       String title = "";
       if(chartType.equals("activity report"))
           title = (new StringBuilder(String.valueOf(title))).append("Activity Report for ").toString();
       if(chartType.equals("class activity"))
           title = (new StringBuilder(String.valueOf(title))).append("Class Report for ").toString();
       if(chartType.equals("view activity"))
           title = (new StringBuilder(String.valueOf(title))).append("View Report for ").toString();
       title = (new StringBuilder(String.valueOf(title))).append(System.getProperty("user.name")).append(" from ").append(DateFormat.getDateInstance().format(getStartDate())).append(" to ").append(DateFormat.getDateInstance().format(getEndDate())).toString();
       String windowTitle = "Patchwork Metrics report";
       String xAxisLabel = "Part";
       String yAxisLabel = "Time";
       DefaultCategoryDataset dataset = new DefaultCategoryDataset();
       GenericStorageObj storageLayerDataSet = null;
       if(chartType.equals("activity report"))
           storageLayerDataSet = createActivityChartData(getStartDate().getTime(), getEndDate().getTime());
       else
       if(chartType.equals("class activity"))
           storageLayerDataSet = createClassChartData(getStartDate().getTime(), getEndDate().getTime());
       else
       if(chartType.equals("view activity"))
           storageLayerDataSet = createViewChartData(getStartDate().getTime(), getEndDate().getTime());
       else
           return;
       String category;
       Integer timeSpent;
       for(Iterator iterator = storageLayerDataSet.getNestedObjects().iterator(); iterator.hasNext(); dataset.addValue(timeSpent, "Time Spent", category))
       {
           IStorableObj obj = (IStorableObj)iterator.next();
           GenericStorageObj tuple = (GenericStorageObj)obj;
           category = (String)tuple.getField("part").getValue();
           timeSpent = (Integer)tuple.getField("time").getValue();
       }
       org.jfree.chart.JFreeChart chart = ChartFactory.createBarChart(title, xAxisLabel, yAxisLabel, dataset, PlotOrientation.VERTICAL, false, true, false);
       ChartFrame frame = new ChartFrame(windowTitle, chart);
       frame.pack();
       frame.setVisible(true);
}


Note also how the JFreeChart chart is created. This is a good candidate for a Factory Method.

Improved Design

A diagram of the improved design of the reporting interface is shown below.

Martins-improved-design.png

Changes Made

The following are the changes I made to better conform with OO Design principles.

  • The "support" classes which were not communicating with other classes have been removed. Support and ActivityReportTest have both been removed from the package. ActivityReportTest should have been created in a separate "test" package. ActivityReportAction is still required, but has been left out of the diagram, as it relates to higher-level Eclipse Plugin code and is not really part of the core reporting module.

Patterns Used

In the improved version, I used the following design patterns:

  • Added a set of ActivityCategory objects to the ActivityReport class to track the categories shown. Added appropriate methods to enforce the Law of Demeter.
  • To enforce Separation of concerns, I created a GUI class to handle the View of the report. This would allow updating the report internals and then updating display as well. Before, the only time that SetStartDate() and getEndDate() were called was in the save() method of the ActivityReportWizardPage class (which meant that after creating the report, the dates could not be changed). TODO.
  • The getActivityReportChartTypes() or the ActivityReport class creates and returns a set. Perhaps this should be made a static set or an Enum used instead. Perhaps it could even be abstracted into a Strategy. We can see there are 3 types of reports: activity, class, and view. At the moment, ActivityReport has three methods which operate in parallel: createActivityChartData(), createViewChartData(), and createClassChartData(). These should perhaps be absctracted into Factory Methods, and suggests that the Open closed principle is not being used. Anyone wanting to create a new type of report will have to edit the existing code. TODO.
  • Perhaps different categories could be represented as a Decorator?

Discussion

The design project was to improve the reporting interface for the "Team Patchwork Reporting Application". TODO.

Personal tools