Raul Estrela
May 2024Aspects of software design are almost never a pure style issue or just a personal preference
“There is no such thing as “perfect” code - there is only better code. Instead of seeking perfection, what a code review (Reviewer) should seek is continuous improvement.”
The functionality is good for the users of the code?
The code is well-designed?
The code is more complex than it needs to be?
Code has appropriate tests and tests are well designed?
Are all of the comments actually necessary and explaning the why?
The code conforms to project style guidelines?
Code is consistent with the recommendations or the surrounding code?
Code is appropriately documented?
Design • Functionality • Comments • Style • Consistency • Documentation • Complexity • Tests & Coverage
It will prefil automatically the Code Review details...
Avoid surprises...
Look at the Code Review description, the commit and what the code does in general. Does this change even make sense?
If this change shouldn't have happened in the first place, please respond immediately with an explanation of why the change should not be happening.
When you reject a change like this, it's important suggest to the developer what they should have done instead and reject the code.
“There was a recent announcement that the library mapping4js won't be supported anymore from version 2.5. (circumstance)
I'm afraid this is not the best way to go. I'm aware of the current limitation of the existing mapping implementation (...) (acknowledge)
but I was just having a look on this other library (...), seems to be a better approach in the long term. What to you think? (guidance/openness)
Btw, I really liked the idea of replacing the custom library! (positivity)”
“I found this idea really interesting but I'm afraid that doing such a risky change at this specific time will impact delivery of other features currently being implemented. (circumstance) Your point in adding this library is totally valid (acknowledge), but I was having a look and I found this alternative Here's an how we (teamwork) could do possibly achieve a good result:”
// form-validator.js
const complex = (typeA, typeB) => { typeA, typeB }
// validations.js
address: use(complex)
“What do you think if we proceed with this workaround for now and add the library later? (guidance)”
“At the surface the changes look good (positivity), tests are passing but testing coverage was affected a bit. (circumstance) I guess you forgot to test the new mapping functions. Also, there are 3 concerning code quality issues raised by Sonar. (guidance/openness) Can you please have a look?”
Find the file or files that are the “main” part of the change. Often, there is one file that has the largest number of logical changes, and it's the major piece of the work done. Look at these major parts first. This helps give context to all of the smaller parts, and generally accelerates doing the code review.
If you see some major design problems with this part of the code, you should send those comments immediately and reject the changes, even if you have time to review the rest of the changes right now.
“I believe this function is not typesafe and this might raise some problems mapping mixed numeric types. Plus, it doesn't check for empty values. I've noticed already that the numeric property `total` already lost the desired precision, and unit tests show that if the value if `tax` is absent the default value will be null. This can raise some problems in the upstream services. (circumstance) Leaving here an example on how can we possibly overcome this, let me know your thoughts:” (guidance/teamwork/openness)
// BalanceMapper.java
var taxMapper = new NumberMapper<BigDecimal> { (...) }
var transactionsMapper = new NumberMapper<Long> { (...) }
// Mapper.java
(...).tax(taxMapper.map(tax)).transactions(transactionsMapper.map(transactions))(...)
“This explicit constructor can be avoided, plus this class can be immutable. (circumstance) Please consider similar use cases in this package, where the Builder pattern is being used. (guidance) I believe it's an improvement that brings value without too much effort. (awareness) Please let me know what do you think and feel free to suggest an alternative approach.”(teamwork/openness)
“The stubbing of these 3 methods in this test class are using generic values, this does not guarantee that the correct datatypes conversion is happening (circumstance), right? Please let me know if there's anything I'm missing.”(teamwork/openness)
Sometimes it's also helpful to read the tests first before you read the main code, because then you have an idea of what the change is supposed to be doing.
At this step you might suggest doing some things differently or some improvements to the original solution.
“Suggestion: replace if else with switch statement (readibility). Example:”
private String getGenderDescription(GenderCode gender) {
return switch (gender) {
case F -> "Female";
case M -> "Male";
case U -> "Unknown";
default -> "None";
};
}
“Nit: change parameter name to "genderCode" instead of "gender"”
“FYI: This testing class is becoming unmaintainable. I don't expect you to do this in this CL, but you may find this interesting to think about for the future.”
“Nice detail. Thanks for refactoring this part here, it was a bit messy.”
All questions raised are closed by the reviewers, and there's mutual agreement between both parts on the changes performed.
The necessary number of reviewers accepted the changes proposed