Insurance Premium Quote Challenge
up vote
1
down vote
favorite
I was failed at coding challenge for my interview with the following reasons given by the interviewer: deep use of mutation and a not that well thought up internal API.
I understand that my code and design have so many flaws and I genuinely want to get your opinion so I could improve my code.
The challenge is about asking me to build a quote processor to calculate a premium for different products, based on different rule sets.
Since the requirements are very lengthy, I try to summarize it below:
Data model
- A user (with an id, an address, and a risk value)
- An address (with an id and a location risk value)
- A product (with an id and a price value)
(Risk values are in our patented Universal Risk Value Scale [tm])
For products we have modelled in our system the following types:
- Houses (with address and size in square meters)
- Bananas (with number of black spots)
- Bicycles (with number of gears)
Asides from above, the premium quote would need to take in rules, base surcharge, universal risk value for each product and each user to quote a premium for user.
Rules
We want to build a quote processor that will receive a user and a set of products, and return whether we reject the user or not, and if not, for how much premium will we insure the products in euros per year.
To ensure this, we have a set of rules to follow.
Each product will have a base premium value, that multiplied by the product value will give a subtotal for the product's premium. To this subtotal, we must add a surcharge that depends on the product type and maybe on other rules. Each surcharge is multiplied to the base value.
Then, for all the products, if for one the rules say that it is un-insurable, then the final result given is that we won't offer an insurance. If no product is un-insurable, then we add all the premiums and that is the quote we return to the user.
Below are my classes, I am putting here one or two model classes just to present my design.
It is my first time using SO so I do not know how to put code in a good way yet, please understand.
- Interfaces:
public interface Product {
BigDecimal getProductValue();
BigDecimal getBasePremium();
BigDecimal getSubTotalPremium();
}
public interface Risk {
void setRiskValue(int riskValue);
BigDecimal getRiskSurcharge();
static BigDecimal getUnIdentifiedRiskSurcharge()
{
return new BigDecimal(-1);
}
static BigDecimal getDefaultRiskSurcharge()
{
return new BigDecimal(0);
}
static boolean isWithinRange(int riskValue, int minValue, int maxValue)
{
return riskValue >= minValue && riskValue <= maxValue;
}
}
- Model classes:
- Base class InsuredProduct implements above interfaces.
public abstract class InsuredProduct implements Product, Risk {
private int id;
private BigDecimal productValue;
private int riskValue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public InsuredProduct(int id, BigDecimal productValue)
{
this.id = id;
this.productValue =productValue;
}
public BigDecimal getProductValue() {
return productValue;
}
public void setProductValue(BigDecimal productValue) {
this.productValue = productValue;
}
@Override
public BigDecimal getSubTotalPremium()
{
return getProductValue().multiply(getBasePremium());
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
public int getRiskValue() {
return this.riskValue;
}
}
- Then Banana class as insured product extends from base class:
public class Banana extends InsuredProduct {
private static BigDecimal BASE_PREMIUM = new BigDecimal(1.15);
private int noOfBlackSpots;
private int userRiskValue;
public Banana(int id, BigDecimal productValue) {
super(id, productValue);
}
public int getNoOfBlackSpots() {
return noOfBlackSpots;
}
public void setNoOfBlackSpots(int noOfBlackSpots) {
this.noOfBlackSpots = noOfBlackSpots;
}
@Override
public BigDecimal getBasePremium() {
return BASE_PREMIUM;
}
@Override
public BigDecimal getRiskSurcharge() {
if(this.userRiskValue > 200)
return Risk.getUnIdentifiedRiskSurcharge();
final int minAcceptableBlackSpots = 3;
final int maxAcceptableBlackSpots = 12;
if(Risk.isWithinRange(this.noOfBlackSpots, minAcceptableBlackSpots, maxAcceptableBlackSpots))
return Risk.getDefaultRiskSurcharge();
return Risk.getUnIdentifiedRiskSurcharge();
}
@Override
public void setRiskValue(int riskValue) {
this.userRiskValue = riskValue;
}
}
- A User class (with Address) as an insured person. User's address is also part of risk surcharge to determine the quote calculation.
public class User implements Risk {
private static final BigDecimal MAXIMUM_USER_RISK_SURCHARGE = new BigDecimal(3.0);
private static final BigDecimal MEDIUM_USER_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_USER_RISK_SURCHARGE = new BigDecimal(0.3);
private int id;
private Address address;
private int riskValue;
public User(int id, Address address)
{
this.setId(id);
this.setAddress(address);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getRiskValue() {
return riskValue;
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedRiskValue = 501;
final int startMinimumRiskValue = 20;
final int endMinimumRangeRiskValue = 200;
final int startMaximumRiskValue = 201;
final int endMaximumRangeRiskValue = 500;
if(this.getRiskValue() >= unsupportedRiskValue)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumRiskValue)
return MINIMUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumRiskValue, endMinimumRangeRiskValue))
return MEDIUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumRiskValue, endMaximumRangeRiskValue))
return MAXIMUM_USER_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
public class Address implements Risk{
private static final BigDecimal MAXIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(2.5);
private static final BigDecimal MEDIUM_LOCATION_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(0.7);
private int id;
private int locationRisk;
public Address(int id)
{
this.id = id;
}
public int getRiskValue() {
return locationRisk;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public void setRiskValue(int riskValue) {
this.locationRisk = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedLocationRisk = 502;
final int startMinimumLocationRisk = 100;
final int endMinimumRangeLocationRisk = 299;
final int startMaximumLocationRisk = 300;
final int endMaximumRangeLocationRisk = 501;
if(this.getRiskValue() >= unsupportedLocationRisk)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumLocationRisk)
return MINIMUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumLocationRisk, endMinimumRangeLocationRisk))
return MEDIUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumLocationRisk, endMaximumRangeLocationRisk))
return MAXIMUM_LOCATION_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
- Processor: To calculate the premium quote or to determine if it's is insurable.
public class UserPremiumBuilder<T extends InsuredProduct> {
private User user;
T product;
private UserPremiumBuilder(User user){
this.user = user;
}
public static <T extends InsuredProduct> UserPremiumBuilder<T> createProfile(User user){
UserPremiumBuilder<T> builder = new UserPremiumBuilder<T>(user);
return builder;
}
public UserPremiumBuilder <T> setProduct(T product) {
this.product = product;
return this;
}
public BigDecimal calculateSingleProductPremiumForUser() {
BigDecimal userRiskSurcharge = user.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(userRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
this.product.setRiskValue(this.user.getRiskValue());
BigDecimal productRiskSurcharge =this.product.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(productRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
if(Risk.getDefaultRiskSurcharge().compareTo(productRiskSurcharge)==0)
return this.product.getSubTotalPremium();
BigDecimal totalPremium = this.product.getSubTotalPremium().multiply(this.product.getRiskSurcharge()).multiply(user.getRiskSurcharge());
return totalPremium;
}
}
- A sample unit test class:
public class UserPremiumBuilderBananaTest {
Banana banana;
@Before
public void initBanana()
{
banana = new Banana(1, new BigDecimal(10));
}
@Test
public void testUnInsurableBananaRiskSurchargeWithUserRiskValueLargerThan200() {
User user = initUser(10);
user.setRiskValue(201);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(4);
BigDecimal totalPremium = createProfile(user).setProduct(banana).calculateSingleProductPremiumForUser();
assertEquals(Risk.getUnIdentifiedRiskSurcharge(), totalPremium);
}
@Test
public void testInsurableBananaRiskSurchargeWithUserRiskNotGreaterThan200() {
User user = initUser(10);
user.setRiskValue(200);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(3);
UserPremiumBuilder<Banana> builder = createProfile(user);
BigDecimal totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
BigDecimal productPremium = banana.getSubTotalPremium().setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
user.setRiskValue(199);
totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
}
private static UserPremiumBuilder<Banana> createProfile(User user)
{
return UserPremiumBuilder.createProfile(user);
}
private User initUser(int addressRiskValue)
{
Address address = new Address(1);
address.setRiskValue(addressRiskValue);
User user = new User(1, address);
return user;
}
}
java
New contributor
add a comment |
up vote
1
down vote
favorite
I was failed at coding challenge for my interview with the following reasons given by the interviewer: deep use of mutation and a not that well thought up internal API.
I understand that my code and design have so many flaws and I genuinely want to get your opinion so I could improve my code.
The challenge is about asking me to build a quote processor to calculate a premium for different products, based on different rule sets.
Since the requirements are very lengthy, I try to summarize it below:
Data model
- A user (with an id, an address, and a risk value)
- An address (with an id and a location risk value)
- A product (with an id and a price value)
(Risk values are in our patented Universal Risk Value Scale [tm])
For products we have modelled in our system the following types:
- Houses (with address and size in square meters)
- Bananas (with number of black spots)
- Bicycles (with number of gears)
Asides from above, the premium quote would need to take in rules, base surcharge, universal risk value for each product and each user to quote a premium for user.
Rules
We want to build a quote processor that will receive a user and a set of products, and return whether we reject the user or not, and if not, for how much premium will we insure the products in euros per year.
To ensure this, we have a set of rules to follow.
Each product will have a base premium value, that multiplied by the product value will give a subtotal for the product's premium. To this subtotal, we must add a surcharge that depends on the product type and maybe on other rules. Each surcharge is multiplied to the base value.
Then, for all the products, if for one the rules say that it is un-insurable, then the final result given is that we won't offer an insurance. If no product is un-insurable, then we add all the premiums and that is the quote we return to the user.
Below are my classes, I am putting here one or two model classes just to present my design.
It is my first time using SO so I do not know how to put code in a good way yet, please understand.
- Interfaces:
public interface Product {
BigDecimal getProductValue();
BigDecimal getBasePremium();
BigDecimal getSubTotalPremium();
}
public interface Risk {
void setRiskValue(int riskValue);
BigDecimal getRiskSurcharge();
static BigDecimal getUnIdentifiedRiskSurcharge()
{
return new BigDecimal(-1);
}
static BigDecimal getDefaultRiskSurcharge()
{
return new BigDecimal(0);
}
static boolean isWithinRange(int riskValue, int minValue, int maxValue)
{
return riskValue >= minValue && riskValue <= maxValue;
}
}
- Model classes:
- Base class InsuredProduct implements above interfaces.
public abstract class InsuredProduct implements Product, Risk {
private int id;
private BigDecimal productValue;
private int riskValue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public InsuredProduct(int id, BigDecimal productValue)
{
this.id = id;
this.productValue =productValue;
}
public BigDecimal getProductValue() {
return productValue;
}
public void setProductValue(BigDecimal productValue) {
this.productValue = productValue;
}
@Override
public BigDecimal getSubTotalPremium()
{
return getProductValue().multiply(getBasePremium());
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
public int getRiskValue() {
return this.riskValue;
}
}
- Then Banana class as insured product extends from base class:
public class Banana extends InsuredProduct {
private static BigDecimal BASE_PREMIUM = new BigDecimal(1.15);
private int noOfBlackSpots;
private int userRiskValue;
public Banana(int id, BigDecimal productValue) {
super(id, productValue);
}
public int getNoOfBlackSpots() {
return noOfBlackSpots;
}
public void setNoOfBlackSpots(int noOfBlackSpots) {
this.noOfBlackSpots = noOfBlackSpots;
}
@Override
public BigDecimal getBasePremium() {
return BASE_PREMIUM;
}
@Override
public BigDecimal getRiskSurcharge() {
if(this.userRiskValue > 200)
return Risk.getUnIdentifiedRiskSurcharge();
final int minAcceptableBlackSpots = 3;
final int maxAcceptableBlackSpots = 12;
if(Risk.isWithinRange(this.noOfBlackSpots, minAcceptableBlackSpots, maxAcceptableBlackSpots))
return Risk.getDefaultRiskSurcharge();
return Risk.getUnIdentifiedRiskSurcharge();
}
@Override
public void setRiskValue(int riskValue) {
this.userRiskValue = riskValue;
}
}
- A User class (with Address) as an insured person. User's address is also part of risk surcharge to determine the quote calculation.
public class User implements Risk {
private static final BigDecimal MAXIMUM_USER_RISK_SURCHARGE = new BigDecimal(3.0);
private static final BigDecimal MEDIUM_USER_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_USER_RISK_SURCHARGE = new BigDecimal(0.3);
private int id;
private Address address;
private int riskValue;
public User(int id, Address address)
{
this.setId(id);
this.setAddress(address);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getRiskValue() {
return riskValue;
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedRiskValue = 501;
final int startMinimumRiskValue = 20;
final int endMinimumRangeRiskValue = 200;
final int startMaximumRiskValue = 201;
final int endMaximumRangeRiskValue = 500;
if(this.getRiskValue() >= unsupportedRiskValue)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumRiskValue)
return MINIMUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumRiskValue, endMinimumRangeRiskValue))
return MEDIUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumRiskValue, endMaximumRangeRiskValue))
return MAXIMUM_USER_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
public class Address implements Risk{
private static final BigDecimal MAXIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(2.5);
private static final BigDecimal MEDIUM_LOCATION_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(0.7);
private int id;
private int locationRisk;
public Address(int id)
{
this.id = id;
}
public int getRiskValue() {
return locationRisk;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public void setRiskValue(int riskValue) {
this.locationRisk = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedLocationRisk = 502;
final int startMinimumLocationRisk = 100;
final int endMinimumRangeLocationRisk = 299;
final int startMaximumLocationRisk = 300;
final int endMaximumRangeLocationRisk = 501;
if(this.getRiskValue() >= unsupportedLocationRisk)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumLocationRisk)
return MINIMUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumLocationRisk, endMinimumRangeLocationRisk))
return MEDIUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumLocationRisk, endMaximumRangeLocationRisk))
return MAXIMUM_LOCATION_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
- Processor: To calculate the premium quote or to determine if it's is insurable.
public class UserPremiumBuilder<T extends InsuredProduct> {
private User user;
T product;
private UserPremiumBuilder(User user){
this.user = user;
}
public static <T extends InsuredProduct> UserPremiumBuilder<T> createProfile(User user){
UserPremiumBuilder<T> builder = new UserPremiumBuilder<T>(user);
return builder;
}
public UserPremiumBuilder <T> setProduct(T product) {
this.product = product;
return this;
}
public BigDecimal calculateSingleProductPremiumForUser() {
BigDecimal userRiskSurcharge = user.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(userRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
this.product.setRiskValue(this.user.getRiskValue());
BigDecimal productRiskSurcharge =this.product.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(productRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
if(Risk.getDefaultRiskSurcharge().compareTo(productRiskSurcharge)==0)
return this.product.getSubTotalPremium();
BigDecimal totalPremium = this.product.getSubTotalPremium().multiply(this.product.getRiskSurcharge()).multiply(user.getRiskSurcharge());
return totalPremium;
}
}
- A sample unit test class:
public class UserPremiumBuilderBananaTest {
Banana banana;
@Before
public void initBanana()
{
banana = new Banana(1, new BigDecimal(10));
}
@Test
public void testUnInsurableBananaRiskSurchargeWithUserRiskValueLargerThan200() {
User user = initUser(10);
user.setRiskValue(201);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(4);
BigDecimal totalPremium = createProfile(user).setProduct(banana).calculateSingleProductPremiumForUser();
assertEquals(Risk.getUnIdentifiedRiskSurcharge(), totalPremium);
}
@Test
public void testInsurableBananaRiskSurchargeWithUserRiskNotGreaterThan200() {
User user = initUser(10);
user.setRiskValue(200);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(3);
UserPremiumBuilder<Banana> builder = createProfile(user);
BigDecimal totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
BigDecimal productPremium = banana.getSubTotalPremium().setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
user.setRiskValue(199);
totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
}
private static UserPremiumBuilder<Banana> createProfile(User user)
{
return UserPremiumBuilder.createProfile(user);
}
private User initUser(int addressRiskValue)
{
Address address = new Address(1);
address.setRiskValue(addressRiskValue);
User user = new User(1, address);
return user;
}
}
java
New contributor
At a first glance, try to avoid instantiating BigDecimals when you can reuse existing instances. Thus, instead ofnew BigDecimal(0)
useBigDecimal.ZERO
. Similar instances exists forONE
andTEN
as well. Also, don't use thedouble
constructor of BigDecimal, because double can be imprecise and your 3.0 could become 3.0000000001. Use eithernew BigDecimal("3.0")
orBigDecimal.valueOf(3.0)
.
– Tom
12 hours ago
@Tom: Thank you, definitely very useful advice! If you could also shed some light on the interviewer's feedback to my code: "deep use of mutation and a not that well thought up internal API.", I really appreciate that!
– Anna
11 hours ago
I'm sorry, I don't have the time for further inspections of the code, but I'm sure someone else will gladly help you.
– Tom
11 hours ago
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I was failed at coding challenge for my interview with the following reasons given by the interviewer: deep use of mutation and a not that well thought up internal API.
I understand that my code and design have so many flaws and I genuinely want to get your opinion so I could improve my code.
The challenge is about asking me to build a quote processor to calculate a premium for different products, based on different rule sets.
Since the requirements are very lengthy, I try to summarize it below:
Data model
- A user (with an id, an address, and a risk value)
- An address (with an id and a location risk value)
- A product (with an id and a price value)
(Risk values are in our patented Universal Risk Value Scale [tm])
For products we have modelled in our system the following types:
- Houses (with address and size in square meters)
- Bananas (with number of black spots)
- Bicycles (with number of gears)
Asides from above, the premium quote would need to take in rules, base surcharge, universal risk value for each product and each user to quote a premium for user.
Rules
We want to build a quote processor that will receive a user and a set of products, and return whether we reject the user or not, and if not, for how much premium will we insure the products in euros per year.
To ensure this, we have a set of rules to follow.
Each product will have a base premium value, that multiplied by the product value will give a subtotal for the product's premium. To this subtotal, we must add a surcharge that depends on the product type and maybe on other rules. Each surcharge is multiplied to the base value.
Then, for all the products, if for one the rules say that it is un-insurable, then the final result given is that we won't offer an insurance. If no product is un-insurable, then we add all the premiums and that is the quote we return to the user.
Below are my classes, I am putting here one or two model classes just to present my design.
It is my first time using SO so I do not know how to put code in a good way yet, please understand.
- Interfaces:
public interface Product {
BigDecimal getProductValue();
BigDecimal getBasePremium();
BigDecimal getSubTotalPremium();
}
public interface Risk {
void setRiskValue(int riskValue);
BigDecimal getRiskSurcharge();
static BigDecimal getUnIdentifiedRiskSurcharge()
{
return new BigDecimal(-1);
}
static BigDecimal getDefaultRiskSurcharge()
{
return new BigDecimal(0);
}
static boolean isWithinRange(int riskValue, int minValue, int maxValue)
{
return riskValue >= minValue && riskValue <= maxValue;
}
}
- Model classes:
- Base class InsuredProduct implements above interfaces.
public abstract class InsuredProduct implements Product, Risk {
private int id;
private BigDecimal productValue;
private int riskValue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public InsuredProduct(int id, BigDecimal productValue)
{
this.id = id;
this.productValue =productValue;
}
public BigDecimal getProductValue() {
return productValue;
}
public void setProductValue(BigDecimal productValue) {
this.productValue = productValue;
}
@Override
public BigDecimal getSubTotalPremium()
{
return getProductValue().multiply(getBasePremium());
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
public int getRiskValue() {
return this.riskValue;
}
}
- Then Banana class as insured product extends from base class:
public class Banana extends InsuredProduct {
private static BigDecimal BASE_PREMIUM = new BigDecimal(1.15);
private int noOfBlackSpots;
private int userRiskValue;
public Banana(int id, BigDecimal productValue) {
super(id, productValue);
}
public int getNoOfBlackSpots() {
return noOfBlackSpots;
}
public void setNoOfBlackSpots(int noOfBlackSpots) {
this.noOfBlackSpots = noOfBlackSpots;
}
@Override
public BigDecimal getBasePremium() {
return BASE_PREMIUM;
}
@Override
public BigDecimal getRiskSurcharge() {
if(this.userRiskValue > 200)
return Risk.getUnIdentifiedRiskSurcharge();
final int minAcceptableBlackSpots = 3;
final int maxAcceptableBlackSpots = 12;
if(Risk.isWithinRange(this.noOfBlackSpots, minAcceptableBlackSpots, maxAcceptableBlackSpots))
return Risk.getDefaultRiskSurcharge();
return Risk.getUnIdentifiedRiskSurcharge();
}
@Override
public void setRiskValue(int riskValue) {
this.userRiskValue = riskValue;
}
}
- A User class (with Address) as an insured person. User's address is also part of risk surcharge to determine the quote calculation.
public class User implements Risk {
private static final BigDecimal MAXIMUM_USER_RISK_SURCHARGE = new BigDecimal(3.0);
private static final BigDecimal MEDIUM_USER_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_USER_RISK_SURCHARGE = new BigDecimal(0.3);
private int id;
private Address address;
private int riskValue;
public User(int id, Address address)
{
this.setId(id);
this.setAddress(address);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getRiskValue() {
return riskValue;
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedRiskValue = 501;
final int startMinimumRiskValue = 20;
final int endMinimumRangeRiskValue = 200;
final int startMaximumRiskValue = 201;
final int endMaximumRangeRiskValue = 500;
if(this.getRiskValue() >= unsupportedRiskValue)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumRiskValue)
return MINIMUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumRiskValue, endMinimumRangeRiskValue))
return MEDIUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumRiskValue, endMaximumRangeRiskValue))
return MAXIMUM_USER_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
public class Address implements Risk{
private static final BigDecimal MAXIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(2.5);
private static final BigDecimal MEDIUM_LOCATION_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(0.7);
private int id;
private int locationRisk;
public Address(int id)
{
this.id = id;
}
public int getRiskValue() {
return locationRisk;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public void setRiskValue(int riskValue) {
this.locationRisk = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedLocationRisk = 502;
final int startMinimumLocationRisk = 100;
final int endMinimumRangeLocationRisk = 299;
final int startMaximumLocationRisk = 300;
final int endMaximumRangeLocationRisk = 501;
if(this.getRiskValue() >= unsupportedLocationRisk)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumLocationRisk)
return MINIMUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumLocationRisk, endMinimumRangeLocationRisk))
return MEDIUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumLocationRisk, endMaximumRangeLocationRisk))
return MAXIMUM_LOCATION_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
- Processor: To calculate the premium quote or to determine if it's is insurable.
public class UserPremiumBuilder<T extends InsuredProduct> {
private User user;
T product;
private UserPremiumBuilder(User user){
this.user = user;
}
public static <T extends InsuredProduct> UserPremiumBuilder<T> createProfile(User user){
UserPremiumBuilder<T> builder = new UserPremiumBuilder<T>(user);
return builder;
}
public UserPremiumBuilder <T> setProduct(T product) {
this.product = product;
return this;
}
public BigDecimal calculateSingleProductPremiumForUser() {
BigDecimal userRiskSurcharge = user.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(userRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
this.product.setRiskValue(this.user.getRiskValue());
BigDecimal productRiskSurcharge =this.product.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(productRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
if(Risk.getDefaultRiskSurcharge().compareTo(productRiskSurcharge)==0)
return this.product.getSubTotalPremium();
BigDecimal totalPremium = this.product.getSubTotalPremium().multiply(this.product.getRiskSurcharge()).multiply(user.getRiskSurcharge());
return totalPremium;
}
}
- A sample unit test class:
public class UserPremiumBuilderBananaTest {
Banana banana;
@Before
public void initBanana()
{
banana = new Banana(1, new BigDecimal(10));
}
@Test
public void testUnInsurableBananaRiskSurchargeWithUserRiskValueLargerThan200() {
User user = initUser(10);
user.setRiskValue(201);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(4);
BigDecimal totalPremium = createProfile(user).setProduct(banana).calculateSingleProductPremiumForUser();
assertEquals(Risk.getUnIdentifiedRiskSurcharge(), totalPremium);
}
@Test
public void testInsurableBananaRiskSurchargeWithUserRiskNotGreaterThan200() {
User user = initUser(10);
user.setRiskValue(200);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(3);
UserPremiumBuilder<Banana> builder = createProfile(user);
BigDecimal totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
BigDecimal productPremium = banana.getSubTotalPremium().setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
user.setRiskValue(199);
totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
}
private static UserPremiumBuilder<Banana> createProfile(User user)
{
return UserPremiumBuilder.createProfile(user);
}
private User initUser(int addressRiskValue)
{
Address address = new Address(1);
address.setRiskValue(addressRiskValue);
User user = new User(1, address);
return user;
}
}
java
New contributor
I was failed at coding challenge for my interview with the following reasons given by the interviewer: deep use of mutation and a not that well thought up internal API.
I understand that my code and design have so many flaws and I genuinely want to get your opinion so I could improve my code.
The challenge is about asking me to build a quote processor to calculate a premium for different products, based on different rule sets.
Since the requirements are very lengthy, I try to summarize it below:
Data model
- A user (with an id, an address, and a risk value)
- An address (with an id and a location risk value)
- A product (with an id and a price value)
(Risk values are in our patented Universal Risk Value Scale [tm])
For products we have modelled in our system the following types:
- Houses (with address and size in square meters)
- Bananas (with number of black spots)
- Bicycles (with number of gears)
Asides from above, the premium quote would need to take in rules, base surcharge, universal risk value for each product and each user to quote a premium for user.
Rules
We want to build a quote processor that will receive a user and a set of products, and return whether we reject the user or not, and if not, for how much premium will we insure the products in euros per year.
To ensure this, we have a set of rules to follow.
Each product will have a base premium value, that multiplied by the product value will give a subtotal for the product's premium. To this subtotal, we must add a surcharge that depends on the product type and maybe on other rules. Each surcharge is multiplied to the base value.
Then, for all the products, if for one the rules say that it is un-insurable, then the final result given is that we won't offer an insurance. If no product is un-insurable, then we add all the premiums and that is the quote we return to the user.
Below are my classes, I am putting here one or two model classes just to present my design.
It is my first time using SO so I do not know how to put code in a good way yet, please understand.
- Interfaces:
public interface Product {
BigDecimal getProductValue();
BigDecimal getBasePremium();
BigDecimal getSubTotalPremium();
}
public interface Risk {
void setRiskValue(int riskValue);
BigDecimal getRiskSurcharge();
static BigDecimal getUnIdentifiedRiskSurcharge()
{
return new BigDecimal(-1);
}
static BigDecimal getDefaultRiskSurcharge()
{
return new BigDecimal(0);
}
static boolean isWithinRange(int riskValue, int minValue, int maxValue)
{
return riskValue >= minValue && riskValue <= maxValue;
}
}
- Model classes:
- Base class InsuredProduct implements above interfaces.
public abstract class InsuredProduct implements Product, Risk {
private int id;
private BigDecimal productValue;
private int riskValue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public InsuredProduct(int id, BigDecimal productValue)
{
this.id = id;
this.productValue =productValue;
}
public BigDecimal getProductValue() {
return productValue;
}
public void setProductValue(BigDecimal productValue) {
this.productValue = productValue;
}
@Override
public BigDecimal getSubTotalPremium()
{
return getProductValue().multiply(getBasePremium());
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
public int getRiskValue() {
return this.riskValue;
}
}
- Then Banana class as insured product extends from base class:
public class Banana extends InsuredProduct {
private static BigDecimal BASE_PREMIUM = new BigDecimal(1.15);
private int noOfBlackSpots;
private int userRiskValue;
public Banana(int id, BigDecimal productValue) {
super(id, productValue);
}
public int getNoOfBlackSpots() {
return noOfBlackSpots;
}
public void setNoOfBlackSpots(int noOfBlackSpots) {
this.noOfBlackSpots = noOfBlackSpots;
}
@Override
public BigDecimal getBasePremium() {
return BASE_PREMIUM;
}
@Override
public BigDecimal getRiskSurcharge() {
if(this.userRiskValue > 200)
return Risk.getUnIdentifiedRiskSurcharge();
final int minAcceptableBlackSpots = 3;
final int maxAcceptableBlackSpots = 12;
if(Risk.isWithinRange(this.noOfBlackSpots, minAcceptableBlackSpots, maxAcceptableBlackSpots))
return Risk.getDefaultRiskSurcharge();
return Risk.getUnIdentifiedRiskSurcharge();
}
@Override
public void setRiskValue(int riskValue) {
this.userRiskValue = riskValue;
}
}
- A User class (with Address) as an insured person. User's address is also part of risk surcharge to determine the quote calculation.
public class User implements Risk {
private static final BigDecimal MAXIMUM_USER_RISK_SURCHARGE = new BigDecimal(3.0);
private static final BigDecimal MEDIUM_USER_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_USER_RISK_SURCHARGE = new BigDecimal(0.3);
private int id;
private Address address;
private int riskValue;
public User(int id, Address address)
{
this.setId(id);
this.setAddress(address);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getRiskValue() {
return riskValue;
}
@Override
public void setRiskValue(int riskValue) {
this.riskValue = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedRiskValue = 501;
final int startMinimumRiskValue = 20;
final int endMinimumRangeRiskValue = 200;
final int startMaximumRiskValue = 201;
final int endMaximumRangeRiskValue = 500;
if(this.getRiskValue() >= unsupportedRiskValue)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumRiskValue)
return MINIMUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumRiskValue, endMinimumRangeRiskValue))
return MEDIUM_USER_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumRiskValue, endMaximumRangeRiskValue))
return MAXIMUM_USER_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
public class Address implements Risk{
private static final BigDecimal MAXIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(2.5);
private static final BigDecimal MEDIUM_LOCATION_RISK_SURCHARGE = new BigDecimal(1.0);
private static final BigDecimal MINIMUM_LOCATION_RISK_SURCHARGE = new BigDecimal(0.7);
private int id;
private int locationRisk;
public Address(int id)
{
this.id = id;
}
public int getRiskValue() {
return locationRisk;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public void setRiskValue(int riskValue) {
this.locationRisk = riskValue;
}
@Override
public BigDecimal getRiskSurcharge() {
final int unsupportedLocationRisk = 502;
final int startMinimumLocationRisk = 100;
final int endMinimumRangeLocationRisk = 299;
final int startMaximumLocationRisk = 300;
final int endMaximumRangeLocationRisk = 501;
if(this.getRiskValue() >= unsupportedLocationRisk)
return Risk.getUnIdentifiedRiskSurcharge();
if(this.getRiskValue() < startMinimumLocationRisk)
return MINIMUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMinimumLocationRisk, endMinimumRangeLocationRisk))
return MEDIUM_LOCATION_RISK_SURCHARGE;
if(Risk.isWithinRange(this.getRiskValue(), startMaximumLocationRisk, endMaximumRangeLocationRisk))
return MAXIMUM_LOCATION_RISK_SURCHARGE;
return Risk.getDefaultRiskSurcharge();
}
}
- Processor: To calculate the premium quote or to determine if it's is insurable.
public class UserPremiumBuilder<T extends InsuredProduct> {
private User user;
T product;
private UserPremiumBuilder(User user){
this.user = user;
}
public static <T extends InsuredProduct> UserPremiumBuilder<T> createProfile(User user){
UserPremiumBuilder<T> builder = new UserPremiumBuilder<T>(user);
return builder;
}
public UserPremiumBuilder <T> setProduct(T product) {
this.product = product;
return this;
}
public BigDecimal calculateSingleProductPremiumForUser() {
BigDecimal userRiskSurcharge = user.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(userRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
this.product.setRiskValue(this.user.getRiskValue());
BigDecimal productRiskSurcharge =this.product.getRiskSurcharge();
if(Risk.getUnIdentifiedRiskSurcharge().compareTo(productRiskSurcharge)==0)
return Risk.getUnIdentifiedRiskSurcharge();
if(Risk.getDefaultRiskSurcharge().compareTo(productRiskSurcharge)==0)
return this.product.getSubTotalPremium();
BigDecimal totalPremium = this.product.getSubTotalPremium().multiply(this.product.getRiskSurcharge()).multiply(user.getRiskSurcharge());
return totalPremium;
}
}
- A sample unit test class:
public class UserPremiumBuilderBananaTest {
Banana banana;
@Before
public void initBanana()
{
banana = new Banana(1, new BigDecimal(10));
}
@Test
public void testUnInsurableBananaRiskSurchargeWithUserRiskValueLargerThan200() {
User user = initUser(10);
user.setRiskValue(201);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(4);
BigDecimal totalPremium = createProfile(user).setProduct(banana).calculateSingleProductPremiumForUser();
assertEquals(Risk.getUnIdentifiedRiskSurcharge(), totalPremium);
}
@Test
public void testInsurableBananaRiskSurchargeWithUserRiskNotGreaterThan200() {
User user = initUser(10);
user.setRiskValue(200);
banana.setRiskValue(user.getRiskValue());
banana.setNoOfBlackSpots(3);
UserPremiumBuilder<Banana> builder = createProfile(user);
BigDecimal totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
BigDecimal productPremium = banana.getSubTotalPremium().setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
user.setRiskValue(199);
totalPremium = builder.setProduct(banana).calculateSingleProductPremiumForUser();
totalPremium = totalPremium.setScale(2, BigDecimal.ROUND_HALF_EVEN);
assertEquals(productPremium, totalPremium);
}
private static UserPremiumBuilder<Banana> createProfile(User user)
{
return UserPremiumBuilder.createProfile(user);
}
private User initUser(int addressRiskValue)
{
Address address = new Address(1);
address.setRiskValue(addressRiskValue);
User user = new User(1, address);
return user;
}
}
java
java
New contributor
New contributor
New contributor
asked 14 hours ago
Anna
61
61
New contributor
New contributor
At a first glance, try to avoid instantiating BigDecimals when you can reuse existing instances. Thus, instead ofnew BigDecimal(0)
useBigDecimal.ZERO
. Similar instances exists forONE
andTEN
as well. Also, don't use thedouble
constructor of BigDecimal, because double can be imprecise and your 3.0 could become 3.0000000001. Use eithernew BigDecimal("3.0")
orBigDecimal.valueOf(3.0)
.
– Tom
12 hours ago
@Tom: Thank you, definitely very useful advice! If you could also shed some light on the interviewer's feedback to my code: "deep use of mutation and a not that well thought up internal API.", I really appreciate that!
– Anna
11 hours ago
I'm sorry, I don't have the time for further inspections of the code, but I'm sure someone else will gladly help you.
– Tom
11 hours ago
add a comment |
At a first glance, try to avoid instantiating BigDecimals when you can reuse existing instances. Thus, instead ofnew BigDecimal(0)
useBigDecimal.ZERO
. Similar instances exists forONE
andTEN
as well. Also, don't use thedouble
constructor of BigDecimal, because double can be imprecise and your 3.0 could become 3.0000000001. Use eithernew BigDecimal("3.0")
orBigDecimal.valueOf(3.0)
.
– Tom
12 hours ago
@Tom: Thank you, definitely very useful advice! If you could also shed some light on the interviewer's feedback to my code: "deep use of mutation and a not that well thought up internal API.", I really appreciate that!
– Anna
11 hours ago
I'm sorry, I don't have the time for further inspections of the code, but I'm sure someone else will gladly help you.
– Tom
11 hours ago
At a first glance, try to avoid instantiating BigDecimals when you can reuse existing instances. Thus, instead of
new BigDecimal(0)
use BigDecimal.ZERO
. Similar instances exists for ONE
and TEN
as well. Also, don't use the double
constructor of BigDecimal, because double can be imprecise and your 3.0 could become 3.0000000001. Use either new BigDecimal("3.0")
or BigDecimal.valueOf(3.0)
.– Tom
12 hours ago
At a first glance, try to avoid instantiating BigDecimals when you can reuse existing instances. Thus, instead of
new BigDecimal(0)
use BigDecimal.ZERO
. Similar instances exists for ONE
and TEN
as well. Also, don't use the double
constructor of BigDecimal, because double can be imprecise and your 3.0 could become 3.0000000001. Use either new BigDecimal("3.0")
or BigDecimal.valueOf(3.0)
.– Tom
12 hours ago
@Tom: Thank you, definitely very useful advice! If you could also shed some light on the interviewer's feedback to my code: "deep use of mutation and a not that well thought up internal API.", I really appreciate that!
– Anna
11 hours ago
@Tom: Thank you, definitely very useful advice! If you could also shed some light on the interviewer's feedback to my code: "deep use of mutation and a not that well thought up internal API.", I really appreciate that!
– Anna
11 hours ago
I'm sorry, I don't have the time for further inspections of the code, but I'm sure someone else will gladly help you.
– Tom
11 hours ago
I'm sorry, I don't have the time for further inspections of the code, but I'm sure someone else will gladly help you.
– Tom
11 hours ago
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Anna is a new contributor. Be nice, and check out our Code of Conduct.
Anna is a new contributor. Be nice, and check out our Code of Conduct.
Anna is a new contributor. Be nice, and check out our Code of Conduct.
Anna is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209439%2finsurance-premium-quote-challenge%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
At a first glance, try to avoid instantiating BigDecimals when you can reuse existing instances. Thus, instead of
new BigDecimal(0)
useBigDecimal.ZERO
. Similar instances exists forONE
andTEN
as well. Also, don't use thedouble
constructor of BigDecimal, because double can be imprecise and your 3.0 could become 3.0000000001. Use eithernew BigDecimal("3.0")
orBigDecimal.valueOf(3.0)
.– Tom
12 hours ago
@Tom: Thank you, definitely very useful advice! If you could also shed some light on the interviewer's feedback to my code: "deep use of mutation and a not that well thought up internal API.", I really appreciate that!
– Anna
11 hours ago
I'm sorry, I don't have the time for further inspections of the code, but I'm sure someone else will gladly help you.
– Tom
11 hours ago