Matthew's Design Study

From CSSEMediaWiki
Revision as of 02:58, 10 August 2009 by Matthew Harward (Talk | contribs)
Jump to: navigation, search

For my design study, I am going to be working to improve the design of my COSC460 project. The project is a plug-in for Eclipse designed to provide a tool for visualising software metrics directly onto source code. The plug-in is written in Java and is approximately 5K LOC.

Contents

Desired Behaviour & Requirements

Requirements

  • Produce a system that can take in metrics information and update a JavaEditor with overlaid decorations.
    • Code Colouring
    • Colour/shape chips
    • ...
  • Multiple metrics/displays should be able to be displayed per file.
  • The system should be able to deal with static and dynamic sources of metrics.
  • XML and an API should be usable to update information.
  • It should be possible to determine mappings/metrics that are applied.

Constraints

  • Eclipse can not open the same type of editor within the same perspective or same window.
  • The JavaEditor may NOT be subclassed. Note this will force us to create a wrapper/strategy for the JavaEditor which can prod at it to gain the additional functionality required.
  • The Eclipse structural hierarchy must be used.

Existing Code Base

This system is my first attempt at developing this system. At first glance it appears fairly logical; however, some more serious OOD issues lurk beneath the surface...

Initial development. Please note some of the composition/dependency connections are wrong.
Initial development with functional groupings.

Design Discussion/Overview

In this section I will briefly discuss each of the current components and their roles. Please note that these functional groupings do not directly correspond to existing packages. The diagrams to the left provide further detail.

  • Plugin: This Singleton class provides a launcher for the Eclipse plugin. It provides all of the initial driving calls to instantiate the underlying document monitor and listeners.
  • Document Monitor: This package provides handling of Java files in the editor, keeping track of those that have been loaded and also as a location to retrieve updated metrics data. Generally, this class relies on Singletons to keep track of the open files.
  • Editor Listeners: These classes listen to the Eclipse editor, in most cases this is effectively the current document's buffer. Each change of state is reported to the EditorListener class.
  • The Model: This set of packages provides a representation of the stored data. A MetricDocument contains all of the metrics, mappings and displays for a single Java file. There can be multiple

metrics represented using multiple mappings in any one document, and each of these may have multiple MetricSections, which represent the an actual appearance of the metric in the editor.

  • Display & Editor Manipulation: This set of classes deal with the current Eclipse editor and provide the functionality to add adornments to the editor. A wide variety of these adornments exist,

they are backed up with appropriate Shape and Color managers.

  • API: These classes provides an Observer interface where external 'Providers' can listen for and then as necessary provide metrics information as requested.
  • Serialisation: This package allows metrics data to be provided and/or converted via a defined XML format.
  • Eclipse View: These classes provide a view that allows users to alter which metric visualizations are currently active and which displays are being used for each.

Existing Usage of OOD Features & Techniques

Areas of Greatest Concern

  • API: Is the architectural model appropriate? Is the use of the Observer pattern correct here? Maybe the MVC should be explored...
  • Model: Are there any possible improvements?
  • String Manipulation: Is there any way to avoid the current String manipulation in Mapping Properties?
  • Display Strategies: Is there any way of simplifying this hierarchy? Are the current methods of instantiation appropriate?
  • Eclipse View: Dynamic updating of data is a concern here.
  • File Instances: Is the current design the most sound way of dealing with Eclipse's editor model (i.e. multiple files, with multiple views).
  • Alternative Languages: What can be done to make the system more modular and appropriate for multiple languages?

First Design

Architecture

The key point to note here is that, if we consider the MVC pattern, the old architecture is clearly wrong as the provider of the Model is being told to update itself rather than informing the View when it is updated. This clearly breaks Tell, Don't Ask and a number of other significant maxims. In order to complete this transformation, the existing single Eclipse plugin will be broken into 3+ or more eclipse plug-ins with defined extension points and dependencies. This alteration will also have a significant affect on the API of the MetricsOverlay plugin.

