Personal Finance Manager The Model (Part Three)

Content

The Model

Summary

On the previous page PFM Epics & Stories we defined the Stories to implement for Sprint One. As we have a dependency on the 'Data Model' it will be the first task to implement.

A Simple Data Model (Epic 1a Task 1)

Remember from our original Product Statement we extracted the nouns for our database entities.

  • User
  • Bank Accounts
  • Transactions
  • Categories
  • Reports
We decided to use 'Owner' instead of 'User' as bank accounts usually have an owner associated with them.

What follows is a data model for our PFM application, its a first pass and so is kept really simple and easy to understand. During further analysis and Sprints it will be expanded further.

pfm-data-model.png

The Project Container (Epic 1a Task ii)

We first need a project container for our files and artifacts, as this is a Java project we will use maven for its creation. Maven is fast becoming a defacto standard for Java projects it specifies a standard project directory structure and set of conventions for layouts, etc. By defining certain conventions within software projects such as layouts and naming leads to many benefits as developers will learn to recognise where certain project artefacts are stored and automation of project tasks becomes trivial savings in time and costs are easily leveraged.

Note:
Of course you must have Maven installed correctly so that you can execute 'mvn' on the command line with no errors. Go to The Maven Download Site if you need to take care of this first. The instructions are clear and precise so no repetition will be given here. Install version 3

We are now going to create a project to contain all the PFM domain entities that represent the 'Model' so it will be named pfm-model, go ahead and execute this command to create a Maven project by this name.

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=com.inivitiv.tutorials.pfm.domain -DartifactId=pfm-model -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

After some lengthy output eventually it should indicate that the build was successful.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Wed Jan 29 22:20:44 MST 2014
[INFO] Final Memory: 22M/213M
[INFO] ------------------------------------------------------------------------

In the directory that you executed the command there will be a new subdirectory named 'pfm-model' with the following directory structure.

pfm-model-tree1.png

Configuration Management (Epic 4-1a Task i)

After running maven in the last section we now have a standard project directory structure. So it is a good time to start with version control, why version control? Well all commercially employed developers are expected to be able to work with version control systems (VCS) for checking in and out your modified code. You will also be working in teams so your work will sometimes have to be merged with someone elses. Doing this in tutorials or your own coding fosters good working habits and gives you confidence in working with these systems. There are also many benefits to using a VCS.

  • You are able to revert back to working copies when mistakes are made.
  • You have a record of all changes made (when working with a ticketing system this is essential for traceability)
  • When working in projects you can tag/baseline your work at key project milestones, these are good marker points in your work and give you a good point of return if things go pear shaped
  • When getting close to releases you can tag/baseline your work and release from this tag/baseline. Then if bugs are found you can fix and re-tag/baseline up a version number so you know the fix is applied past this point.
These are just a few of the benefits of using a VCS there are many more and no company worth its salt would consider not using one and enforcing a working process aroung the tool chosen.

Adding the Project to Git

The PFM project will be managed using 'git', git is more that a VCS it does not just manage changes, but also allows safe distribution of your projects, merging and branching, user management and many other features. When a tool offers all these features in moves into the realm of a Source Configuration Management tool (SCM). In fact whole books are devoted to this particular subject, if you would like a quick overview of the topic then take a look at the Software Configuration Management Wiki another good resource is cmcrossroads.com.

Make sure you have 'git' installed, full instructions on how to install it for your operating system can be found on the git home page. The Getting Started Page is also an essential read.

Navigate to the root directory of the pfm-model project and execute this command to initialise your project with 'git'.

git init
Now you need to add all the project contents so execute this command next.
git add .

