School of Information Technology and Mathematical Sciences
COMP 3023 Software Development with C++
Group Project
Networked Asset Manager
Introduction
This document specifies the requirements for the group project of the Software Development with C++ course, SP5 2018. This assignment will develop your skills by developing an application in a team environment while allowing you to put into practice what has been taught in class during this course.
The assignment will require you to design, implement, test, and debug a GUI-based networked database1 application using object-oriented methods and the application of Design Patterns. The application will store information about Assets, their types and properties, and their maintenance as well as support the sharing of this information with other running instances of the application over the network. To realise this, several Design patterns will need to be incorporated into the design and implementation of the application. The project will require you to use collaboration tools and version control to manage the project and collaborate with your team members as you progress through the assignment as well as document your classes appropriately through UML class diagrams and Doxygen comments. To support concurrent development by each team member, Unit Testing will be very important to ensure that things are working before a GUI is able to test each component of the application.
If any parts of this specification appear unclear, please ensure you seek clarification.
Learning Outcomes
After completing this assignment, you will have learnt to:
• Collaboratively design a class hierarchy using UML
• Apply Object-Oriented principles (encapsulation, reuse, etc.) and Design Patterns to the software design
• Implement the software design in C++ within a team environment
• Develop a cross-platform application using a cross-platform framework (Qt)
• Use professional tools for collaboration and software development, such as: version control, project management, issue tracking, and continuous integration
• Write code adhering to coding standards, guidelines and good programming practices
Design Patterns
In developing the class design for the Networked Asset Manager, the following the Design Patterns will be incorporated:
• Singleton (extensible version)
• Abstract Factory

• Prototype

---------------------------------------------------------------------------------------------------

1 You will not actually be using a database, just manipulating objects in memory.

• Type-Object
Unlike the previous assignment you do not have to identify where to apply the Design Patterns (there is complexity elsewhere in this project). However, you should read the description of the patterns.
For more information on Abstract Factory and Prototype2, refer to the book: Gamma, E, Helm, R, Johnson, R and Vlissides, J 1995, Design patterns: elements of reusable object-oriented software, Addison-Wesley, ISBN: 978-0-201-63361-0.3 Be aware that the C++ examples from the book are for an older version of C++. If using them for guidance, they must be updated to C++ 14.
For the Type-Object pattern, refer to the article (posted to the course website for convenience):
Woolf, B., Johnson, R.: The type object pattern. Pattern Lang. Progr. Des. 3, 132 (1996)
Adequate descriptions of the above patterns along with some code examples can also be found on Wikipedia and elsewhere:
• Singleton: https://en.wikipedia.org/wiki/Singleton_pattern (Note: the Wikipedia entry does not consider extensibility of the Singleton.)
• Abstract Factory: https://en.wikipedia.org/wiki/Abstract_factory_pattern
• Prototype: https://en.wikipedia.org/wiki/Prototype_pattern
• Type-Object: http://gameprogrammingpatterns.com/type-object.html
Task Description
In this assignment, you will design and implement a GUI-based networked database application that fulfils the following specification. The application will store details about assets that a company owns, including records of maintenance for auditing purposes. However, the company operates in a highly dynamic environment with new types of assets becoming available all the time; therefore, the application will also keep track of the types of asset and their properties, which may differ between asset types.
The aim of the assignment is to build a software application in a team environment using a cross-platform framework (Qt), GUI and networking libraries. The style of application (a database application with a web service-style API) is very common in the real-world and something you are likely to come across when you graduate. The design and implementation of the application will require features of C++ taught in the latter half of the course, such as templates, in addition to those features covered previously, such as inheritance and polymorphism. The focus of this assignment is the collaborative development of the application. Due to the added difficulty and complexity of managing a team, this specification will be more detailed when it comes to the application of the Design Patterns and the major interfaces that are required. You will be required to develop a UML Class Diagram that incorporates the described interfaces plus additional classes/functions your group considers necessary. This will be a key piece of documentation that supports communication between team members. Moreover, the separation of tasks between team members and the use of Unit Testing will be important to allow concurrent development of different aspects of the application by different team members. The specification consists of some larger and more complex aspects, as well as some smaller components: the idea being that group members of different capability levels should each be able to contribute to the group effort.
First, you will need to develop a class design using UML class diagrams based on the requirements in the remainder of this specification. A simple and free UML editor that can be used for this assignment is UMLet
-----------------------------------------------------------------------------------------------------------------------------

2 The Type-Object pattern is not in the GoF Design Patterns book.
3 Scanned PDFs of the relevant sections are available from the course website as the library has limited copies of the book.

