UML Diagrams - CMPUT301F12T01/classproject GitHub Wiki

UML Diagrams

Actors

The currently identified actors in the system are:

Actors identified with the system

  • Users: users of the system
  • TaskCreator: a user that can create a task
  • TaskFulfill: a user that chooses to fulfill a task
  • Server: the back-end server that hosts globally shared tasks.

The Universe

These are the most basic use cases within our system:

Use cases in our universe

Abstract data types

These abstract data types are used ubiquitously in the system. They are passed around almost like the base types (int, double, Boolean, String, etc.).

The UML abstract data type classes

Overall system design

The following diagram give a taste of the three-level interaction between the Android UI classes (providing views and controllers) and the "storage" classes the provide local persistent storage and global publication. The main models are described in greater detail in the following section.

Overall System Design

Business logic layer

WARNING: This layer is severely out-of-date. Tell Eddie to change it, once the new model passes its most important tests.

This comprises the "Model" of "Model-View-Controller". The top layers (e.g., Android GUI) will provide views and controller for the top level model. Note that the top level model itself is a view to underlying models.

Business logic layer classes

Sequence: Creating a new task

The following is a sequence diagram demonstrating the use of Model-View-Controller combined with the Observer pattern.

Here, the TaskEditorActivity is the controller, adding a Task to the TaskManager. The TaskManager finds the proper TaskCollection and adds this Task to it. Since TaskCollections are observable, it notifies all of its observers of this change. Its observers include UIs and the persistent storage interfaces, which display, store, or upload the change.

Create task sequence diagram

Observer pattern with message passing

WARNING: the following scheme was created by a frustrated Erlang programmer.

Our design consists of this massive Model-View-Controller architecture. Classes that actually handle storage and uploading are Observers, hence view to the model. This makes adding Tasks and Reports really easy, but appending any more actions to this and things get complicated rather quickly. The solution is to send Messages which are tuples consisting of

  • the action; and
  • the object affected by the action -- called the "payload"

in notifyObservers() call, which will call the receiver's update() method.

Messaging UML

This is strongly inspired by the following idiomatic Erlang code (though please use gen_server, or gen_event for these kind of things!), which handles client-server interaction:

%% In the client...
rpc(Message) -> {self(), Message} ! task_manager.

add(Task) -> rpc({add, Task}).
remove(Task) -> rpc({remove, Task}).
modify(Task) -> rpc({modify, Task}).


%% In the server...
loop(Database) ->
    receive
        {_Sender, {Action, Payload}} when is_record(Payload, task) ->
            handle_task_action(Database, Action, Payload)
    end.

handle_task_action(OldDatabase, add, Task) ->
    NewDatabase = database:add(OldDatabase, Task),
    loop(NewDatabase);
handle_task_action(OldDatabase, remove, Task) ->
    NewDatabase = database:remove(OldDatabase, Task),
    loop(NewDatabase);
handle_task_action(OldDatabase, modify, Task) ->
    Key = tasklib:get_key(Task),
    NewDatabase = database:replace(OldDatabase, Key, Task),
    loop(NewDatabase).

Here, the lines

receive
    {_Sender, {Action, Payload}} when is_record(Payload, task) ->
        % ...
end.

are analogous to

public update(Observable sender, Object message) {
    if (((Message) message).getPayload() instanceof Task)
        // ...
}

The Message class adds this functionality to Java. Some people say to never try implementing one programming language in another; evidentially, those people have never programmed in Java.

See the "Sequence: Creating a new task" to see the message passing in action!