(Don't forget the '.' at the end of the command)

Your projects contents are now 'staged' in the 'git repository' to know more about the 'git SCM' lifecycle follow this link to Git Basics Recording Changes to the Repository.

Finally commit your changes (the files you added) by executing this command.

git commit -a -m "Initial import of project contents"

Creating a Feature Branch (Epic 4-1a Task ii)

At the moment you are working on the 'master' version of the project, when using Scrum it is usual to create a branch off the master version when creating a new feature. We will create the Owner Entity class next but before we do lets create a feature branch to do the development on. This way if we make a mistake or decide to go back to our current state we can just switch back to the 'master' branch. The following diagram illustrates this concept.

workingOnAFeatureBranch.png

This is the simplest method for working by yourself, usually when working on large projects with many developers a number of branches are created off the master and merges are carried out between them. To get an overview I can recommend this page Git Branching Workflows. For our purposes the master/feature branch method will work fine.

Creating a feature branch using 'git' is simple just execute this simple command.

git checkout -b owner_entity

You are now working on a new feature branch.

Create the Owner Class (Epic 1a)

Before we create the 'Owner' class we need to make some changes to the default pom.xml generated when we create our 'pfm-model' project. It needs to have some dependencies added to support the Owner class, the next section describes what is necessary.

Modifying the Maven POM

Firstly we will update the default unit testing framework (JUnit) to version 4 and then add the 'javax.persistence' dependency. This dependency makes it possible to create annotations for our classes so as to map them to a database. We also change the jar version to 1.0.1 and set the compiler version to 1.6 needed for using Annotations as they are not supported in ealier Java compilers, see the new pom.xml below.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.inivitiv.tutorials.pfm.domain</groupId>
  <artifactId>pfm-model</artifactId>
  <version>1.0.1</version>
  <packaging>jar</packaging>

  <name>pfm-model</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <verbose>true</verbose>
          <fork>true</fork>
          <compilerVersion>1.6</compilerVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>javax.persistence</groupId>
      <artifactId>persistence-api</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Creating an Eclipse Project

Now would also be a good time to import our project into your favourite IDE, I use Eclipse. Maven can be used to create the necessary IDE project files so that the project imports easily into your IDE.

For eclipse execute the following maven command...

mvn eclipse:eclipse
For other IDE's such as IntelliJ or Netbeans maven support is already incorporated, just create a new project based on Maven and point your IDE to the 'pfm-model' directory.

Now we can create the Owner Entity Class...
(click inside box to select code)

package com.inivitiv.tutorials.pfm.domain;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

public class Owner implements Serializable{
/**
* Serialization UID
*/
private static final long serialVersionUID = 4117246466654386817L;

/*
* Unique Id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "OWNER_ID")
private Long id;
/*
* First Name.
*/
@Column(name = "first_name", nullable = false)
private String firstName;
/*
* Middle name (if any)
*/
@Column(name = "middle_name")
private String middleName;
/*
*  Surname
*/
@Column(name = "surname", nullable = false)
private String surname;
/*
* Default no arg constructor (required for Spring Framework injection)
*/
public Owner() {

}
/**
* Arg filled contructor for initializing an object.
* @param firstName - The Owners first name
* @param middleName - The Owners middle name 
* @param surname - The Owners surname
*/
public Owner(String firstName, String middleName, String surname){
this.firstName = firstName;
this.middleName = middleName;
this.surname = surname;
}
public Long getId() {
	return id;
}
public void setId(Long id) {
	this.id = id;
}
public String getFirstName() {
	return firstName;
}
public void setFirstName(String firstName) {
	this.firstName = firstName;
}
public String getMiddleName() {
	return middleName;
}
public void setMiddleName(String middleName) {
	this.middleName = middleName;
}
public String getSurname() {
	return surname;
}
public void setSurname(String surname) {
	this.surname = surname;
}
}

This is a simple POJO (Plain Old Java Object), it uses the javax.persistance package so that we can annotate the class with database table and column declarations. These annotations will be used later when we develop a persistance layer.

Creating a Unit Test

Now we will create a Unit Test for our new class. We will be using JUnit4 Unit testing framework that we already added the dependency for in our maven pom.xml file. You will notice that I test setters/getter in this test, some say this is overkill but I disagree.

If for instance you were to inadvertantly make a mistake in the code and do this...


public void setSurname(String surname) {
this.middleName = surname;
}

The mistake would not manifest itself until much later in the development process and as everyone knows fixing bugs is much more expensive in time and resources than getting the coding and tests correct! With this kind of testing you know that your class is bullet proof.

(click inside box to select code)

{literal}
package com.inivitiv.tutorials.pfm.domain;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class OwnerTest {

/**
 * Owner used for all tests.
 */
private Owner owner;

/**
 * Create an instance of the Owner and initialise
 * @throws Exception
 */
@Before
public void setUp() throws Exception {
	owner = new Owner();
	owner.setId(1L);
	owner.setFirstName("Test First Name");
	owner.setMiddleName("Test Middle Name");
	owner.setSurname("TestSurname");
}
@Test
public void testOwner() {
	assertTrue(null != this.owner);
}
@Test
public void testOwnerInitContructor(){
	Owner lOwner = new Owner("FirstName", "MiddleName", "Surname");
	assertEquals("FirstName", lOwner.getFirstName());
	assertEquals("MiddleName", lOwner.getMiddleName());
	assertEquals("Surname", lOwner.getSurname());
}
@Test
public void testGetId() {
	assertTrue(1L == owner.getId());
}
@Test
public void testGetFirstName() {
	assertEquals("Test First Name",owner.getFirstName());
}
@Test
public void testGetMiddleName() {
	assertEquals("Test Middle Name",owner.getMiddleName());
}
@Test
public void testGetSurname() {
	assertEquals("TestSurname",owner.getSurname());
}
}

{/literal}

Not run your tests by executing this maven command.

mvn clean test

Your final output should indicate the all the tests completed sucessfully

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.inivitiv.tutorials.pfm.domain.OwnerTest
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.057 sec
Running com.inivitiv.tutorials.pfm.domain.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 7, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.030s
[INFO] Finished at: Mon Mar 17 12:59:21 MDT 2014
[INFO] Final Memory: 11M/150M
[INFO] ------------------------------------------------------------------------

If you now take a look inside the 'target' subdirectory of your project you will find some text reports describing the results of your tests. They are found in the directory 'target/surefire-reports' within this directory are text and XML formatted reports. The text files are a summary of the total tests and the XML formatted reports contain much more information regarding the tests, but are not particulary readable. It is more desirable to generate them in HTML format so we can view them in a browser. Fortunately this is quite simple, the next section shows you how.

Generate HTML Reports (Epic 5-1a Task i,ii,iii)

Creating HTML reports regarding the status of your code is an important task and give some idea of the quality of the code.

Unit Test Reporting

To generate HTML Unit Test reports is very simple with maven, there is a reporting plugin that takes care of it for you, just add a reporting section with the appropiate plugin and you are ready to go. Just add this section after the </build> tag. (click inside box to select code)

<reporting>
<plugins>
<!-- JUnit test reports -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.17</version>
</plugin>	
</plugins>
</reporting>

Now execute...

mvn site

Once this maven target has completed you will find a nicely formatted report at this location 'target/site/surefire-report.html'. Quite a comprehensive report of all your JUnit tests. Here is a preview of a small section that has links allowing you to drill down into each test.

surfire-report.png

Code Coverage Reports

Of course just because you have written lots of tests does not necessary mean your code is well tested. What if you missed testing a method or a complete section of your code, well that is where code coverage reporting comes in. It will report on how much of your class is tested, the final icing on the cake for unit testing to be complete.

Add this section to your pom.xml to generate code coverage HTML reports after the JUnit reporting plugin section shown above.

<!-- Emma Unit test coverage -->
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>emma-maven-plugin</artifactId>
  <version>1.0-alpha-3</version>
</plugin>

Now execute...

mvn site

The code coverage reports can be found at this location 'target/site/emma/index.html'

Coding Guidelines Reports

Finally to complete our reporting we will add coding guidelines reporting. If you write for any of the opensource projects out there or even as a contractor for an organisation you will need to make sure you comply or your code will be rejected. So to create coding guideline reports add this section to your pom.xml, we will be using the Sun Java Coding Guidelines (now Oracle of course).

Add this section to your pom.xml to generate code coverage HTML reports after the Emma reporting plugin section shown above.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>2.12</version>
  <reportSets>
    <reportSet>
      <reports>
        <report>checkstyle</report>
      </reports>
    </reportSet>
  </reportSets>
</plugin>

Execute this maven command again.

mvn site
Now you have a coding guideline report for the code you have written at this location in your project 'target/site/checkstyle.html'. Do not worry at this stage about the reported errors, you should configure the above plugin to use the guidelines specified by your organisation. See the plugin's web site for how to do this at Maven Apache Checkstyle Configuration.

Check in Your Work

Now would be a good time to check in your work using git. Execute the command.

git commit -a -m "Owner Entity class created and tested"

Merging the Feature Branch

Remember earlier in this Sprint we create a feature branch using 'git' our SCM system. Then once we have completed all the steps on the previous page we checked in our work after we had run our tests and made sure everything was working. Now we need to merge back to the main branch as we have completed all our work for Sprint One.

Doing this with git is simple, navigate to the pfm-model project and execute the following commands.

This will put you back on the master branch...

git checkout master
This will merge your feature branch into the master branch...
git merge owner_management

You have now managed to merge your changes back. Obviously because you are the only one working on this project there are now conflicts so it was very trivial and you should not get any errors.

Tag the Release

There are many ways of releasing a product or library, the 'Git' web site is a good resource especially the section on Basic Branching and Merging. For the pfm-model library we will tag the master branch now that we have sucessfully merged back. The tag name will be the version we have in our pom.xml so it matches and we can trace it back, or create the version anytime we need if necessary.

Execute this command to tag our release.

git tag -a 1.0.1 -m "Initial release with Owner entity and tests" master

Installing the pfm-model Project

Installing a maven project means to add it to your repository so you can refer to it as a dependency in another project. You have already installed locally other projects that are used within the pfm-model projects pom.xml. For instance the JUnit framework is simply a JAR file that is installed in your repository so you can use it in your project. The default location for your local maven repository is in your home directory in a sub-directory named '.m2/repository/'. So for a Windows PC this is found in 'C:\Documents and Settings\<your-username>\.m2\repository' whereas on Linux/Mac/Unix it is found in '~/.m2/repository/'.

Of course you can change this if you want by specifying a location in the maven configuration file found within your maven installation the root of which is specified by an environment variable named 'M2_HOME' within this location it can be found in the 'config' subdirectory the file is named 'settings.xml'. Just specify your location by editing the tag <localRepository>/path/to/repository/here</localRepository> its as easy as that.

Now we will install our pfm-model project jar file to the repository so we can refer to it in our database layer that we will create next.

Execute the maven command....

mvn install
The project will be compiled, tested, packaged and then installed in the repository. Now look inside your maven repository and you will see it has been installed at: -
'<your home directory>/.m2/repository/com/inivitiv/tutorials/pfm/domain/pfm-model/1.0.1/pfm-model-1.0.1.jar'.

Sprint One is almost complete we just need to add persistance, on the next page we will create a new maven project for this layer.

Date Entered2014-06-08