(http://umlet.com/). The UML class diagram must include all classes, public data members, public member functions, protected data members and member functions (if any), and associations between classes. The diagram must identify the key roles/participants of the Design Patterns occurring in the design. The diagram may optionally display private member functions, but private member variables should not be included.
Workplan and Group Collaboration
To complete this assignment, it is important that you take a planned, methodical approach in collaboration with your group members. You and your group will need to think about how to break down the assignment into smaller chunks of functionality that can be allocated among the team and implemented and tested independently. Working in an incremental manner, and testing as you progress, helps to limit the scope of errors that are introduced as you perform the implementation and will assist when integrating your work with others. Moreover, an incremental approach allows you to focus on a single problem at a time as well as refactor and redesign the application in a controlled manner as you (re)discover requirements or issues that were not obvious at first.
To enable adequate collaboration with your group members, the first order of business will be to organise a platform for collaboration. At the centre of this collaboration framework will be a version control system (Git) through an online repository. Possible online repositories include BitBucket [https://bitbucket.org/] and GitLab [https://about.gitlab.com/] (which many of you may already be using). Note: whichever you choose you must ensure that your repository is private and cannot be seen by anyone outside your group. Online version control interfaces like BitBucket, GitLab, and GitHub4 provide some basic project management features such as issue tracking and wikis. However, for improved collaboration and project management, I suggest you integrate Trello (or similar). Trello [https://trello.com/] is a project management and collaboration tool popular among small, agile teams. It is quite simple and will help you keep track of tasks, assign them to group members, and indicate to your team when they are complete.
This assignment should be completed in the following stages:
1. Read this assignment specification in full.
2. Check your group allocations and contact your group members.
3. Read this assignment specification again.
4. Organise with your team an online repository and collaboration environment—someone will need to create the repository and invite the others to access it. This step will be essential in the in ensuring ongoing communication with team members.
5. You and your team create an initial class design of the application—this will serve as a primary communication tool between team members on what is expected and should be maintained throughout the project.
6. Implement class and function stubs—this will allow group members to work somewhat independently without issues due to missing classes, functions, etc. It will also allow tests to be created based on the expected interfaces.
7. Identify team members’ strengths and weakness and assign tasks to individual team members.
8. Perform your task(s)
9. Use the online collaboration tools and in person meetings (if possible) to manage the project and monitor progress. (Back to 8.)
10. Successfully complete the project.
--------------------------------------------------------------------------------------------------------------------------------

4 GitHub is highly popular for open source projects; however, it requires a paid subscription to obtain private repositories. While you get private repositories for free as a student, it is unclear what happens if GitHub decides you no longer fulfil the student requirements, that is, they may make your private repositories public. Therefore, do not use GitHub for your project.
General Functionality
The Networked Asset Manager application will need to support the creation, management, and deletion of assets and asset related information in a networked environment. Logged on users (in the real-world security and permissions, as well as knowing who modified the data, are serious concerns) will be able to view and modify the details of assets, etc., through a GUI with changes synchronised between other instances of the application. In addition, users will be able to search for assets using some of their common attributes (e.g., serial number).
Core to the application is an Asset Register that stores the assets and related details, such as their type, their properties, maintenance records, and custodians (i.e., the person responsible for managing the asset). Each type of information is stored in and retrieved from the Asset Register using its unique ID. Each stored entity has some additional meta-data to help manage it: last edit time, and the last edit user. In a real-world application it the storage class would be backed by a database; however, for simplicity we will just store the objects in memory using the map data structure.
You will need to make use of Qt’s Signals and Slots mechanism (an implementation of the Observer Design Pattern) to communicate between components and ensure that the state of the application is correctly synchronised.
The user must be able to select at runtime (i.e., when they “login”) whether they want to run the application in “online” or “offline” mode. This will be handled using the extensible singleton pattern with a networked and non-networked version of the asset storage class. Below are some details of achieving this.
AbstractAssetRegister «singleton» (derived from: QObject)
The AbstractAssetRegister class will provide the interface for all types of asset register (offline, networked, possibly a future database backed implementation, etc.), including access to the singleton instance. AbstractAssetRegister is an abstract class and must not be instantiable itself; moreover, it must be a subclass of QObject to attain the Signals and Slots capability.
Constructors:
• explicit AbstractAssetRegister(QObject*)—since the class is derived from QObject, it should have the common QObject constructor for specifying the parent object (you could make the parent the singleton instance of QApplication, for example). For extensibility of the Singleton pattern, the constructor must be protected.
Instance-level interface (i.e., non-static functions) includes (but is not limited to):
• username()/setUsername(…)5—accessor and mutator for managing the “logged-in” user. This will just be a simple string (QString since we are in the Qt framework) specified by the user through the GUI. There will not be any control over what users are allowed, permissions, etc. it will only be used to record who created and modified an asset (or related entity) as part of the entity’s meta-data.
• generateId()—since we are operating in a distributed environment it is important that we avoid clashes between entity identifiers created by different instances of the application running on different (or the same) computer. A relatively simple way to achieve this is to use randomly generated IDs using an algorithm designed for such systems such as UUIDs (Universally Unique Identifiers). This function will create and return a new UUID (as a QString) to be used as an identifier. This can be done using Qt with the QUuid class and its createUuid() function.

------------------------------------------------------------------------------------------------
5 Where an ellipsis (i.e. ‘…’) appear in the parameter section of a function signature, it means it requires 1 or more parameters but they have not been explicitly provided as part of this specification.

• storeEntity(…)—stores an entity (Asset, AssetType, Custodian, or MaintenanceRecord) in the AssetRegister: must return true if the entity was added, false if the it was not (e.g., due to the ID not being unique). May be a single function using inheritance and polymorphism to a common base class, or multiple overloaded functions. Document your design decision.
• retrieveEntity(id)—retrieves an entity (Asset, AssetType, Custodian, or MaintenanceRecord) from the AssetRegister using the entity’s identifier. Must return a nullptr if an entity with that identifier cannot be found. As above, may be one function or a group of overloaded functions, document your decision.
• deleteEntity(id)—remove the entity with the given identifier from the register: must return true if the entity was removed, false if it was not (e.g., it may have already been removed). Calling this function multiple times with the same identifier will not have any negative consequences. Make sure you clear any dynamically allocated memory when deleting an entity from the register (refer to QObject::deleteLater() when cleaning up QObjects).
• allEntities([type])6—returns a collection of all entities stored in the register. Modifying the returned collection must not modify the register. You must be able to retrieve all entities regardless of concrete class, as well as all entities of a particular class (i.e., Asset, AssetType, Custodian, MaintenanceRecord).
The class level interface (static members) includes:
• template instance()—static member function to return the single instance of this class (or any of its subclasses). Use lazy initialisation to create the single instance if one does not currently exist. To support extensibility, this function will be a template function: the type parameter will specify the concrete subclass that is to be created (if the register instance does not already exist). Once an instance of a type has been created, that instance will always be returned, regardless if the function is called with a different type: i.e., there cannot be multiple register instances of different types instantiated at the same time. For example, to select the simple AssetRegister class as the singleton, the first call to this function should be: AbstractAssetRegister::instance() Note: you can create a non-template version of the function for convenience. This convenience function should log an error if it is called before an instance of any concrete register types is created.
• register—the static data member of type AbstractAssetRegister. Must be able to support polymorphism. To allow subclasses to manipulate the static member (to support the extensibility requirement) this member must be protected. This will allow the creation of a MockAssetRegister for testing. Such a special subclass should have static member function that can clear the register class variable, allowing a new register object to be created the on the subsequent call to instance().
Signals:
• addedEntity(id, [type])—emitted when a new entity is added to the register.
• deletedEntity(id, [type])—emitted when an entity is deleted from the register.
AssetRegister (derived from: AbstractAssetRegister)
The first concrete subclass of AbstractAssetRegister is the AssetRegister. This class is relatively straightforward: it simply implements each of the functions of the interface defined by AbstractAssetRegister.
Important: to support the extensible singleton, this class must declare AbstractAssetRegister to be a friend class. This will allow the instance() static function (which is defined in the scope of AbstractAssetRegister and not its subclasses) to access the protected constructor of AssetRegister.

------------------------------------------------------------------------------------------------
6 Parameters in square brackets ‘[‘ & ‘]’ are optional parameters.

NetworkedAssetRegister (derived from: AssetRegister)
The NetworkedAssetRegister will behave in the same way as the standard AssetRegister (its core behaviour is inherited) but adds support for synchronising itself over the network. It will be instantiated when the user chooses to “log-in” using “online mode”. It must have a data member of type NetworkManager (refer to the Networking section below), which it uses to exchange entities with other instances of the application running in online mode. You may use a combination of function overrides and signals/slots to ensure the state of the distributed application is synchronised across all participants. When updating the stored entities, you must check the lastEditedTime and only update the local entity if the lastEditedTime is prior to that of the entity received from the network. Refer to section RegisteredEntity for the attributes of entities.
Assets, Asset Types, and their Properties
First and foremost, the Asset Register application needs to be able to store information about the company’s assets. This includes information such as the serial number, model, purchase price, who manages it, and what maintenance has been performed on it. However, it also includes information about properties7 that differ between different types of asset: for example, Pump assets have properties such as flow rate and alignment (horizontal/vertical), while Computers may indicate their operating system, MAC address, IP address, etc. Therefore, we need to be able represent the types of asset in the system alongside the assets themselves. In addition, we must represent the user-defined properties (or user properties) specific to the types defined at runtime, which will allow functionality such as validation of property values (e.g., the operating system property for Computer may only allow the values: “OSX”, “Windows”, “Linux”).
There are a couple of Design Patterns that can help to dynamically define the types of asset at runtime. The first is Prototype, which allows special instances (called prototypes) to be created that represent the type itself. These prototypes can be cloned (i.e., copied) to create the actual instances of the type. Defining the Asset class as prototype would allow the description of an asset type through the specification of the typical values for that type; however, the copies often become disconnected from the prototype and the prototype does distinguish between information related to the type itself and that of the real instances.

------------------------------------------------------------------------------------------------
7 Qt also provides a concept of ‘dynamic properties’, do not confuse the user-defined properties that we are creating here with the dynamic properties of Qt (which are still compile time constructs).