A component UML diagram of the old and proposed architecture. Each component represents a set or one Eclipse plugin. The blue JavaEditor is an existing component in the Eclipse Java Development Tools (JDT). Multiple data providers can provide metrics information, some may also choose not to use our provided EditorListener and listen directly to the Editor themselves. (Revised 5/8: Now includes constraints and accounts for Tell, don't ask.)

Eclipse Plugin Considerations

  • Eclipse allows the ability to instantiate individual plugins as required at runtime. This functionality has been deemed currently unnecessary.
  • Extension points have been set up for the EditorListener and MetricOverlay plugins to notify others of their functionality.
  • All of the plugins at this point have been defined as singletons, it is intended that any providers intending to provide additional functionality implement their own plug in. Would it be possible to subclass objects in MetricsProvider to make this easier?

The UpdatedEditor Issue

In order for information on the editor that has been updated to flow through the system, a few things need to be considered.

  • In the first design, as it formed a single plugin, all of the data stored in what is now UpdatedEditor was stored in MetricFile with the appropriate metric information for that instance of the file.
  • In order to provide necessary information to the system, data on the updated editor needs to be forwarded through the plug in.
  • We want to maximise component encapsulation while minimising complexity.

Our options, therefore, are:

  • UpdatedEditor is held by MetricsOverlay, this means that EditorListener needs to know about the existence of MetricsOverlay. This seems unnecessary for a simple component designed to create a well-rounded architecture. It should be able to provide its functionality by itself.
  • UpdatedEditor is held by EditorListener. This seems sensible as Keep related data and behavior in one place is conserved. It does provide a slight problem, in that MetricsOverlay needs to know of the existence of EditorListener. This is usually not a problem, but implementations of MetricsDataProvider need not use EditorListener, introducing unnecessary coupling.
  • We create a new plug-in containing information needed by all sections. This adds unnecessary complexity.
  • We accept that the states of both are separate and that they should never know about each other. In order to do this, we must commit the sin of Avoid becomes in the MetricsDataProvider. This has the additional disadvantage that the extensibility of the system is reduced as additional knowledge is required.

I feel the best option is leaving UpdatedEditor in EditorListener and allow MetricsOverlay to see it.

EditorListener component

First attempt for this plugin.

This new plug-in responds to changes in Eclipse by listening to provided listener classes and collating all listen events.

Design Overview

  • Activator - Provides the plug in instantiation.
  • ServiceChecker - Checks available services that can provide dispatches and attaches dispatches as possible.
  • Dispatch + Sublasses - These hierarchy checks Eclipse's hierarchy and listens to the available listeners to generate updates as appropriate, ie if the file type is right etc. Updates are call an appropriate method in EdiotrListener.
  • EditorListener - Forms a part of an Observer pattern providing updates for any registered objects. Constructs an UpdatedEditor object to transfer during a update notification. This object keeps track of the previous state and uses this, with the incoming updates to determine the current state of the editor part that is currently active. If an update is needed, this class notifies any observers. This class also makes sure the ServiceTracker keeps up to date.
  • UpdatedEditor - This data class stores the necessary information for accessing and modifying the editor.
  • EditorState - This enum represents the state of the current editor. There are only 3 states we are actually interested in.
  • AcceptableFileTypeHandler - This class allows the system to change the file types it is interested in. (Note: the default constructor is designed specifically for Java as this is its primary design. This should be subclassed for the Java version).

Comparison to Initial Design

New Features:

  • Now abstracted to new plug in.
  • Listens to a much wider variety of events.
  • Can handle different file types.

Class Comparison:

  • Editor Listener and FileBufferDispatch existed with mostly the same job. Editor listener is now much less complicated as it only produces results from the listening.
  • Other Listeners (Dipatch) are all new, as is the service checker.
  • File handling is no longer completely statically defined as AcceptableFileypeHandler is new.
  • Updated editor is a new type of data object.

Design Considerations

Maxims/Ideas

  • Removing EditorListener from its previous plug in was a result of using Separation of concerns.
  • Getters and setters have been used only where absolutely required.
  • Tell, don't ask is generally practised by all components.
  • Classes that have the potential to be subclassed have protected fields, all the rest are private.
  • I considered a much more heavy weight solution where this plug in kept track of all open pages and made sure they were listened to with an iron fist. However, this level of detail is unnecessary for the updates required. This fulfils Do the simplest thing that could possibly work.
  • I have avoided Premature optimization, several classes contain inefficient code that it is current unnecessary to improve.

Design Patterns

  • Singleton on Activator, EditorListener, ServiceChecker, Two Dispatches.
  • Observer with EditorListener as the concrete observable object.
  • Unclear Mediator between EditorListener and ServiceChecker.
  • Unclear Strategy between EditorListener and AcceptableFileTypeHandler.

Still ToDo

  • Create an abstract superclass for AcceptableFileTypeHandler and sub class for Java/UserDefined. This will clean up that strategy pattern.
  • Should UpdatedEditor be part of this plug in, while it is the logical place to include it, this means two things: 1) If an EditorListener is not used, then this class will not be visible, unless explicitly included, in MetricsOverlay. 2) Currently MetricsOverlay stores the same data + MetricDocument in a MetricFile, this is suboptimal as the UpdatedEditor has to be split up to become a MetricFile. Maybe move UpdatedEditor into MetricOverlay and let EditorListener know about MetricOverlay

