Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

6COM1038 Software Engineering Practice

Raymond Hu

Unsure about anything? Ask in tutorials, or email the module leader (Raymond Hu, r.z.h.hu@herts.ac.uk).

0. Preliminaries

Read the Tinee Client Application Specification (again!).


Coursework 1 is the precursor to this assignment. You are expected to have completed CW1, and therefore be
familiar with the provided code, its various issues, and the application specification.

1. Overview

Assessment 2 of 2 – 60% of module total

Refactor and redesign the Tinee client prototype to resolve the existing issues (e.g., as identified in your
review) in accordance to the Client Application Specification.
Do so by applying the software engineering practices studied in this module: e.g., version control, static code
analysis, black-box and white-box testing techniques, internationalisation, etc.
Demonstrate the efficacy of your design by extending your client to support the additional features required by
the Specification.
Present and explain your work clearly and concisely in a report following the specified report structure.

2. Your Tasks

2.1 Programming and Design – 40% of this assessment


2.2 Software Engineering Practices – 50% of this assessment
2.3 Report – 10% of this assessment
Use the specified report structure as a checklist for the overall assignment

Read all of this section carefully before starting. Many of the items in this section overlap; e.g., the software
engineering practices should be conducted throughout the refactoring and redesign process. Some of your
work will thus touch on more than one of these items at the same time.

2.1 Programming and Design (40%)

a) Refactoring and redesign. Debug, refactor and redesign the client to address the issues raised in your
code review (CW1). Lay the groundwork to support your upcoming work on the additional features and
extensions required by the Specification. Do so by reworking your client as follows:
Refactor the client to based on the Command Pattern. This pattern decouples the code definition of
“commands”, the creation of requests to execute a command, and the actual command execution. That
will in turn simplify the addition of further kinds of commands in future.
Restructure your client to further modularise its main components: the core data structures, the user
interface, and the application logic that binds everything together.
Hint: consider the basic Model-View-Controller (MVC) framework included in the provided code (the
sep.mvc package). See its Javadoc and the Appendix for more details.

General reminder: Any disciplined approach to debugging and refactoring needs solid test support to prevent

1 of 7
regressions, i.e., accidently breaking existing functionality when adding new functionality or fixing other bugs.
Pay up-front attention to the Testing item in Sec. 2.2 and 2.3.

b) Extensions. (Mandatory, as per the Specification.) Exercise and refine your client design by implementing
all the additional features and extensions described in the Specification, i.e., “Additional commands”,
“Extensions” and “Alternative UI”. As described in the Specification, you do not need to implement an actual
GUI, but your design is expected to offer appropriate support for adding alternative UIs in the future.
Hint: your design work from part a) can be judged on how well it supports your work in this part. Revise
your design as needed.
Hint for Undo: consider what data structure would work well with your command pattern to support this
functionality.
Hints on i18n: as a CLI application, you do not need to consider issues such as culturally sensitive images
or colours. However, the prototype client is littered with hardcoded strings written in English. In addition to
the lecture and tutorial, the Java i18n Trail is recommended.
Be sure to add appropriate test support during the development of all these features to verify their
functionality, especially when you encounter bugs. For i18n, you may find it helpful to create another
ResourceBundle with a specific Locale resource (e.g., fr‐FR ) just to test you have implemented your
solution correctly.

Bonus extensions. The following are optional tasks for bonus marks. It is possible to attain maximum marks
for this assessment without undertaking them.

Add the following command to your client.

Command Client “state” (current → successor) Behaviour


The same as push and closes the ticket on the
close Drafting → Main
server. See the notes below

The server team have already included support for closing a ticket.
A close command is communicated to the server as a special-case Push message: the message line
of the last tine in the Push should be exactly "##CLOSE##" .
The server will only close a ticket if requested by the ticket creator (i.e., the author of the initial tine).
The server will not add further tines to a closed ticket.

2.2 Software Engineering Practices (50%)

You will be assessed on good software engineering practices. We visit all these topics over the course of this
module!

c) Version control. Version control is indispensable to any realistic software project.


