After studying this code and completing the corresponding exercises, you should be able to,
- 1. Use High-Level Designs
[LO-HighLevelDesign]
- 2. Use Event-Driven Programming
[LO-EventDriven]
- 3. Use API Design
[LO-ApiDesign]
- 4. Use Assertions
[LO-Assertions]
- 5. Use Logging
[LO-Logging]
- 6. Use Defensive Coding
[LO-DefensiveCoding]
- 7. Use Build Automation
[LO-BuildAutomation]
- 8. Use Continuous Integration
[LO-ContinuousIntegration]
- 9. Use Code Coverage
[LO-CodeCoverage]
- 10. Apply Test Case Design Heuristics
[LO-TestCaseDesignHeuristics]
- 11. Write Integration Tests
[LO-IntegrationTests]
- 12. Write System Tests
[LO-SystemTesting]
- 13. Automate GUI Testing
[LO-AutomateGuiTesting]
- 14. Apply Design Patterns
[LO-DesignPatterns]
- 15. Use Static Analysis
[LO-StaticAnalysis]
- 16. Do Code Reviews
[LO-CodeReview]
Note how the Developer Guide describes the high-level design using an Architecture Diagrams and high-level sequence diagrams.
Resources
Note how the Developer Guide uses events to communicate with components without needing a direct coupling. Also note how the EventsCenter.java
acts as an event dispatcher to facilitate communication between event creators and event consumers.
Resources
Note how components of AddressBook have well-defined APIs. For example, the API of the Logic
component is given in the Logic.java
Resources
Note how the AddressBook app uses Java assert
s to verify assumptions.
Resources
Resources
Note how AddressBook uses the ReadOnly*
interfaces to prevent objects being modified by clients who are not supposed to modify them.
Resources
Resources
-
Use gradle to do these tasks: Run all tests in headless mode, build the jar file.
Resources
Note how our CI server Travis uses Coveralls to report code coverage. () After setting up Coveralls for your project, you can visit Coveralls website to find details about the coverage of code pushed to your repo. Here is an example.
Resources
The StringUtilTest.java
class gives some examples of how to use Equivalence Partitions, Boundary Value Analysis, and Test Input Combination Heuristics to improve the efficiency and effectiveness of test cases testing the StringUtil.java
class.
Resources
Consider the StorageManagerTest.java
class.
-
Test methods
prefsReadSave()
andaddressBookReadSave()
are integration tests. Note how they simply test if TheStorageManager
class is correctly wired to its dependencies. -
Test method
handleAddressBookChangedEvent_exceptionThrown_eventRaised()
is a unit test because it uses dependency injection to isolate the SUTStorageManager#handleAddressBookChangedEvent(…)
from its dependencies.
Compare the above with LogicManagerTest
. Some of the tests in that class (e.g. execute_*
methods) are neither integration nor unit tests. They are integration + unit tests because they not only check if the LogicManager is correctly wired to its dependencies, but also checks the working of its dependencies. For example, the following two lines test the LogicManager
but also the Parser
.
@Test
public void execute_invalidCommandFormat_throwsParseException() {
...
assertParseException(invalidCommand, MESSAGE_UNKNOWN_COMMAND);
assertHistoryCorrect(invalidCommand);
}
Resources
Note how tests below src/test/java/systemtests
package (e.g AddCommandSystemTest.java
) are system tests because they test the entire system end-to-end.
Resources
Note how this project uses TextFX library to automate GUI testing, including headless GUI testing.
Here are some example design patterns used in the code base.
-
Singleton Pattern :
EventsCenter.java
is Singleton class. Its single instance can be accessed using theEventsCenter.getInstance()
method. -
Facade Pattern :
StorageManager.java
is not only shielding the internals of the Storage component from outsiders, it is mostly redirecting method calls to its internal components (i.e. minimal logic in the class itself). Therefore,StorageManager
can be considered a Facade class. -
Command Pattern : The
Command.java
and its sub classes implement the Command Pattern. -
Observer Pattern : The event driven mechanism used by this code base employs the Observer pattern. For example, objects that are interested in events need to have the
@Subscribe
annotation in the class (this is similar to implementing an<<Observer>>
interface) and register with theEventsCenter
. When something noteworthy happens, an event is raised and theEventsCenter
notifies all relevant subscribers. Unlike in the Observer pattern in which the<<Observable>>
class is notifying all<<Observer>>
objects, here the<<Observable>>
classes simply raises an event and theEventsCenter
takes care of the notifications. -
MVC Pattern :
-
The 'View' part of the application is mostly in the
.fxml
files in thesrc/main/resources/view
folder. -
Model
component contains the 'Model'. However, note that it is possible to view theLogic
as the model because it hides theModel
behind it and the view has to go through theLogic
to access theModel
. -
Sub classes of
UiPart
(e.g.PersonListPanel
) act as 'Controllers', each controlling some part of the UI and communicating with the 'Model' (via theLogic
component which sits between the 'Controller' and the 'Model').
-
-
Abstraction Occurrence Pattern : Not currently used in the app.
Resources
-
Find other possible applications of the patterns to improve the current design. e.g. where else in the design can you apply the Singleton pattern?
-
Discuss pros and cons of applying the pattern in each of the situations you found in the previous step.
Note how this project uses the CheckStyle static analysis tool to confirm compliance with the coding standard.
Resources