MetricsOverlay component

Comparison to Initial Design

New Features

  • Ability to have annotations

New Design Features

  • Comparators for model elements
  • Simplified model

Unnecessary Model Element - MappedMetric

This class was unnecessary, it simply held Mappings and MetricSections. MetricSections are now held in Mapping, this makes the model tidier. Arguably, the previous solution broke the Law of Demeter, as objects would have to query the MappedMetric just to get at the underlying Mapping. It has the slight disadvantage of adding to the complexity of Mappings, but it doing so, decreases the complexity of all classes that use the model.

Interpolation between Metric and Display

File:InterpolationUML.png
A class diagram showing the strategy pattern.

A value for each section of the metric has been interpolated into a value that can be used by the display. This interpolation can be linear, logarithmic (on the metric or display side, by a certain log) or exponential (on the metric or display side, by a certain exp). It should also be extensible to allow new interpolation methods, like tanh to be added.

In the old design, this was one huge method (89 lines long) with a massive switch statement in Mapping.

This was clearly a strategy of Mapping. A strategy pattern has been implemented from Mapping which deals with each exponential type as a separate subclass of the abstract InterpolationStrategy class. See the attached thumbnail for details.

Multiple Metrics on One Display

The Issue

  • Some of the display types have the ability to display multiple metrics. How should we deal with this?
  • This is an issue because the model is currently designed to support mappings between one metric and one display.
  • This may be considered a major issue; however, it may be too difficult to realistically fix.
  • Displaying multiple metrics, while possibly useful, has no proven applications currently. Having said that, one has yet to prove that metrics themselves are useful...

Potential Solutions

  • We intentionally don't solve it.
  • We could just leave it, but this is probably not a nice thing to leave people who might want to extend the system.
  • Have a mapping be able to take multiple metrics.
    • If this change is made, some way of differentiating between different kinds of displays is needed.
    • We will also need to make the mapping strategy more generic.
    • This will require changes to the XML.

I believe this is (or atleast should be) one of the Amelioration patterns. As I can't find any documentation describing this pattern, I shall create it and call it the One Into Many pattern.

MetricsProvider component

I have implemented a simple version of this section as an exemplar. The tool is primarily design to allow others to add information, but this should give some ideas.

Design Considerations

Second Design

Final Design

Personal tools