You are required to maintain your project as a private GitHub repository. Be sure to continuously commit your
changes and push your commits to your GitHub repository. You will also be required to demonstrate the use of
Git branches for organising your working on separate tasks.
Tip: taking advantage of Git/GitHub (e.g., by writing meaningful commit messages) will help you later with your
final report.

d) Testing. Testing is a fundamental element of the software design and development process, not an
optional afterthought. You are required to provide evidence of disciplined testing using JUnit/NetBeans. Your
tests should include:
Acceptance tests. Your initial tests may simply check that your program does not crash. As your work
progresses, options will open up for more precise verification of outputs. Remember, code should be
written to be test-able!
Unit tests. For focused (sets of) operations and classes – i.e., units – you may apply systematic black-
box testing techniques. The key point is to justify the design of your test cases: how should you select

2 of 7
which inputs to test?
Tests against bugs that you encountered during development, whether inherited from the prototype (e.g.,
as identified in CW1) or in your own work.
Code coverage: use code coverage as a white-box testing technique to complement your black-box
testing by quantifying the adequacy of your test suite. The target is 70% instruction coverage and 50%
branch coverage for your client package tests, as measured using the JaCoCo NetBeans plugin.

e) Static code analysis. A wide range of code analysis tools for many languages and platforms are available
(often freely) to modern software developers. You are required to apply the static code analysis tools used in
CW1 to your client code. As a reminder:
FindBugs – no configuration beyond the defaults is needed. Check that you are running the FindBugs
Source Inspector on the whole of your Client package (i.e., all your classes).
EasyPmd – the default rulesets are basic.xml , imports.xml and unusedcode.xml . Again, you are
encouraged to include further rulesets: empty.xml , unnecessary.xml , strings.xml ,
strictexception.xml and design.xml .

f) Documentation. Professional communication is a necessity in industry. You likely found the Javadoc in the
base framework packages helpful. Now, it is your turn to document your code in a way that would be helpful to
your teammates, other developers or the wider community – or just the future you who will forget some of the
important details after only a day or two.
In general, your documentation should centre on the public interfaces of your code, and what external parties
should know to run, modify or extend it. Conversely, a lack of documentation where needed or bad
documentation are code smells. You are required to include:
A user-friendly README in your GitHub repository (e.g., build instructions, execution parameters, etc.).
Javadoc for your client package to support future maintenance/extensions (e.g., additional commands,
alternative views).
Your report, as detailed in the next section.

Keep your README and Javadoc brief but meaningful. They will be evaluated based on your recognition of
concepts and items that are important to document, rather than a complete account of every detail of your
code.

2.3 Report (10%)

The purpose of your report is to highlight your solutions to the tasks in 2.1 and 2.2. Use your report to
demonstrate your understanding and application of the relevant software engineering principles and practices
as clearly as possible. Although the report itself is weighted at 10%, much of the other 90% will be judged first
from your report – so a well-written report is essential!

You are required to structure your report and include all the items as listed below.
Use this as a checklist for the overall assignment. Note: your answers to some items may overlap, and their
order is not necessarily the order in which you carry out the work.

Programming and Design (40%)


a. Refactoring and redesign.
Explain (i) how the following are incorporated into your client design (e.g., key classes/interfaces, class
diagram, etc.), and (ii) their purpose in relation to the functionality of your client.
Command pattern
Model-View-Controller, or your alternative provision
Discuss how the above influence coupling/cohesion in your application. Explain the subsequent
benefits w.r.t. future modifications/extensions by considering two lightly sketched examples.

3 of 7
b. Extensions. (Mandatory, as detailed in Sec. 2.1 and the Specification.)
Explain how you have implemented:
Undo of appropriate commands in the Drafting state. Demonstrate the functionality by including a
small number of output samples, screenshots, etc. Give links to the tests in your codebase related
to this feature.
Support for internationalisation. Note: you must provide appropriate mechanisms for localising
your application, but it is not necessary to provide concrete translations.

Software Engineering Practices (50%)


