You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: report.md
+230-1
Original file line number
Diff line number
Diff line change
@@ -144,14 +144,65 @@ It is stated that `replacementNode` can be null and that `nodeToRemoved` can't b
144
144
Could be stated in the documentation that if the root of the BST is null the function simply returns an empty array. Shouldn't have to browse through the code to find this fact. Although it is stated that the input `order` determines how the array is sorted, this could be explained in more detail.
Like @psalqvist, I set CCN=2 and for each `if`, `for`, `while`, `else if`, `&&` and `||` (not for `else`) i added 1 and for each return i subtracted with 1. There was a slight difference between the results computed from manual count and the counting from lizard tool.
149
156
157
+
##### 2.
158
+
There does exist a similarity between the length of the function and the complexity for it.
150
159
151
-
#### @Kubha99
160
+
##### 3.
161
+
###### balanceAfterInsert
162
+
Has input of `RedBlackNode` as input and balances the given tree, this function is called once we insert a node in the tree
163
+
164
+
###### balanceAfterDelete
165
+
Similar to `balanceAfterInsert` this function takes a `RedBlackNode` and balances the tree after a delete
166
+
167
+
##### 4.
168
+
In `balanceAfterDelete` there exists a case where an execption needs to be handled.
169
+
170
+
##### 5.
171
+
Both of the functions are well documented and there exists line comments explaining what operations are done and sometimes why.
172
+
There also exists documentation for input as well as output.
Like @psalqvist, we start with CCN = 2 then add 1 for `if`, `for`, `while`, `else if`, `&&` and `||` (not for `else`), and subtract 1 to CCN when reaching a `return` statement. The result shows a lower manual CCN. It is because that in both functions there are more than 1 return point, especially in the `BTree.validateNode`, almost every `if` statement is followed by a `return` code.
184
+
185
+
##### 2.
186
+
Looking at the CCN result from lizard it seems like NLOC correlates with CCN. The manual count for `Multiplication.multiplyUsingLogs` also indicates that.
187
+
188
+
##### 3.
189
+
###### validateNode
190
+
Takes a `node` object as input and validates the node according to the B-Tree invariants. Returns `True` if valid, else `false`.
191
+
192
+
###### multiplyUsingFFT
193
+
Takes two `string` objects as input and extract the numbers, then multiply the two numbers using Fast Fourier transform method. Returns the result as a `string`.
194
+
195
+
##### 4.
196
+
There are no exceptions in either of the functions.
197
+
198
+
##### 5.
199
+
###### validateNode
200
+
This function is well documented since there are many comments that explain what some part of the function does. It is also clear what the input and output are.
201
+
202
+
###### multiplyUsingFFT
203
+
There are no comments in the code which makes it harder for the reader to know what each part does. However, if you are familiar with the FFT method it can be intuitive.
204
+
205
+
155
206
156
207
157
208
## Refactoring
@@ -164,6 +215,121 @@ Carried out refactoring (optional, P+):
164
215
165
216
git diff ...
166
217
218
+
219
+
### @nolanderc: `BinaryHeapArray.heapDown`
220
+
221
+
The main goal of refactoring should be to reduce the amount of duplication in the `if` statements. For example, there is one that looks like this:
222
+
```java
223
+
if ((type ==Type.MIN&& left !=null&& right !=null&& value.compareTo(left) >0&& value.compareTo(right) >0)
224
+
|| (type ==Type.MAX&& left !=null&& right !=null&& value.compareTo(left) <0&& value.compareTo(right) <0) {
225
+
...
226
+
}
227
+
```
228
+
Here the checks for `left !=null` and `right !=null` are duplicated twice each. Also the comparisons against `value` are repeated twice, but with different operators (`<` and `>`).This pattern is repeated an additional 2-4 times, depending on how you count.
229
+
230
+
We can reduce the cyclomatic complexity of this code by restructuring the code so that each check fornull only happens once, and which comparison to do against the value is determined by the `type` only a single time. Applying these changes results in something the following:
231
+
232
+
```java
233
+
// determine the order we want nodes in once
234
+
int desiredOrder = (type ==Type.MIN) ?-1:1;
235
+
int undesiredOrder =-desiredOrder;
236
+
237
+
// Do checks against null and perform comparisons against the parent value.
238
+
// If their order does not match the desired, we need to swap them.
239
+
boolean leftShouldSwap = left !=null&&Integer.signum(value.compareTo(left)) == undesiredOrder;
240
+
boolean rightShouldSwap = right !=null&&Integer.signum(value.compareTo(right)) == undesiredOrder;
241
+
242
+
// handle different cases depending on which child needs to swap with the parent
243
+
if (leftShouldSwap & rightShouldSwap) {
244
+
// if both need to swap, make sure that swapping preserves the desired order
This is essentially everything the old 46 nLOC function did, but with multiple levels of nested `if` statements and convuluted logic. In the end, the new version uses two functions with a cyclomatic complexity of 2 and 10, respectively. Compare this to the old version which had a cyclomatic complexity of 41.
To improve the cyclomatic complexity we want to either remove or reduce the use of `if`, `for`, `while`, `else if`, `&&` and `||`. In the multiplyUsingFFT we can find a lot of if statements used to investigate both of the input numbers since they are strings. For instance the following is used to check whether the product is negative.
This can be improved by converting both of the strings to integers and check if the product is negative or not.
272
+
273
+
```java
274
+
int x =Integer.parseInt(a);
275
+
int y =Integer.parseInt(b);
276
+
if(x*y <0) negative =true;
277
+
```
278
+
By doing this we have reduced the cyclomatic complexity but the drawback is that we initiate new variables and we are dependent on another library.
279
+
280
+
Lastly, we can remove the use of some commonly used operations by promoting them to a function. For instance, since both strings are edited to remove the minus symbol (the following code), we can reduce the complexity by adding a helper function that gets called for each string. The drawback is of course those additional functions.
281
+
```java
282
+
if (a.charAt(0) =='-') {
283
+
a = a.substring(1);
284
+
}
285
+
if (b.charAt(0) =='-') {
286
+
b = b.substring(1);
287
+
}
288
+
```
289
+
290
+
In the end, we managed to reduce the CCN from 21 to 13.
291
+
292
+
Git diff:Check the refactor section [here](https://docs.google.com/document/d/1qRhKoisnicSaKS3oRQEs6EaFpCoqO1QLV4kNYcLeAFo/edit?usp=sharing).
293
+
294
+
### `BTree.validateNode`
295
+
296
+
As with the previous function we aim to reduce the use of `if`, `for`, `while`, `elseif`, `&&` and `||`.Inthiscase a lot of if statements were used to check a specific condition and directly followed by a `return`.For example the following:
297
+
298
+
```java
299
+
if (keySize < minKeySize) {
300
+
returnfalse;
301
+
} elseif (keySize > maxKeySize) {
302
+
returnfalse;
303
+
} elseif (childrenSize ==0) {
304
+
returntrue;
305
+
} elseif (keySize != (childrenSize -1)) {
306
+
returnfalse;
307
+
} elseif (childrenSize < minChildrenSize) {
308
+
returnfalse;
309
+
} elseif (childrenSize > maxChildrenSize) {
310
+
returnfalse;
311
+
}
312
+
```
313
+
314
+
This can be reduced by creating a helper function that does the same thing and then we just need to check the value returned by the helper function. The code above can be replaced with the following:
315
+
316
+
```java
317
+
// make the check in another function and save the result
318
+
int checkNonRoot = validateNonRootHelper(keySize, childrenSize);
319
+
// return the corresponding boolean
320
+
if (checkNonRoot ==0) {
321
+
returnfalse;
322
+
} elseif (checkNonRoot ==1) {
323
+
returntrue;
324
+
}
325
+
```
326
+
The drawback is that we need to add a few additional functions and variables.
327
+
328
+
In the end, we managed to reduce the CCN from 22 to 14.
329
+
330
+
Git diff:Check the refactor section [here](https://docs.google.com/document/d/1qRhKoisnicSaKS3oRQEs6EaFpCoqO1QLV4kNYcLeAFo/edit?usp=sharing).
331
+
332
+
167
333
## Coverage
168
334
169
335
### Tools
@@ -173,6 +339,12 @@ Document your experience in using a "new"/different coverage tool.
173
339
How well was the tool documented?Was it possible/easy/difficult to
174
340
integrate it with your build environment?
175
341
342
+
### NOTES
343
+
344
+
#### @ekorre1001
345
+
346
+
The code coverage tool I am using is OpenClover which works with the Ant build tool. I followed the provided quick start guide and managed to integrate it with Ant. It was quite easy to do the setup since only a few steps were required, although a few things did not work out initially.
347
+
176
348
### Your own coverage tool
177
349
178
350
Show a patch (or link to a branch) that shows the instrumented code to
@@ -186,6 +358,20 @@ git diff ...
186
358
What kinds of constructs does your tool support, and how accurate is
187
359
its output?
188
360
361
+
#### @nolanderc
362
+
363
+
See `git show 9ef482092816b3367f4d4b45214821ee11019fe3`
364
+
365
+
It supports `if` statements, `while` loops and `for` loops. The output should
366
+
show exactly how many times a code block was executed, and also notify if a code
367
+
block has not been executed. Example:
368
+
369
+
```
370
+
BranchCoverageTest.branchCoverageWithNotReached:
371
+
- entry point:1
372
+
- not reached:0<--NOTREACHED
373
+
```
374
+
189
375
### Evaluation
190
376
191
377
1.How detailed is your coverage measurement?
@@ -208,6 +394,49 @@ git diff ...
208
394
209
395
Number of test cases added: two per team member (P) or at least four (P+).
210
396
397
+
### NOTES
398
+
399
+
400
+
#### @ekorre1001
401
+
402
+
Changed to another function because:
403
+
404
+
BTree::validateNode:Barely any test for the data structure and no test forthis specific function which makes it harder to understand.
0 commit comments