summaryrefslogtreecommitdiff
path: root/src/Q1/README.md
blob: 57457fefcffc248d7f9a4cf30a06209daee5c626 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
Learning Profile for Assignment #1, And Question #1

Name: Mo Khan
Student ID: 3431709

1. Problem Statement:

Create a class named AddressBook that has the following field names:

* firstName
* middleName
* lastName
* homeAddress
* businessPhone
* homePhone
* cellphone
* skypeId
* facebookId
* personalWebSite

Use appropriate data types to store the values for these fields in AddressBook objects.
Create appropriate get and set methods to retrieve and assign values to these names.
For example `getMiddleName(viveAddressBook)` should return the middle name of the person `Vive`.
Similarly, `vive.setPersonalWebsite(url)` should set the personal website of the person `Vive` to the specified URL object.
Using the get and set methods, create a comparison method `compareNames(name1, name2)` that compares the first, middle, and last names of strings name1 and name2.
Assume that name1 and name2 follow the following format: "FirstName M. LastName".

Test your program for correct, partially correct (e.g., name string without the middleName),
and incorrect inputs (e.g., phone number containing special characters).


2. Description of the Code: 

I solved this exercise by installing `maven` and `junit`. Then I started
implementing the `AddressBook` API one method at a time.

I had trouble understanding the `compareNames` API because it was
non-intuitive to me. I have previously worked with `C#` and am familiar
with the `IComparer<T>` interface so I looked for the equivalent in
Java. I found the `Comparable<T>` interface and chose to implement that.

The `Comparable<T>` interface requires implementers to implement a
method named `compareTo` that returns an integer value. This interface
is used for sorting.

Instead of trying to interpret how the `compareNames` method is supposed
to behave, I chose to delegate to `compareTo` and return the string
representation of the integer value.

I also chose to override equality for this object to use `value`
equality instead of `reference` equality.

For code style I chose to use the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). I used a maven plugin to auto format the code to abide by the style guide each time I ran the tests.

3. Errors and Warnings:

I practice test driven development. So I always focus on writing a
failing test first. This allows me to make sure that I see the intended
failure in my test before implementing the required code to make it
pass. It also helps me design the API of my software from the
perspective of the client code that would use my software. The design
benefits of test driven development were not as useful here, since the
design of the API was provided to us in the assignment.

Here's an example of a failure that occurred when I wrote the test first
before implementing the required interface.

```bash
モ mvn test
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< ca.mokhan.comp268:assignment1 >--------------------
[INFO] Building assignment1 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- fmt-maven-plugin:2.8:format (default) @ assignment1 ---
[INFO] Processed 8 files (0 reformatted).
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ assignment1 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/mokha/development/gh/comp-268/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ assignment1 ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 4 source files to /Users/mokha/development/gh/comp-268/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /Users/mokha/development/gh/comp-268/src/Q1/AddressBookTest.java:[21,12] cannot find symbol
  symbol:   method setFirstName(java.lang.String)
  location: variable subject of type Q1.AddressBook
[ERROR] /Users/mokha/development/gh/comp-268/src/Q1/AddressBookTest.java:[81,9] cannot find symbol
  symbol:   method setFirstName(java.lang.String)
  location: variable hunk of type Q1.AddressBook
[ERROR] /Users/mokha/development/gh/comp-268/src/Q1/AddressBookTest.java:[85,10] cannot find symbol
  symbol:   method setFirstName(java.lang.String)
  location: variable shiro of type Q1.AddressBook
[INFO] 3 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.759 s
[INFO] Finished at: 2019-05-13T19:55:36-06:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project assignment1: Compilation failure: Compilation failure:
[ERROR] /Users/mokha/development/gh/comp-268/src/Q1/AddressBookTest.java:[21,12] cannot find symbol
[ERROR]   symbol:   method setFirstName(java.lang.String)
[ERROR]   location: variable subject of type Q1.AddressBook
[ERROR] /Users/mokha/development/gh/comp-268/src/Q1/AddressBookTest.java:[81,9] cannot find symbol
[ERROR]   symbol:   method setFirstName(java.lang.String)
[ERROR]   location: variable hunk of type Q1.AddressBook
[ERROR] /Users/mokha/development/gh/comp-268/src/Q1/AddressBookTest.java:[85,10] cannot find symbol
[ERROR]   symbol:   method setFirstName(java.lang.String)
[ERROR]   location: variable shiro of type Q1.AddressBook
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
```

Here is the output after fixing the failing test:

```bash
モ mvn test
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< ca.mokhan.comp268:assignment1 >--------------------
[INFO] Building assignment1 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- fmt-maven-plugin:2.8:format (default) @ assignment1 ---
[INFO] Processed 8 files (0 reformatted).
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ assignment1 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/mokha/development/gh/comp-268/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ assignment1 ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 4 source files to /Users/mokha/development/gh/comp-268/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ assignment1 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/mokha/development/gh/comp-268/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ assignment1 ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 4 source files to /Users/mokha/development/gh/comp-268/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ assignment1 ---
[INFO] Surefire report directory: /Users/mokha/development/gh/comp-268/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running ca.mokhan.comp268.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.01 sec
Running ca.mokhan.test.AddressBookTest
Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

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

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.552 s
[INFO] Finished at: 2019-05-13T19:56:21-06:00
[INFO] ------------------------------------------------------------------------
```

4. Sample Input and Output:

The test cases are described in `AddressBookTest.java`.

5. Discussion:

When I look at the design for the `AddressBook` class there are a few
things that come to mind.

1. The name `AddressBook` is a poor choice for a name. This object does
   not represent an address book but rather a single contact in an
   address book. I would split this class into two. One class named
   `Contact` that represents the individual details for a contact in the
   address book and a class named `AddressBook` that acts as the
   aggregate root for contacts.
2. This is more of a comment on Java than the API design, but `Java`
   properties seem to requires A LOT of ceremony.

For example in `Ruby` you can define a property/attribute very
succinctly.

```ruby
class Contact
  attr_accessor :first_name
end
```

C# also has a nice shorthand for this. C# also allows specifying
different access control for the getter and setter.

```csharp
public class Contact {
  public string FirstName { get; set; }
}
```

Finally the `Java` version requires much more ceremony.

```java
public class Contact {
  private String firstName;

  public String getFirstName() {
    return this.firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
}
```