Created
August 20, 2020 21:21
-
-
Save forax/80da75b7e31c1cacaf029df928ab78e7 to your computer and use it in GitHub Desktop.
Henry refacting: sealed interface + records
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2019-2020 the original author or authors. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package pro.tremblay.core; | |
import javax.annotation.Nonnull; | |
import java.math.BigDecimal; | |
import java.math.RoundingMode; | |
import java.util.Objects; | |
import static pro.tremblay.core.Percentage.pct; | |
public record Amount(BigDecimal value) implements Numeric<Amount> { | |
private static final Amount ZERO = new Amount(BigDecimal.ZERO); | |
public static Amount zero() { | |
return ZERO; | |
} | |
public static Amount amnt(double value) { | |
return new Amount(BigDecimal.valueOf(value)); | |
} | |
public static Amount amnt(long value) { | |
return new Amount(BigDecimal.valueOf(value)); | |
} | |
public static Amount amnt(@Nonnull BigDecimal value) { | |
return new Amount(Objects.requireNonNull(value)); | |
} | |
public static Amount amnt(@Nonnull String value) { | |
return new Amount(new BigDecimal(Objects.requireNonNull(value))); | |
} | |
public Amount { | |
// To simplify, we consider everything is in the same currency so all amounts have a precision of 2 | |
value = value.setScale(2, RoundingMode.HALF_UP); | |
} | |
@Override | |
public String toString() { | |
return value.toPlainString() + "$"; | |
} | |
@Override | |
public Amount fromValue(@Nonnull BigDecimal newValue) { | |
return new Amount(newValue); | |
} | |
public Amount multiply(Quantity quantity) { | |
return new Amount(value.multiply(quantity.value())); | |
} | |
public Percentage asRatioOf(Amount initialValue) { | |
return pct(value.subtract(initialValue.value) | |
.divide(initialValue.value, 10, RoundingMode.HALF_UP) | |
.multiply(Percentage.hundred().value())); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2019-2020 the original author or authors. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package pro.tremblay.core; | |
import javax.annotation.Nonnull; | |
import javax.annotation.concurrent.ThreadSafe; | |
import java.math.BigDecimal; | |
import java.math.RoundingMode; | |
import java.util.Objects; | |
@ThreadSafe | |
public sealed interface Numeric<T extends Numeric<T>> | |
permits Amount, Percentage, Quantity { | |
BigDecimal value(); | |
T fromValue(@Nonnull BigDecimal newValue); | |
default T add(@Nonnull T numeric) { | |
return fromValue(value().add(numeric.value())); | |
} | |
default T substract(@Nonnull T numeric) { | |
return fromValue(value().subtract(numeric.value())); | |
} | |
default boolean isZero() { | |
return value().signum() == 0; | |
} | |
default T negate() { | |
return fromValue(value().negate()); | |
} | |
/** | |
* Scale this numerator to another denominator. E.g. if this is "3" on "4" ("from" param) | |
* and we want to scale to "8" ("to" param), we expect 3 x 8 / 4 = 6 as a result. | |
* | |
* @param from denominator from which to start | |
* @param to denominator to go to | |
* @return the numerator scaling to another denominator | |
*/ | |
default T scale(int from, int to) { | |
return fromValue(value().multiply(BigDecimal.valueOf(to)) | |
.divide(BigDecimal.valueOf(from), 2, RoundingMode.HALF_UP)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2019-2020 the original author or authors. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package pro.tremblay.core; | |
import javax.annotation.Nonnull; | |
import javax.annotation.concurrent.ThreadSafe; | |
import java.math.BigDecimal; | |
import java.math.RoundingMode; | |
import java.util.Objects; | |
@ThreadSafe | |
public record Percentage(BigDecimal value) implements Numeric<Percentage> { | |
private static final Percentage HUNDRED = pct("100"); | |
private static final Percentage ZERO = pct("0"); | |
public static Percentage hundred() { | |
return HUNDRED; | |
} | |
public static Percentage zero() { | |
return ZERO; | |
} | |
public static Percentage pct(long value) { | |
return new Percentage(BigDecimal.valueOf(value)); | |
} | |
public static Percentage pct(@Nonnull String value) { | |
return new Percentage(new BigDecimal(Objects.requireNonNull(value))); | |
} | |
public static Percentage pct(@Nonnull BigDecimal value) { | |
return new Percentage(Objects.requireNonNull(value)); | |
} | |
public Percentage { | |
value = value.setScale(2, RoundingMode.HALF_UP); | |
} | |
@Override | |
public String toString() { | |
return value.toPlainString() + "%"; | |
} | |
@Override | |
public Percentage fromValue(@Nonnull BigDecimal newValue) { | |
return new Percentage(newValue); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2019-2020 the original author or authors. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package pro.tremblay.core; | |
import javax.annotation.Nonnull; | |
import javax.annotation.concurrent.ThreadSafe; | |
import java.math.BigDecimal; | |
import java.math.RoundingMode; | |
import java.util.Objects; | |
@ThreadSafe | |
public record Quantity(BigDecimal value) implements Numeric<Quantity> { | |
private static final Quantity ZERO = new Quantity(BigDecimal.ZERO); | |
private static final Quantity TEN = qty(10); | |
public static Quantity zero() { | |
return ZERO; | |
} | |
public static Quantity ten() { | |
return TEN; | |
} | |
public static Quantity qty(long value) { | |
return new Quantity(BigDecimal.valueOf(value)); | |
} | |
public static Quantity qty(@Nonnull BigDecimal value) { | |
return new Quantity(Objects.requireNonNull(value)); | |
} | |
public Quantity { | |
// To simplify, we consider everything is in the same currency so all amounts have a precision of 2 | |
value = value.setScale(0, RoundingMode.HALF_UP); | |
} | |
@Override | |
public String toString() { | |
return value.toPlainString(); | |
} | |
@Override | |
public Quantity fromValue(@Nonnull BigDecimal newValue) { | |
return new Quantity(newValue); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment