๊ฐ์ฒด ์งํฅ์ ๋๋ช ์ฌ์ธ Java๋ฅผ ์ฌ์ฉํ๋ฉฐ ๊ฐ๋ฐ์๋ค, ์ฆ ์ฐ๋ฆฌ๋ค์ ์ ์ฐจ ์งํฅ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ๋๊ฐ ๋ง๋ค.
์ฒ์ ๊ฐ์ฒด ์งํฅ์ ๊ณต๋ถํ๋ ๋, ๊ฐ์ฒด๋ผ๋ ๊ฐ๋ ์ด ๊ทธ๋ฆฌ๋ ๋ฏ์ค์๋ค.
C์ธ์ด๋ก ์ฝ๋ฉ ์ ๋ฌธ์ ํ๊ธฐ์, ์ ์ฐจ์ ์ธ ์ฝ๋์ ๋ช ๋ น์๋ง ์ต์ํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ฐ์ฒด ์งํฅ ๊ธฐ๋ฒ์ ๊ณต๋ถํ๋ฉด์, ํด๋์ค๋ฅผ ์ฌ๋์ผ๋ก ๋ฐ๋ผ๋ณด๋ ค ๋ ธ๋ ฅํ๊ณ ์ฌ๋ฌ ๊ฐ์ง ์ฑ ๊ณผ ๊ฐ์ฒด ์งํฅ ์ํ ์ฒด์กฐ ์์น ๋ฑ์ ๊ฐ๋ ์ ์์งํ๋,
์๊ฐ์ด ์ง๋๋ฉฐ ํจ์ฌ Java์ค๋ฝ๊ฒ ์์ฑํ ์ ์๊ฒ ๋ ๊ฒ ๊ฐ๋ค.
ํ์ง๋ง, ์์ง๋ ๊ฐ์ฒด ์ฆ ํด๋์ค๋ฅผ ์ค๊ณํ๊ณ ๋๋๋ ๊ฑด ํ๋ ์ผ์ด๋ผ ์๊ฐํ๋ค.
๊ทธ๊ฒ์ ๊ณง ์ค๊ณ์ ๋ํ ์์ญ์ด๋ผ ์๊ฐ์ด ๋๋๋ฐ, ์ต๊ทผ์ LinkedIn ์์ ๋ณธ ํ ๋น ๋์ ๊ธ์ฒ๋ผ ๊ฐ๋ฐ์๋ค์ ์ค๊ณ๋ฅผ ์ง์ ๋ค๋ฃจ๋ฉฐ ๊ณต๋ถํ ์ผ์ด ์๊ธฐ ๋๋ฌธ์ด๋ผ๋ ์๊ฐ๋ ๋ ๋ค.
์ ๋ง ๊ธฐ๋ณธ์ด ๋๋ ๋ด์ฉ์ด์ง๋ง ๋ค์ ํ๋ฒ ์ ๋ฆฌํด ๋ณด์~!
---
์ด ์ฑํฐ์์๋ ์ค๋ฌธ์กฐ์ฌ ๊ธฐ์ ์ ์๋ฅผ ๋ ๋ค.
๊ฐ๋ฒผ์ด usecase๋ฅผ ์ฝ๋๋ก ์์ฑํ ๊ฒ์ ์๋ก ๋ค๊ณ ์๋๋ฐ, ์ฒ์์ ์ฑ ์ ์์ด ํ๋์ usecase ์์ ์ ์ฐจ์ ์ธ ์ฝ๋๋ฅผ ๋ณด์ฌ์ฃผ๋ฉฐ ์์ํ๋ค.
๊ฐ์ฒด ์งํฅ ์ค๊ณ ๊ธฐ๋ฒ์ ์ ์ฉํ๋ฉฐ, ๋ฆฌํฉํ ๋ง์ ํด๋ ๊ฐ๋ณด์.
์ฑ ์ ์ฃผ๋ ์ค๊ณ.
์ฑ ์, ์ญํ , ํ๋ ฅ์ผ๋ก ํํํ๋ ์ ๊ทผ ๋ฐฉ๋ฒ์ ํ ๋ถ์ผ.
๊ฐ์ฒด์ ์ฑ ์์ ๋ถ์ฌํ๋ ๊ฒ์ด ์ค์ํ๋ค.
๊ฐ์ฒด์ ์ฑ ์์ ๊ณง "์๋ ๊ฒ", "ํ๋ ๊ฒ"์ด๋ค.
์๋ ๊ฒ์ ํด๋์ค์ ์์ฑ(ํ๋)์ด๋ฉฐ, ํ๋ ๊ฒ์ ๋ฉ์๋์ด๋ค. ์ ๋ง ๊ธฐ๋ณธ๊ธฐ~
๊ฐ์ฒด ์งํฅ ์ํ ์ฒด์กฐ ์์น์์๋ ๋ค๋ฃจ ๋ฏ์ด,
๊ฐ์ฒด์ ๋ฌป์ง ๋ง๊ณ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ผ (Tell Dont Ask)
๋๋ฏธํฐ์ ๋ฒ์น "Don't talk to stranger"(๋ฏ์ ์ฌ๋๊ณผ ๋ํํ์ง ๋ง๋ผ)
private String secondUncle = me.family.father.family.father.sons[1];
^ ์๊ฒ ๋ณด๋ค๋ (์ฒด์ด๋์ด ๋๋ฌด ์ฌํ์์, ๋ฌป์ง ๋ง๊ตฌ..)
private String secondUncle = me.secondUncle;
^ ์๋ ๊ฒ ํ๋ฉด ํจ์ฌ ๋ซ์ง ์์๊น
๋จ์ผ ์ฑ ์ ์์น. (Simple Responsibility Principle)
ํด๋์ค๋ ํ ๊ฐ์ง ์ผ๋ง ์ํ, ํ ๊ฐ์ง ์ด์ ์ ์ํด์๋ง ๋ณ๊ฒฝ๋์ด์ผ ํ๋ค.
๋ง์ฝ ํด๋์ค๊ฐ ๋ณ๊ฒฝ๋๋ ์ด์ ๊ฐ ์ฌ๋ฌ ๊ฐ๋ผ๋ฉด SRP๋ฅผ ์๋ฐํ ๊ฒ.
์ฌ๋ฌ ์ฑ ์์ ๊ฐ์ง ํด๋์ค๋ก ๋๋๊ณ , ์ฐ๊ด๋ ์์ฑ์ ํ๋์ ํด๋์ค๋ก ํตํฉํ๋ผ!
public class Assign {
private Customer customer;
private Surveyor surveyor;
}
์์ ๊ฐ์ด ํตํฉํด์~
๊ฐ๋ฐฉ/ํ์ ์์น. (Open/Closed Principle)
์ฝ๋๊ฐ ์์ ๋ก์ฐ๋ฉด์๋ ์ ํ์ ์ด์ด์ผ ํ๋ค.
์ํํธ์จ์ด ์ํฐํฐ๋ ๊ฒฐ๊ตญ ํ์ฅ์ ๋ํด์ ๊ฐ๋ฐฉ์ ์ด๋, ์์ ์ ๋ํด์ ํ์์ ์ด์ด์ผ ํ๋ค.
์ผ๋ก๋ก WAS์ธ tomcat์ ์๋ก ๋ ๋ค. Java Web Application์ warํ์ผ๋ก ๋ง๋ค๊ณ tomcat์ ๋ฐฐํฌํ๋๋ฐ, warํ์ผ์ ํฐ์บฃ ๊ณ ์ ๊ธฐ๋ฅ์ ์ํฅ์ ์ฃผ๊ฑฐ๋ ๋ณ๊ฒฝํ์ง ์์ผ๋ฏ๋ก ๋ณ๊ฒฝ์ ํ์์ ์ด๋ค. ๋ฐ๋๋ก ์๋ก์ด ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฏ๋ก ํ์ฅ์ ๊ฐ๋ฐฉ๋์ด ์๋ค๊ณ ๋ณผ ์ ์๋ค.
์ฝ๋์์๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค. ์ธํฐํ์ด์ค๋ ์์ ํด๋์ค์ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋๊ณ ๊ตฌํ ํด๋์ค๋ ์์ ํด๋์ค์์ ๊ธฐ๋ฅ์ ํ์ฅํ๋ค.
ํ์ฅ์ ๋ํ ๊ฐ๋ฐฉ์ ๊ตฌํ, ์์ ํด๋์ค์์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์์ด์ผ ํ๊ณ , ์์ ์ ๋ํ ํ์๋ ์ธํฐํ์ด์ค๋ ์์ ํด๋์ค์ ๋ณํ๊ฐ ํ์์ ์ํฅ์ ์ฃผ์ง ์์์ผ ํ๋ค.
interface Filter {
boolean isSatisfied(Customer customer);
}
class ContactFilter extends Filter {
//...
}
class AgeFilter implements Filter {
// ...
}
class GenderFilter implements Filter {
// ...
}
์ด์ฒ๋ผ ๊ตฌํ์ฒด๋ ์ฑ๊ฒฉ์ ๋ง๊ฒ ํด๋น ์ถ์์ฒด๋ฅผ ํ์ฅํด ๋๊ฐ ์ ์๋ค.
๋ฆฌ์ค์ฝํ ์นํ ์์น. (Liskov Substitution Principle)
ํด๋ผ์ด์ธํธ๊ฐ ์์ ํด๋์ค๋ฅผ ์์ ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํ๋๋ฐ ๋์์ ์ค๋ค.
ํด๋ผ์ด์ธํธ๋ ํด๋์ค์ ์์ ๊ตฌ์กฐ์ ๊ด๊ณ์์ด ์์ ํด๋์ค๋ง ์ดํดํ๊ณ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
S๊ฐ ๊ธฐ๋ฐํ์ T์ ์๋ธํ์ ์ด๋ฉด T ํ์ ์ ๊ฐ์ฒด๋ ํ๋ก๊ทธ๋จ ์คํ์ ๋ฌธ์ ๋ฅผ ์ผ์ผํค์ง ์๊ณ S ํ์ ์ ๊ฐ์ฒด๋ก ์นํ์ด ๊ฐ๋ฅํด์ผ ํ๋ค.
๊ธฐ๋ฐ ํ์ : ํด๋ผ์ด์ธํธ๊ฐ ์ง์ ์ฌ์ฉํ๋ ํ์ , ํด๋ผ์ด์ธํธ๋ ๊ธฐ๋ฐํ์ ์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถ
์๋ธ ํ์ : ๊ธฐ๋ฐ ํ์ ์ ์์ํ ๋ชจ๋ ์ข ๋ฅ์ ํด๋์ค
๋ฌธ๋งฅ : ํด๋ผ์ด์ธํธ๊ฐ ๊ธฐ๋ฐ ํ์ ์ ๋ฉ์๋๋ฅผ ์ด์ฉํด ์๋ธ ํ์ ์ ํธ์ถํ ์ ์๋ ์กฐ๊ฑด
public interface Distributable {
public List<Assign> distribute(List<Customer> customers, List<Surveyor> surveyors);
}
public class RoundRobinDistributor implements Distributable {
@Override
public List<Assign> distribute(List<Customer> customers, List<Surveyor> surveyors) {
// round robin ๋ฐฉ์ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ
}
}
public class PerformanceDistributor implements Distributable {
@Override
public List<Assign> distribute(List<Customer> customers, List<Surveyor> surveyors) {
// ์ฑ๊ณผ๊ฐ ์ข์ ์ค๋ฌธ ์กฐ์ฌ์์๊ฒ ๋ฐฐ์ ํ๋ ๋ฐฉ์ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ
}
}
๊ฑฐ์ ๋น์ทํ ๋ฏ~~ ๋ฌธ๋งฅ๋ง ์ดํดํ๋ฉด ๋๋ค.
์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น. (Interface Segregation Principle)
๋๋ฌด ๋ง๊ฑฐ๋, ๊ด๊ณ์๋ ์คํผ๋ ์ด์ ์ ์ ๊ณตํ๋ ์ธํฐํ์ด์ค๋ฅผ ์ง์ํ์.
๋ชฉ์ ์ ๋ง๊ฒ!! ์๊ฒ ๋๋์~~
Spring Data JPA Interface ๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด,
์์ ๊ฐ์ด ์ฑ ์์ ๋ง๊ฒ ์ฌ๋ฌ interface๋ค์ด ํ์๋ก ์์ํ๋ ๊ฒ์ ์ ์๊ฐ ์๋ค.
JPA ์ธ๋ถ ๊ตฌํ์ด ํ์ ์๋ค๋ฉด, CrudRepository ๋ง ์์ํ๋ ๊ฒฝ์ฐ๋ ์ผ๋ถ ๋ณผ ์ ์๋ค.
์์กด์ฑ ์ญ์ ์์น. (Dependency Inversion Principle)
์ฌ์ค ์์ ๋์จ ๊ฐ๋ ๋ค๊ณผ ๊ฑฐ์ ๋น์ทํ ๊ฐ๋ .
๊ตฌ์ฒด์ ์ธ (ํน์ ์์ฃผ ๋ณํ ์ ์๋) ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ง์ ์์ง ๋ชปํ๊ฒ ๋ถ๋ฆฌํ๋ผ.
LSP ์์ ์ฝ๋์์ ์ ์ ์์๋ฏ์ด, ํด๋ผ์ด์ธํธ๋ Distributable ์ธํฐํ์ด์ค๋ง ์๋ฉด ๋๋ค. ์ธ๋ถ ๊ตฌํ์ ์ ํ์๊ฐ ์๋ค.
๋ง์ด ์ด๋ ค์ธ ์๋ ์์ง๋ง ๊ฒฐ๊ตญ, ์์กด์ฑ์ interface๋ก ์ญ์ ์ํจ ๊ฒ์ด๋ค. ๊ตฌํ๋ถ๋ฅผ ์์กดํ์ง ์๊ฒ ํ๊ธฐ ์ํด!!
์ด๋ฅผ ํ ๋ฉด,
interface UserReader {
fun findBy(userId: Long) : User?
}
class DBUserReader(
private val jpaUserDao: JpaUserDao
): UserReader {
override fun findBy(userId: Long): User? {
return jpaUserDao.findByIdOrNull(userId).toEntity()
}
}
class HttpUserReader(
private val userClient: UserClient
): UserReader {
override fun findBy(userId: Long): User? {
return runCatching {
userClient.getUser(userId)
}.onFailure {
logger.error(it.message())
}.getOrNull()
}
}
// ๋น์ฆ๋์ค์์..
fun usecase(
private val dbUserReader: UserReader
) {
// ๋ก์ง ๊ตฌํ
}
}
์๋ ๊ฒ ํ ์๋ ์๋ค.
---
๊ฐ์ฒด ์งํฅ ์์น์ ๊ณต๋ถ๋ง ํ์ง ๊ธ๋ก ์ฒ์ ์ ๋ฆฌํด ๋ณธ๋ค ใ ใ
๋น์ฆ๋์ค๋ฅผ ์น๋ฉด์, ์ข ๋ ์ ๋ ํ๊ณ ์ต๋ํ ํ์ฉํ๋ ค ์์ํด์ผ ํ๋ค!! ๊ทธ๋์ผ ๋์ง~~
๋ค์ ์ฅ์ ๋๋์ด ์ด๋ฒคํธ ์์ฑ์ด๋ค!!