feat : SOLID - SRP 샘플 코드 구현

This commit is contained in:
banjjoknim
2022-11-07 22:31:29 +09:00
parent 8ac2fd7eff
commit f9af46e64a
17 changed files with 243 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# SOLID & Design Pattern Sample
## SOLID
- SOLID 원칙들은 소프트웨어 작업에서 프로그래머가 소스 코드가 읽기 쉽고 확장하기 쉽게 될 때까지 소프트웨어 소스 코드를 리팩터링하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침이다.
- 각 항목별 before & after 를 비교하면서 어떤 차이가 있는지 생각해본다.
- before & after 에 새로운, 또는 동일한 규칙(비즈니스 로직, 유효성 검사 등)을 적용해야 한다고 가정하고 변경을 시도해본다.
### SRP(Single Responsibility Principle)
- 단일 책임 원칙
- 한 클래스는 하나의 책임만 가져야 한다. 즉, 한 클래스가 변경되는 이유는 한 가지여야 한다.
#### 구현 요구사항
- 예금주의 이름으로 계좌를 생성할 수 있다.
- 계좌에 입금할 수 있다.
- 계좌에서 출금할 수 있다.
## 참고자료
- [SOLID (객체 지향 설계)](https://ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84))

View File

@@ -0,0 +1,18 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RequestMapping("/accounts")
@RestController
class CreateAccountController(
private val createAccountService: CreateAccountService
) {
@PostMapping("")
fun createAccount(@RequestBody request: CreateAccountRequest): Account {
return createAccountService.createAccount(request)
}
}

View File

@@ -0,0 +1,5 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
data class CreateAccountRequest(
val holderName: String
)

View File

@@ -0,0 +1,14 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.AccountRepository
import org.springframework.stereotype.Service
@Service
class CreateAccountService(
private val accountRepository: AccountRepository
) {
fun createAccount(request: CreateAccountRequest): Account {
return accountRepository.createAccount(request.holderName)
}
}

View File

@@ -0,0 +1,18 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RequestMapping("/accounts")
@RestController
class DepositAccountController(
private val depositAccountService: DepositAccountService
) {
@PatchMapping("/deposit")
fun depositAccount(@RequestBody request: DepositAccountRequest): Account {
return depositAccountService.depositAccount(request)
}
}

View File

@@ -0,0 +1,6 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
data class DepositAccountRequest(
val accountId: Long,
val amount: Int
)

View File

@@ -0,0 +1,16 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.AccountRepository
import org.springframework.stereotype.Service
@Service
class DepositAccountService(
private val accountRepository: AccountRepository
) {
fun depositAccount(request: DepositAccountRequest): Account {
val account = accountRepository.findAccount(request.accountId)
account.deposit(request.amount)
return account
}
}

View File

@@ -0,0 +1,18 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RequestMapping("/accounts")
@RestController
class WithdrawalAccountController(
private val withdrawalAccountService: WithdrawalAccountService
) {
@PatchMapping("/withdrawal")
fun withdrawal(@RequestBody request: WithdrawalAccountRequest): Account {
return withdrawalAccountService.withdrawalAccount(request)
}
}

View File

@@ -0,0 +1,6 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
data class WithdrawalAccountRequest(
val accountId: Long,
val amount: Int
)

View File

@@ -0,0 +1,16 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.after
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.AccountRepository
import org.springframework.stereotype.Service
@Service
class WithdrawalAccountService(
private val accountRepository: AccountRepository
) {
fun withdrawalAccount(request: WithdrawalAccountRequest): Account {
val account = accountRepository.findAccount(request.accountId)
account.withdrawal(request.amount)
return account
}
}

View File

@@ -0,0 +1,18 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.before
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RequestMapping("/accounts")
@RestController
class AccountControllerBefore(
private val accountServiceBefore: AccountServiceBefore
) {
@PatchMapping("/manage-account-before")
fun manageAccount(@RequestBody request: ManageAccountRequest): Account {
return accountServiceBefore.manageAccount(request)
}
}

View File

@@ -0,0 +1,28 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.before
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.Account
import com.banjjoknim.soliddesignpatternsample.solid.srp.common.AccountRepository
import org.springframework.stereotype.Service
@Service
class AccountServiceBefore(
private val accountRepository: AccountRepository
) {
fun manageAccount(request: ManageAccountRequest): Account {
return when (request.type) {
ManageAccountType.CREATE -> {
accountRepository.createAccount(request.holderName)
}
ManageAccountType.DEPOSIT -> {
val account = accountRepository.findAccount(request.accountId)
account.deposit(request.amount)
account
}
ManageAccountType.WITHDRAWAL -> {
val account = accountRepository.findAccount(request.accountId)
account.withdrawal(request.amount)
account
}
}
}
}

View File

@@ -0,0 +1,8 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.before
data class ManageAccountRequest(
val accountId: Long,
val holderName: String,
val amount: Int,
val type: ManageAccountType
)

View File

@@ -0,0 +1,7 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.before
enum class ManageAccountType {
CREATE, // 생성
DEPOSIT, // 입금
WITHDRAWAL // 출금
}

View File

@@ -0,0 +1,20 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.common
import javax.persistence.Entity
import javax.persistence.Id
@Entity
class Account(
val holderName: String = "",
var balance: Int = 0,
@Id
val id: Long = 0,
) {
fun deposit(amount: Int) {
this.balance = this.balance + amount
}
fun withdrawal(amount: Int) {
this.balance = this.balance - amount
}
}

View File

@@ -0,0 +1,7 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.common
interface AccountRepository {
fun createAccount(holderName: String): Account
fun findAccount(accountId: Long): Account
}

View File

@@ -0,0 +1,14 @@
package com.banjjoknim.soliddesignpatternsample.solid.srp.common
import org.springframework.stereotype.Repository
@Repository
class AccountRepositoryStub : AccountRepository {
override fun createAccount(holderName: String): Account {
return Account(holderName = "banjjoknim", balance = 0)
}
override fun findAccount(accountId: Long): Account {
return Account(id = 1L, balance = 10000)
}
}