[TDD Chapter3] ν μ€νΈ μ½λ μμ± μμ
π ν μ€νΈ μ½λ μμ± μμ
1. μ¬μ΄ κ²½μ°μμ μ΄λ €μ΄ κ²½μ°λ‘ μ§ν
2. μμΈμ μΈ κ²½μ°μμ μ μμ μΌλ‘ μ§ν
κ·Έλ λ€λ©΄ μ΄λ €μ΄ κ²½μ°λ‘ μμ±νλ©΄ μλλ μ΄μ λ λκΉ?
π± μ΄λ°μ 볡μ‘ν ν μ€νΈλΆν° μμνλ©΄ μλλ μ΄μ
μ΄λ°μ 볡μ‘νκ² μμνλ©΄ ν λ²μ ꡬνν΄μΌ νλ μ½λκ° λ§μμ§λ€.
if λ¬Έμ΄ λμ΄λ μλ μκ³ νλ²μ λ§μ μ½λλ₯Ό λ§λ€λ€λ³΄λ©΄ λλ λͺ¨λ₯΄κ² λ²κ·Έλ₯Ό λ§λ€κ³ λμ€μ λ²κ·Έλ₯Ό μ‘κΈ° μν΄ λ§μ μκ°μ νλΉνκ² λλ€.
π± ꡬννκΈ° μ¬μ΄ ν μ€νΈλΆν° μμνκΈ°
λ³΄ν΅ μλΆ λ΄μ ꡬνμ μλ£νκ³ ν΅κ³Όν μ μλ ν μ€νΈ ꡬνμ μ νν΄μΌ νλ€.
Chapter 2μμ νλ μνΈ κ°λ μΈ‘μ μμμλ λ€μ μ€ νλκ° μ¬μΈ κ²μ΄λ€.
1. λͺ¨λ 쑰건μμ μΆ©μ‘±νλ κ²½μ°
2. λͺ¨λ 쑰건μμ μΆ©μ‘±νμ§ μλ κ²½μ°
1λ²μ κ²½μ° λͺ¨λ 쑰건μ μΆ©μ‘±νμ§ μλ κ²½μ°λΌλ©΄ λ¨μν WEAKλ₯Ό return νλ©΄ λκ³ , 2λ²μ κ²½μ° λͺ¨λ 쑰건μ μΆ©μ‘±νλ κ²½μ°μλ λ¨μν STRONGμ return νλ©΄ λλ€.
1λ²μ μ ννκ³ ν μ€νΈ μ½λ μμ±μ μ΄μ΄λκ°λ€κ³ κ°μ νμ.
κ·ΈλΌ λ€μκ³Ό κ°μ κ²½μ°μ μκ° μμ κ²μ΄λ€.
1. λͺ¨λ κ·μΉμ μΆ©μ‘±νμ§ μλ κ²½μ°
2. ν κ·μΉλ§ μΆ©μ‘±νλ κ²½μ°
3. λ κ·μΉμ μΆ©μ‘±νλ κ²½μ°
1λ²: λͺ¨λ κ·μΉμ μΆ©μ‘±νλ κ²½μ°λ‘ μ½λλ₯Ό μμ±νκΈ° λλ¬Έμ μμΈμ²λ¦¬κ° λ§μμ Έ λ²κ·Έ μμ±
2λ²: ν κ·μΉμ μΆ©μ‘±νλμ§ μ¬λΆλ₯Ό 체ν¬
3λ²: ν κ·μΉμ μΆ©μ‘±νλμ§ κ²μ¬νκ³ , μΆ©μ‘±νμ§ μλ κ·μΉμ΄ μκΈ° λλ¬Έμ λ λ€ νμΈ ν NORMALμ return
λ°λΌμ, 2λ²κ³Ό 3λ² μ¬μ΄μμ μ ν
κ·μΉ μ€μμλ
1. κΈμ μ μΆ©μ‘±
2. λλ¬Έμ μ¬λΆ κ²μ¬
3. μ«μ ν¬ν¨ μ¬λΆ κ²μ¬
κ° μμ κ²μ΄κ³ κ·Έ μ€μμ μ¬μΈ κ·μΉμ μ ννμ¬ μ½λλ₯Ό μ€κ³νλ€.
π± μμΈ μν©μ λ¨Όμ ν μ€νΈν΄μΌ νλ μ΄μ
μμΈ μ¬νμ μ ν κ³ λ €νμ§ μμ μ½λμμ μμΈ μν©μ λ°μνλ €λ©΄ μ½λμ ꡬ쑰λ₯Ό λ€μ§κ±°λ μ€κ°μ μμΈ μν©μ μ²λ¦¬νκΈ° μν΄ μ‘°κ±΄λ¬Έμ μ€λ³΅ν΄μ μΆκ°λ₯Ό ν΄μΌνλ€.
μ΄λ°μ μμΈ μν©μ ν μ€νΈνλ©΄ μμ κ°μ μν©μ΄ λ°μν μΌμ΄ μ€μ΄λ λ€.
μλ₯Ό λ€λ©΄ 2 μ°¨μμμ μ§νν μ½λμμ κ°μ΄ μμ λ λ°μνλ NPEλ₯Ό μ¬μ μ λ§μ μ μλ€λ μ μ΄λ€.
NPEλ μλ¬ λ°μλΏλ§ μλλΌ νλ‘μΈμ€λ₯Ό μ£½μΌ μλ μκΈ° λλ¬Έμ΄λ€.
π± μκΈ μ‘°μ
μ²μμ ν μ€νΈ μ½λ μμ± μ, μ΄λ €μ΄ κ² μ€ νλκ° ν λ²μ μΌλ§λ§νΌ μ½λλ₯Ό μμ±νλ κ²μΈκ°μ΄λ€.
TDD λ₯Ό μ²μ μ ν λμλ λ€μ λ¨κ³λ‘ κ±°μ³μ μ°μ΅νμ!
1. μ ν΄μ§ κ°μ return
2. κ° λΉκ΅λ₯Ό μ΄μ©ν΄μ μ ν΄μ§ κ°μ return
3. λ€μν ν μ€νΈλ₯Ό μΆκ°νλ©΄μ ꡬνμ μΌλ°ν
public class PasswordStrengthMeterTest {
@Test
void meetsOtherCreteria_except_for_length_Then_Normal(){
testdriven.chap03.PasswordStrengthMeter meter = new PasswordStrengthMeter();
PasswordStrength result = meter.meter("ab12!@A");
assertEquals(PasswordStrength.NORMAL, result);
PasswordStrength result2 = meter.meter("Ab12!c");
assertEquals(PasswordStrength.NORMAL, result2);
}
}
////////////////////////
public PasswordStrength meter(String s){
// if("ab12!@A".equals(s) || "Ab12!c".equals(s)) return PasswordStrength.NORMAL;
if(s.length()<8) return PasswordStrength.NORMAL;
else return PasswordStrength.STRONG;
}
π± μ§μμ μΈ λ¦¬ν©ν λ§
ν μ€νΈκ° ν΅κ³Όλ νμλ 리ν©ν λ§μ μ§ννλ€.
λ§€λ² λ¦¬νν λ§μ μ§ννλ κ²μ μλλ©° μ λΉν νλ³΄κ° λ³΄μ΄λ©΄ 리ν©ν λ§ μ§ν (ex. μ½λ μ€λ³΅)
[리νν λ§ μ₯μ ]
1. μ§μμ 리ν©ν λ§μ μ½λ κ°λ μ±μ΄ λμμ§
2. κ°λ μ±μ΄ λμμ§λ©΄ κ°λ°μλ λΉ λ₯΄κ² μ½λ λΆμ κ°λ₯
3. μμ μμ²μ΄ μλ€λ©΄ λ³κ²½ μ½λλ₯Ό λΉ λ₯΄κ² μ°Ύμ μ μμ
π’ κ°μ₯ μ€μ: λμ νλ μ½λλ₯Ό λ§λλ κ²
π’ SW μμ‘΄ κΈ°κ°μ΄ κΈΈμ΄μ§μλ‘ μ§μμ μΌλ‘ μ½λ λ³κ²½ νμ
π’ 리ν©ν λ§: μ½λ λ³κ²½μ μν΄ λ³κ²½νκΈ° μ¬μ΄ κ΅¬μ‘°λ‘ λ³κ²½
- μμ 리ν©ν λ§μ λ°λ‘ λ³κ²½ (λ³μ μ΄λ¦ λ³κ²½, μμλ₯Ό λ³μλ‘ λ³κ²½)
- 맀μλ μΆμΆκ³Ό κ°μ ꡬ쑰μ μν₯ μ£Όλ κ²μ νλ¦μ΄ λμ λ€μ΄μ€κΈ° μμν λ!
π ν μ€νΈ μ½λ μμ± μμ μ°μ΅
λ§€λ¬ λΉμ©μ μ§λΆν΄μΌ μ¬μ©ν μ μλ μ λ£ μλΉμ€κ° μκ³ κ·μΉμ λ€μκ³Ό κ°λ€.
1. μλΉμ€λ₯Ό μ¬μ©νλ €λ©° λ§€λ¬ 1λ§μμ μ λΆλ‘ λ©λΆ, λ©λΆμΌ κΈ°μ€ νλ¬ λ€κ° μλΉμ€ λ§λ£μΌ
2. 2κ°μ μ΄μ μκΈμ λ©λΆ κ°λ₯
3. 10λ§μ λ©λΆ μ, μλΉμ€ 1λ μ 곡
μ΄λ€ κ²λΆν° ν μ€νΈλ₯Ό μ§ννλ κ²μ΄ μ’μκΉ? μ¦, μ΄λ€ κ²μ΄ κ°μ₯ μ¬μ΄ κ²μΌκΉ?
π± μ¬μ΄ κ²λΆν° ν μ€νΈ
ν μ€νΈλ₯Ό μΆκ°ν λλ ꡬννκΈ° μ½κ±°λ, μμΈ μ¬νμ λ¨Όμ ν μ€νΈ ν΄μΌνλ€λ μ μ λ€μ μκΈ°μν€μ!
μ μν©μμ κ°μ₯ μ¬μ΄ μ μ 1λ²μΌ κ²μ΄λ€.
@Test
void λ§μ_λ©λΆνλ©΄_νλ¬_λ€κ°_λ§λ£μΌμ΄_λ¨(){
LocalDate billingDate = LocalDate.of(2019, 3, 1);
int payAmount = 10_000;
ExpiryDateCalculator cal = new ExpiryDateCalculator();
LocalDate expiryDate = cal.calculateExpiryDate(billingDate, payAmount);
assertEquals(expiryDate, LocalDate.of(2019, 4, 1));
}
////
public LocalDate calculateExpiryDate(LocalDate billingDate, int payAmount){
return LocalDate.of(2019, 4, 1);
}
π± μλ₯Ό μΆκ°νλ©΄μ ꡬνμ μΌλ°ν
μμ μ½λλ νλμ λ μ§μλ§ λ§μΆ°μ§ μ½λμ΄κΈ° λλ¬Έμ λ€λ₯Έ μμμ λ μ§λ₯Ό μ ννμ¬ μΌλ°μ μΈ λ μ§μλ testκ° μ±κ³΅ν μ μλλ‘ μ½λλ‘ λ³κ²½μ νμλ€.
@Test
void λ§μ_λ©λΆνλ©΄_νλ¬_λ€κ°_λ§λ£μΌμ΄_λ¨(){
LocalDate billingDate = LocalDate.of(2019, 3, 1);
int payAmount = 10_000;
ExpiryDateCalculator cal = new ExpiryDateCalculator();
LocalDate expiryDate = cal.calculateExpiryDate(billingDate, payAmount);
assertEquals(expiryDate, LocalDate.of(2019, 4, 1));
LocalDate billingDate2 = LocalDate.of(2019, 5, 5);
int payAmount2 = 10_000;
ExpiryDateCalculator cal2 = new ExpiryDateCalculator();
LocalDate expiryDate2 = cal2.calculateExpiryDate(billingDate2, payAmount2);
assertEquals(expiryDate2, LocalDate.of(2019, 6, 5));
}
///
public LocalDate calculateExpiryDate(LocalDate billingDate, int payAmount){
return billingDate.plusMonths(1);
}
π± μ½λ μ 리: μ€λ³΅ μ κ±° & μμΈ μν© μ²λ¦¬
리ν©ν λ§μ μ§ννμ¬ μ€λ³΅λ μ½λλ₯Ό μ κ±°νλ€.
보ν΅μ μ€λ³΅μ μ κ±°νλ κ²μ΄ μ’μ§λ§, ν μ€νΈ μ½λμ μ€λ³΅ μ κ±°μμλ κ³ λ―Όμ΄ νμνλ€.
μλνλ©΄ κ° ν μ€νΈ λ©μλλ 무μμ ν μ€νΈνλμ§ λͺ ννκ² μ€λͺ μ΄ μμ΄μΌ νκΈ° λλ¬Έμ΄λ€.
-> μ€λ³΅μ μ κ±°ν΄λ³΄κ³ ν μ€νΈ μ½λκ° μ¬μ ν μμ μ μ€λͺ νλμ§ νμΈ νμ
ν λ¬ μ£ΌκΈ°λ‘ λ μ§λ₯Ό μΈλ©΄ μμΈ μν©μ΄ λ°μνλ€
3μ 1μΌκ³Ό 4μ 1μΌμ κ²½μ° λͺ¨λ 1μΌμ λ©λΆνλ©΄ λμ§λ§, λ§μΌμ λ©λΆνλ κ²½μ°
1μ 31μΌκ³Ό 2μ 28μΌμΈ κ²½μ°μ΄λ€. μ΄ κ²½μ°λ λͺ¨λ LocalDateμ ν¨μκ° μμμ κ³μ°ν΄μ€λ€κ³ νλ€.
@Test
void λ©λΆμΌκ³Ό_νλ¬_λ€_μΌμκ°_κ°μ§_μμ(){
assertExpiryDate(LocalDate.of(2019, 1, 31),
10_000, LocalDate.of(2019, 2, 28));
}
private void assertExpiryDate(LocalDate billingDate, int payAmount, LocalDate expectedExpiryDate) {
ExpiryDateCalculator cal = new ExpiryDateCalculator();
LocalDate expiryDate = cal.calculateExpiryDate(billingDate, payAmount);
assertEquals(expiryDate, expectedExpiryDate);
}
////
public LocalDate calculateExpiryDate(LocalDate billingDate, int payAmount){
return billingDate.plusMonths(1); // λ©μλκ° μμμ λ μ§ μ£ΌκΈ°λ₯Ό μ²λ¦¬ν΄μ€
}
π± λ€μ ν μ€νΈ μ ν: λ€μ μμΈ μν©
μ¬νκΉμ§λ νλ¬μ λ§μλ§ λ©λΆνλ μν©μ κ°μ νμ¬ ν μ€νΈ μ½λλ₯Ό μμ±νλ€. νμ§λ§, λλ¬ μ΄μμ μκΈμ νλ²μ λ©λΆνλ κ²½μ°λ μκΈ° λλ¬Έμ λλ¬μ λ©λΆνλ κ²½μ°μ μμΈ μν©μ μ΄ν΄λ³΄μ.
μ¬μ΄ μν©: λλ¬ μ΄μμ μκΈμ ν λ²μ λ©λΆνλ κ²½μ°
μμΈ μν: ν λ¬μ λ©λΆνλ κ²½μ°
νμ¬ ν λ¬μ λ©λΆνλ κ²½μ°μ ν μ€νΈ μ½λλ₯Ό μμ±νκΈ° λλ¬Έμ ν λ¬μ λ©λΆνλ κ²½μ°μ μμΈ μν© μ²λ¦¬νκ³ μ§ννλ κ²μ΄ μ’λ€.
μ΄λ, μμΈ μν©μ μ²λ¦¬νλ €λ©΄ 첫 λ©λΆμΌμ μμμΌ νλ€.
π± λ€μ ν μ€νΈλ₯Ό μΆκ°νκΈ° μ μ 리ν©ν λ§
λ§λ£μΌμ κ³μ°νλ λ° νμν κ°μ΄ λ€μκ³Ό κ°μ΄ λμ΄λ¬λ€.
calculateExpiryDate λ©μλ νλΌλ―Έν°λ‘ 첫 λ©λΆμΌ μΆκ°
첫 λ©λΆμΌ, λ©λΆμΌ, λ©λΆμ‘μ λ΄μ κ°μ²΄λ₯Ό calculateExpiryDate λ©μλμ μ λ¬
νμ¬ νλΌλ―Έν°λ‘ μ λ¬ν΄μΌνλ κ°μ μΈ κ°! -> 첫 λ©λΆμΌ, λ©λΆμΌ, λ©λΆμ‘
μ΄κΈ° λλ¬Έμ νλΌλ―Έν°κ° 3κ° μ΄μμ΄ λλ©΄ κ°μ²΄λ‘ μμ±ν΄μ ν λ²μ μ λ¬νλ κ²μ΄ μ’λ€ .
package testdriven.chap03;
import org.springframework.test.web.reactive.server.WebTestClient;
import java.time.LocalDate;
public class PayData {
private LocalDate billingDate;
private int payAmount;
private PayData(){}
public PayData(LocalDate billingDate, int payAmount){
this.billingDate = billingDate;
this.payAmount = payAmount;
}
public LocalDate getBillingDate(){
return billingDate;
}
public int getPayAmount(){
return payAmount;
}
public static Builder builder(){
return new Builder();
}
public static class Builder{
private PayData payData = new PayData();
public Builder billingDate(LocalDate billingDate){
payData.billingDate = billingDate;
return this;
}
public Builder payAmount(int payAmount){
payData.payAmount = payAmount;
return this;
}
public PayData build(){
return payData;
}
}
}
///
public LocalDate calculateExpiryDate(PayData payData){
return payData.getBillingDate().plusMonths(1);
}
}
///
@Test
void λ§μ_λ©λΆνλ©΄_νλ¬_λ€κ°_λ§λ£μΌμ΄_λ¨(){
assertExpiryDate(PayData.builder()
.billingDate(LocalDate.of(2019, 3, 1))
.payAmount(10_000)
.build(),
LocalDate.of(2019, 4, 1));
assertExpiryDate(PayData.builder()
.billingDate(LocalDate.of(2019, 1, 31))
.payAmount(10_000)
.build(),
LocalDate.of(2019, 2, 28));
}
κ°λ¨νκ² λΉλ ν¨ν΄μ μ μ©νλ©΄ μμκ° λ€μ λ»μ λνλΈλ€λ κ²μ μ½κ² μ μ μλ€.
π± μμΈ μν© ν μ€νΈ μ§ν κ³μ
μ¬νκΉμ§λ 첫 λ©λΆμΌμ κΈ°μ€μΌλ‘ λ§λ£μΌμ κ²μ°νλ κ²μ΄μμ§λ§, μ΄μ λ λ€μκ³Ό κ°μ μν©λ κ³ λ €λ₯Ό ν΄λ³΄μμΌ νλ€.
첫 λ©λΆμΌμ΄ 2019-01-31μ΄κ³ , λ§λ£λλ 2019-02-28μ 1λ§μμ λ©λΆνλ©΄ λ€μ λ§λ£μΌμ 2019-03-31μ΄λ€.
@Test
void 첫_λ©λΆμΌκ³Ό_λ§λ£μΌμ΄_μΌμκ°_λ€λ₯Όλ_λ§μ_λ©λΆ(){
PayData payData = PayData.builder()
.firstBillingDate(LocalDate.of(2019, 5, 31))
.billingDate(LocalDate.of(2019, 6, 30))
.payAmount(10_000)
.build();
assertExpiryDate(payData, LocalDate.of(2019, 7, 31));
}
///
public LocalDate calculateExpiryDate(PayData payData){
int addedMonths = 1;
if(payData.getFirstBillingDate() != null){
LocalDate candidateExp = payData.getBillingDate().plusMonths(addedMonths);
// 첫 λ©λΆ μΌμ(31μΌ)μ ν보 λ§λ£μΌμ μΌμ(28μΌ)μ΄ κ°μ§ μμλ
if(payData.getFirstBillingDate().getDayOfMonth() != candidateExp.getDayOfMonth()){
// 첫 λ©λΆμΌμ μΌμλ₯Ό ν보 λ§λ£μΌμ μΌμλ‘ μ¬μ©
return candidateExp.withDayOfMonth(payData.getFirstBillingDate().getDayOfMonth());
}
}
return payData.getBillingDate().plusMonths(addedMonths);
}
π± λ€μ ν μ€νΈλ₯Ό μ ν: μ¬μ΄ ν μ€νΈ
1. 2λ§μμ μ§λΆνλ©΄ λ§λ£μΌμ΄ λ λ¬λ€κ° λλ€.
2. 3λ§μμ μ§λΆνλ©΄ λ§λ£μΌμ΄ μ λ¬ λ€κ° λλ€.
λ€μκ³Ό κ°μ μν©μμ ν μ€νΈκ° μ±κ³΅ν μ μλλ‘ μ½λλ₯Ό λ³κ²½νμ.
@Test
void μ΄λ§μ_μ΄μ_λ©λΆνλ©΄_λΉλ‘ν΄μ_λ§λ£μΌ_κ³μ°(){
assertExpiryDate(PayData.builder()
.billingDate(LocalDate.of(2019, 3, 1))
.payAmount(20_000)
.build(), LocalDate.of(2019, 5, 1));
assertExpiryDate(PayData.builder()
.billingDate(LocalDate.of(2019, 3, 1))
.payAmount(30_000)
.build(), LocalDate.of(2019, 6, 1));
}
///
public LocalDate calculateExpiryDate(PayData payData){
int addedMonths = payData.getPayAmount()/10_000;
//μλ΅
}
μ΄μ λ 첫 λ©λΆμΌκ³Ό λ©λΆμΌμ μΌμκ° λ€λ₯Ό λ 2λ§μ μ΄μ λ©λΆν κ²½μ°μ μμΈ μν©λ κ³ λ €λ₯Ό ν΄λ³΄μμΌ νλ€.
public LocalDate calculateExpiryDate(PayData payData){
int addedMonths = payData.getPayAmount()/10_000;
if(payData.getFirstBillingDate() != null){
LocalDate candidateExp = payData.getBillingDate().plusMonths(addedMonths);
// 첫 λ©λΆ μΌμ(31μΌ)μ ν보 λ§λ£μΌμ μΌμ(28μΌ)μ΄ κ°μ§ μμλ
if(payData.getFirstBillingDate().getDayOfMonth() != candidateExp.getDayOfMonth()){
// ν보 λ§λ£μΌ(μ€μ λ μ§λ‘ νμΈ)μ΄ μ²« λμ λΈ μΌμλ³΄λ€ λ μμ κ²½μ°μλ ν보 λ§λ£μΌμ μΌμλ‘ return
if(YearMonth.from(candidateExp).lengthOfMonth()<payData.getFirstBillingDate().getDayOfMonth()){
return candidateExp.withDayOfMonth(YearMonth.from(candidateExp).lengthOfMonth());
}
// 첫 λ©λΆμΌμ μΌμλ₯Ό ν보 λ§λ£μΌμ μΌμλ‘ μ¬μ©
return candidateExp.withDayOfMonth(payData.getFirstBillingDate().getDayOfMonth());
}
}
return payData.getBillingDate().plusMonths(addedMonths);
}
///
@Test
void 첫_λ©λΆμΌκ³Ό_λ§λ£μΌ_μΌμκ°_λ€λ₯Όλ_μ΄λ§μ_μ΄μ_λ©λΆ(){
assertExpiryDate(PayData.builder()
.firstBillingDate(LocalDate.of(2019, 1, 31))
.billingDate(LocalDate.of(2019, 2, 28))
.payAmount(20_000)
.build(), LocalDate.of(2019, 4, 30));
assertExpiryDate(PayData.builder()
.firstBillingDate(LocalDate.of(2019, 3, 31))
.billingDate(LocalDate.of(2019, 4, 30))
.payAmount(30_000)
.build(), LocalDate.of(2019, 7, 31));
}
π± μ½λ 리ν©ν λ§
import java.time.LocalDate;
import java.time.YearMonth;
public class ExpiryDateCalculator {
public LocalDate calculateExpiryDate(PayData payData) {
int addedMonths = payData.getPayAmount() / 10_000;
if (payData.getFirstBillingDate() != null) {
return expiryDateUsingFirstBillingDate(payData, addedMonths);
} else {
return payData.getBillingDate().plusMonths(addedMonths);
}
}
private LocalDate expiryDateUsingFirstBillingDate(PayData payData, int addedMonths) {
LocalDate candidateExp = payData.getBillingDate().plusMonths(addedMonths);
final int dayOfFirstBilling = payData.getFirstBillingDate().getDayOfMonth();
// 첫 λ©λΆ μΌμ(31μΌ)μ ν보 λ§λ£μΌμ μΌμ(28μΌ)μ΄ κ°μ§ μμλ
if (isSameDayOfMonth(candidateExp, dayOfFirstBilling)) {
// ν보 λ§λ£μΌ(μ€μ λ μ§λ‘ νμΈ)μ΄ μ²« λμ λΈ μΌμλ³΄λ€ λ μμ κ²½μ°μλ ν보 λ§λ£μΌμ μΌμλ‘ return
final int dayLenOfCandiMon = lastDayOfMonth(candidateExp);
if (dayLenOfCandiMon < dayOfFirstBilling) {
return candidateExp.withDayOfMonth(dayLenOfCandiMon);
}
// 첫 λ©λΆμΌμ μΌμλ₯Ό ν보 λ§λ£μΌμ μΌμλ‘ μ¬μ©
return candidateExp.withDayOfMonth(dayOfFirstBilling);
}else{
return candidateExp;
}
}
private boolean isSameDayOfMonth(LocalDate candidateExp, int dayOfFirstBilling) {
return dayOfFirstBilling != candidateExp.getDayOfMonth();
}
private int lastDayOfMonth(LocalDate date) {
return YearMonth.from(date).lengthOfMonth();
}
}
π± 10κ°μ μκΈμ λ©λΆνλ©΄ 1κ°μ μ 곡
μ΄μ 10κ°μμ λ©λΆνλ©΄ μλΉμ€λ₯Ό 1λ μ 곡ν΄μ£Όλ ν μ€νΈ μ½λλ₯Ό μμ±ν΄λ³΄μ.
public LocalDate calculateExpiryDate(PayData payData) {
int addedMonths = payData.getPayAmount() == 100_000 ? 12: payData.getPayAmount() / 10_000;
if (payData.getFirstBillingDate() != null) {
return expiryDateUsingFirstBillingDate(payData, addedMonths);
} else {
return payData.getBillingDate().plusMonths(addedMonths);
}
}
π± ν μ€νΈ μ μ£Όμ μ¬ν
1. μ²μλΆν° λͺ¨λ ν μ€νΈ μ¬λ‘λ₯Ό μκ°νλ©΄ μκ°λ μ€λ 걸릴 λΏλλ¬ μ½μ§λ μμ
2. μλ‘ λ°κ²¬ν ν μ€νΈ μ¬λ‘λ₯Ό μ€ν¨νλ ν μ€νΈλ‘ λ±λ‘νλ κ²λ μ¬λ‘λ₯Ό λμΉμ§ μλ λ°©λ²
3. 'μ§λΌλ νΈλ λ‘' μμ€ν μ μ¬μ©νλ©΄ ν μ€νΈ μ¬λ‘λ₯Ό νμ μμ μΌλ‘ λ±λ‘ κ°λ₯ (ν΅κ³Ό μ¬λΆ μΆμ κ°λ₯)
4. ν μ€νΈ λͺ©λ‘μ νλμ ν μ€νΈλ‘ λ§λ€λ©΄ μλ¨