Above is a screen shot of a diagram created in Carracci portraying the command pattern. The command pattern demonstrates a way of encapsulating a function or command along with the data required for invoking it (it's arguments) as a piece of data so that it can be stored, passed around, called at a set time and then undone later on. It is particularly useful for implementing menu actions in a graphical user interface as it decouples functionality from the GUI and facilitates the implementation of a history system.
In the Carracci application this diagram is one of a group of ready created diagrams which can be accessed from the menu. Normally, however, a user will create a diagram from scratch by selecting components from the menu, dragging the components round the canvas, configuring components using a pop up menu, and connecting them together using a combination of shortcuts, clicking and dragging. I want in this article though to give a general overview of Carracci rather than provide a tutorial.
The other currently implemented feature is the ability to export the diagram into JSON form which allows the diagram to be stored and reloaded at a later time. Other features that I intend to add is to be able to export the diagram to other image formats such as jpg and png. I have implemented these in prototype form but they are still not live. As far as UML is concerned it would be obvious to attempt other types of diagrams but I don't intend to do this as part of this project.
Technology stack
I choose to use SVG rather than Canvas as I wanted to gain the benefits of vector graphics such as being able to resize images without loss of resolution. Native vanilla Javascript is used for most of the application code with Raphael.js used for manipulating the low level SVG primitives (The name Carracci is a reference to one of Raphael the artist's followers). I also used JQuery, Backbone and Underscore for various utilities although these could be removed with a bit of effort.Everything takes place on the client side and there is no server side code at present.
Architecture
One of the main challenges in designing a software system is determining the constituent parts of which it will be formed as well as how these parts will relate to each other. The starting point for this process is normally the object domain which in this case comprises diagram components such as 'class box', 'connector', and 'note', and also the components that make up the menu system. In the case of diagram components, because of the way they relate to each other within a diagram-they can be joined together and be dragged around- the relationship between objects that represent them is particularly complex. It is obvious that these objects will require some means of passing messages to each other such as location information.
The problem is exacerbated because the diagram components are constructed from SVG elements which are just very simple geometric shapes. The application therefore is responsible for creating complicated, interactive components from these static primitives.
I arrived at a layered architecture with diagram components implemented by complex objects composed of simpler objects which in turn were composed of simpler objects, and so on all the way down to the SVG primitives. Such a design allowed me to abstract away the complexities of underlying layers. Across this, I also used an MVC design to segregate data, representation, and user interaction from each other.
To solve the problem of objects communicating with one another I used the mediator pattern extensively. For example a mediator object was associated with each connector component and was responsible for orchestrating the movement of any of it's parts. A temporary mediator is also created whenever a connector is joined to a box. This ensures that for the lifetime of the connection both connector and box act in concert with one another.
Offline
The application will work when the user is offline. I have used a service worker to cache all the necessary resources so that the site works exactly the same even without internet access.
Github repository Demo