c. Version control. (Pay attention to this item up front!)
Submit a file CHANGELOG.txt containing the output of the git log command on your final project. Your
Git history is expected to relay a meaningful narrative of your progress.
Highlight and briefly explain two instances where you used a dedicated Git branch to develop a bug fix
or new feature, with references to the logs.
d. Testing. (Pay attention to this item up front!)
Briefly outline your JUnit test classes and packages and the purpose of each.
Also answer the following:
Identify the tests related to functionality of the original client prototype.
For two separate bugs present in the prototype, identify tests that expose those bugs and
demonstrate that they are fixed in your client. (It is fine for your answer to overlap with your
work in CW1.)
Identify the tests related to the various client extensions undertaken in this assignment.
Highlight and explain a tricky/interesting bug that you encountered, with references to the
relevant tests.
Explain an application of black-box testing to a suitable unit of your choice.
Examples of suitable units are the parsing of user input into commands, and your Model
component (if you adopted the MVC pattern).
Include screenshots of the JaCoCoverage results (via NetBeans) for your client tests. The target
is 70% instruction coverage and 50% branch coverage for your client package overall. If you
deem this target unsuitable for certain subpackages or classes, explain which and why.
e. Static code analysis. (Pay attention to this item up front!)
Include appropriate screenshots of the following:
FindBugs – the fully expanded list of items in the NetBeans “Inspector” window after running the
FindBugs inspector on your final client package.
PMD – the final “Rulesets” tab of your NetBeans EasyPmd options, and the NetBeans “Action
Items” window set to “Show All” for your final project.
Pick any three PMD or FindBugs warnings/errors that you encountered during the project and: (i)
explain the warning/error and how it is harmful to the functionality/design of your client, and (ii) how you
resolved the issue, with reference to your concrete code. Pick items related to genuine programming
errors, not purely cosmetic issues (e.g., white space conventions).
If your final results contain untreated items, explain why you have opted not to treat them.
f. Documentation.
Include the Javadoc (as generated via NetBeans) for your full client package.
Briefly highlight two examples of how your documentation (Javadoc, README) facilitates future
modification and extension of your code (e.g., additional commands, alternative views).

Repoort (10%)
g. The purpose of your report is for you to clearly communicate your work on Programming and Design
and Software Engineering Practices through the above items a) – f). The 10% weighting for the
report itself is based on the quality of your writing and presentation as a technical document.
Clearly designate a section on Bonus extensions if you wish to include any for assessment – explain

4 of 7
your work as you did for Undo in b).

3. Your Submission

Submit a single zip archive named [SRN]_sep_2021.zip with [SRN] substituted for your own value.
It should contain:
The full source code (includiung tests) and documentation of your client. This must also include:
The .git directory of your code repository.
The javadoc directory and contents generated using NetBeans, and README if applicable.
Your report as a pdf file named report.pdf .

Your code project directory (i.e., Git repo) should be structured like:

Submission checklist:
Your code must compile without errors against the provided base framework.
Your client must be compatible with the provided server.
All your tests must pass. Your tests must be runnable via the NetBeans “Test Project” action.
The static code analysis results for your code must match those in your report.
The .git directory in your zip must match your private GitHub repository.
The Javadoc in your zip must match that generated via NetBeans.

You may lose marks if your submission fails any of these constraints.

Notes on assessment: this assignment examines your ability to develop software towards a professional level
of quality, as opposed to amateurish coding or “hacking”. The assessment criteria thus include:
Correctness – functional correctness w.r.t. the specification, and general consistency.
Appropriate use of language features and coding style (e.g., formatting, comments, etc.)
Design – in terms of the specified requirements, and software engineering principles in general.

You might also note that your Git history, by design, will show exactly what code you commit and when.
Similarly, the diff tool highlights similarities and differences between two codebases (cf. illegal collusion or
plagiarism).

Appendix

A. Command Pattern

The essence of design patterns is that, in most cases: there is already a well-established solution to your
software design problem. As a software developer, you should be able to see past superficial application details

5 of 7
and recognise the fundamental problem at hand. We can then look at relevant design patterns for solutions,
perhaps with some fine tuning.

The Command Pattern offers a solution to common problems when handling dynamic operation requests, e.g.,
interactive user commands. You are required to look into the Command Pattern as an effective way of
addressing some of the design problems in the client prototype. Here is an outline of the pattern:

A Command represents a request to carry out some operation or task. This concept can be expressed
programmatically as an interface:

interface Command {  // A minimal illustration
void execute();  // Override to define the operation or task to be executed
}

The execute method executes the operation request.

Commands are concretely implemented as subclasses that define the actual work.

class MyCommand implements Command {
private SomeObject rcvr;  // The target object of the actual work to do
private Data args;
public MyCommand (SomeObject rcvr, Data cmdArgs) {  // Encapsulate command params
this.rcvr = rcvr;
this.args = cmdArgs;
  }
@Override
public void execute() {
// Carry out the requested work (by invoking rcvr)
this.rcvr.process(this.args);
// etc.
  }
}

Each subclass:
encapsulates the parameters it needs to execute the command (e.g., via its constructor);
implements the execute method to perform the intended work.

A command object thus encapsulates a specific instance of an operation request and its parameters, ready for
execution.
Commands are requested for execution by a requestor. One option is for the requestor to create
command objects for specific requests as needed.
A command is (later) executed by the executor (or the invoker), by calling the execute method on the
command object. Typically, the executor is a different party than the requester.
The target object of the actual operations to perform for a command (part of the encapsulated
parameters) is known as the receiver.

Command encapsulation has several useful characteristics.


Command objects can be “passed around” and stored (like any regular object) under the Command
interface type. This helps to separate the requester from the executor.
Likewise, the executor is decoupled from the concrete command subclasses.
Since command execution is separated from the request, it can be deferred or rescheduled as needed.
This also facilitates recording a history of executed commands…
Last but not least: modifying or adding commands can be done independently of the implementation of
the executor, and of the requestor to an extent.

6 of 7
B. Model-View-Controller

Model-View-Controller (MVC) is a design pattern for structuring applications with user interfaces. There are
many variations – we can think of MVC as the base pattern of a “pattern family”. The primary aim is to separate
an application’s internal data representations from the way that the data is presented to, and accepted from, the
user.

You are provided with a basic MVC framework (the sep.mvc package) suitable for your command line Tinee
client. You are advised to use this framework in the redesign of your client; e.g., for the “Alternative UI”
requirement. As a guide to applying MVC, consider the following questions about your application:

What are the core data structures and application states? Which are logically independent of how
the UI may be designed? These belong in the Model component.
The framework provides the AbstractModel abstract class for you to extend into your concrete Model.
AbstractModel has no fields or methods – it is a blank canvas for you to work with!

Which components and operations are specific to UI functionality? For example, formatting of
data for user presentation, and parsing of user input into commands. These belong in the View.
The framework provides AbstractView for you to extend into a concrete UI; e.g., the command line
interface of the client. There are a few abstract methods for you to override:
init – to be called after the View is created to initialise the UI. You can create your concrete View
and call init from the top-level entry point of your application (e.g., the main method).
run – to be called after init , to start up the main UI loop (e.g., user input reading). May also be
called from the top-level entry point.
close – to be called during application shutdown, to clean up the UI (e.g., free any resources). May
be called by the Controller (see below).
update – called to refresh the presentation of the UI with the latest Model state. May be called from
within the View, e.g., in the run loop – the required application data can be obtained from the Model
by calling the getModel() helper method.
Could also be called from outside the View, e.g., directly from the Model after a data update.

How can we link up our Model and View without tightly coupling them? Where should we locate
the top-level logic to coordinate the application as a whole? These are handled by the Controller.
The framework provides AbstractController for you to extend into a concrete Controller.
Create your Controller after the Model and View – pass the latter two as arguments to the Controller
constructor. The constructor of the base class will take care of binding these components together,
so that the various component getter methods in each class are correctly populated.
You can extend Controller with operations for coordinating your overall application. E.g., to handle
user commands from the View by translating them into the appropriate actions on your Model.
shutdown – override and use this method to gracefully shutdown the overall application.

7 of 7

You might also like