SOLIDλ κ°μ²΄ μ§ν₯ μ€κ³μμ μ€μν 5κ°μ§ μμΉμ μλ―Ένλ€. μ΄ μμΉμ ν΄λ¦° μν€ν μ²μ μ μ λ‘λ²νΈ λ§ν΄μ΄ μ μνμΌλ©°, μννΈμ¨μ΄ κ°λ°μμ μμ‘΄μ±μ κ΄λ¦¬νκ³ , μ μ§λ³΄μμ νμ₯μ±μ ν₯μμν€κΈ° μν΄ μ¬μ©λλ€. κ°μΈμ μΌλ‘ SOLID μμΉμ 곡λΆνκΈ° μ κ³Ό νλ‘ μ½λ보λ μμ μ΄ λ§μ΄ λ¬λΌμ‘λ€κ³ λλλ€.
νλμ ν΄λμ€λ νλμ μ±
μλ§ κ°μ ΈμΌ νλ€λ μμΉμ΄λ€. ν΄λμ€ λΏλ§ μλλΌ λ©μλμλ ν΄λΉνλ κ² κ°λ€.
κ·Έλ°λ° μ±
μ? μ±
μμ΄ λκΉ μ±
μμ΄λ μν μ΄λ€ νλμ ν΄λμ€, νλμ λ©μλλ§λ€ κ°κ°μ μν κ³Ό κ΄μ¬μ¬λ₯Ό μμ§λ ₯μκ² λ§λ€μ΄ μ΄λ₯Ό ν΅ν΄ ν΄λμ€κ° λμ± λͺ
νν΄μ§κ³ , μ¬μ¬μ©μ μ©μ΄νκ² λ§λ€λΌλ μλ―Έμ΄λ€.
μ΄λ₯Ό μ μ§μΌμΌ ν κΉ? κ·Έλ₯ νκ³³μλ€ λ€ λͺ°μμ νλ©΄ μλλ? κ°κ°μ μν λ³λ‘ ν΄λμ€μ λ©μλλ₯Ό λ§λ€λ©΄ κ΄ν μ½λμλ§ λμ΄λμ§ μλ? κ·Έλ μ§ μλ€ μλ μμλ₯Ό 보μ.
public class μ¬λ {
void μΌνκΈ°() {
System.out.println("μ½λλ₯Ό νλ€λ₯ νλ€λ₯ μΉλμ€ ...");
}
void ν¨λνκΈ°() {
System.out.println("λΆλͺ¨λκ» ν¨λνλμ€ ...");
}
void λ°μ΄νΈνκΈ°() {
System.out.println("μ¬μμΉκ΅¬λ λ°μ΄νΈ νλμ€ ...");
}
}
μ¬λμ΄λΌλ ν΄λμ€λ μ½λ©νκΈ°, ν¨λνκΈ°, λ°μ΄νΈνκΈ° λΌλ μ‘μ μ ν μ μλ λ©μλλ€μ΄ μλ€.
λ§μ½ νμ¬, μλ§, μ¬μμΉκ΅¬ λΌλ ν΄λμ€λ€μ΄ μλ€κ³ κ°μ ν λ μ΄ ν΄λμ€λ€μ μ μ¬ κ°λ°μ ν΄λμ€λ₯Ό μμ‘΄νκ² λ κ² μ΄λ€. μ¬κΈ°μ νμ¬ ν΄λμ€μμλ ν¨λνκΈ°μ λ°μ΄νΈνκΈ°μ κ°μ κΈ°λ₯μ νμλ μλλ° μ¬μ©ν μ μκ² λλ€.
λ²μ¨ λ§μ΄ μλ€.
λ, μ¬λ ν΄λμ€λ₯Ό μμ ν λ λ§λ€ ν΄λΉ ν΄λμ€λ€μ΄ μν₯μ λ°κ² λλ€.
μ΄λ₯Ό κ°μ νκΈ° μν΄μλ μν λ³λ‘ ν΄λμ€λ₯Ό λ§λ€κ³ λ©μλλ₯Ό λΆλ¦¬νλ€λ©΄ SRPλ₯Ό μ€μ²ν μ μκ²λλ€.
ν΄λμ€, λͺ¨λ, ν¨μ λ±μ νμ₯μλ μ΄λ €μμ§λ§ λ³κ²½μλ λ«νμμ΄μΌ νλ€λ μμΉμ΄λ€. μ¦, κΈ°μ‘΄ μ½λλ₯Ό λ³κ²½νμ§ μκ³ λ κΈ°λ₯μ μμ νκ±°λ νμ₯ν μ μλ ꡬ쑰λ₯Ό μλ―Ένλ€.
κ·Έλ°λ° μ΄λ»κ² κΈ°μ‘΄ μ½λλ₯Ό λ³κ²½μ μνκ³ νμ₯ν μ μλκ±ΈκΉ? μλ μμλ₯Ό 보μ
public class UserRepository {
private final MysqlConnector connector;
public UserRepository(mysqlConnector connector) {
this.connector = connector;
}
public void save(User user) {
connector.save(user);
}
}
λ³λ‘ μ΄μν μ μ΄ μλ μ½λμ§λ§, λ§μ½ DBMSλ₯Ό MySQLμμ Oracleλ‘ λ³κ²½ν΄μΌ νλ€λ©΄ μ΄λ¨κΉ?
UserRepositoryκ° μμ‘΄νκ³ μλ MysqlConnectorλΆλΆμ OracleConnectorλ₯Ό λ§λ€μ΄μ μμ ν΄μΌ ν κ²μ΄λ€.
κ·Έλ°λ° λ§μ½ μμ€ν
μ 체μμ MysqlConnectorλ₯Ό μμ‘΄νκ³ μλ μ½λλ₯Ό λ³κ²½ν΄μΌ νλ€ μκ°νλ©΄ μ΄μ§μ΄μ§ νλ€.
μ΄λ₯Ό κ°μ νκΈ° μν΄μ μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ¬ DatabaseConnector λΌλ μΆμμ μΈ κ°λ μ λ§λ€λ©΄ λλ€.
ν΅μ¬μ UserRepositoryκ° νΉμ dbλ²€λμ μμ‘΄νμ§ μκ²λ νλκ²μ΄λ€. κ°μ λ μ½λλ₯Ό 보μ
// DBμ°κ²°λΆμ save λ©μλλ₯Ό μΆμν μν¨ ν μΈν°νμ΄μ€λ₯Ό ꡬνν ꡬν체λ€
public interface DatabaseConnector {
void save(User user);
}
public class MysqlConnector implements DatabaseConnector {
@Override
public void save(User user) {
System.out.println("Saving user to MySQL database");
}
}
public class OracleConnector implements DatabaseConnector {
@Override
public void save(User user) {
System.out.println("Saving user to Oracle database");
}
}
// ꡬν체μ μμ‘΄νμ§ μκ³ μΈν°νμ΄μ€μ μμ‘΄ν¨μΌλ‘μ¨ OCPλ₯Ό μ§ν¨ μ½λ
public class UserRepository {
private final DatabaseConnector connector;
public UserRepository(DatabaseConnector connector) {
this.connector = connector;
}
public void saveUser(User user) {
connector.save(user);
}
}
μ΄μ Mysqlμ΄λ Oracleμ΄λ Mariaλ μκ΄μμ΄ DatabaseConnectorλ§ κ΅¬νν ꡬν체λ₯Ό κ½μμ£ΌκΈ°λ§ νλ©΄ UserRepositoryλ₯Ό μμ νμ§ μκ³ λ κΈ°λ₯μ νμ₯νκ±°λ μμ ν μ μκ²λμλ€.
리μ€μ½ν μΉν μμΉμ 1988λ
λ°λ°λΌ 리μ€μ½νκ° μ¬λ°λ₯Έ μμ κ΄κ³μ νΉμ§μ μ μνκΈ° μν΄ λ°νν κ²μ΄λ€.
μλΈ νμ
μ μΈμ λ κΈ°λ° νμ
μΌλ‘ κ΅μ²΄ν μ μμ΄μΌ νλ€λ κ²μ λ»νλ€.
κ΅μ²΄ν μ μλ€λ κ²μ μμ ν΄λμ€λ μ΅μν μμ μ λΆλͺ¨ ν΄λμ€μμ κ°λ₯ν νμλ μνμ΄ λ³΄μ₯λμ΄μΌ νλ€λ μλ―Έμ΄λ€.
μ¦, λΆλͺ¨ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μ¬μ©νλ μμΉμ μμ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό λμ μ¬μ©νμ λ μ½λκ° μλ μλλλ‘ μλν΄μΌ νλ€λ μλ―Έμ΄λ€.
μ΄λ¬ν LSP μμΉμ μ μ μ©ν μμκ° μλ°μ 컬λ μ νλ μμν¬ μ΄λ€.
λ§μΌ λ³μμ LinkedList μλ£νμ λ΄μ μ¬μ©νλ€, μ€κ°μ μ ν λ€λ₯Έ HashSet μλ£νμΌλ‘ λ°κΏλ add() λ©μλ λμμ 보μ₯λ°κΈ° μν΄μλ Collection μ΄λΌλ μΈν°νμ΄μ€ νμ μΌλ‘ λ³μλ₯Ό μ μΈνμ¬ ν λΉνλ©΄ λλ€.
μλνλ©΄ μΈν°νμ΄μ€ Collectionμ μΆμ λ©μλλ₯Ό κ°κΈ° νμ μλ£ν ν΄λμ€μμ implementsνμ¬ μΈν°νμ΄μ€ ꡬν κ·μ½μ μ μ§ν€λλ‘ μ μ€κ³κ° λμ΄μκΈ° λλ¬Έμ΄λ€.
void main() {
// Collection μΈν°νμ΄μ€ νμ
μΌλ‘ λ³μ μ μΈ
Collection data = new LinkedList();
data = new HashSet(); // μ€κ°μ μ ν λ€λ₯Έ μλ£ν ν΄λμ€λ₯Ό ν λΉν΄λ νΈνλ¨
modify(data); // λ©μλ μ€ν
}
void modify(Collection data){
data.add(1); // μΈν°νμ΄μ€ ꡬν κ΅¬μ‘°κ° μ μ‘νμκΈ° λλ¬Έμ add λ©μλ λμμ΄ κ°κΈ° μλ£νμ λ§κ² 보μ₯λ¨
}
리μ€μ½ν μΉν μμΉμ μ΄κΈ΄ μ¬μ΄ μμλ‘λ λ€μκ³Ό κ°λ€.
// λΆλͺ¨ ν΄λμ€
class μ {
public void λ λ€() {
System.out.println("μκ° λ κ³ μλ€.");
}
}
// μμ ν΄λμ€
class μ°Έμ extends μ {
@Override
public void λ λ€() {
System.out.println("μ°Έμκ° λ κ³ μλ€.");
}
}
// μμ ν΄λμ€
class νμ‘° extends μ {
@Override
public void λ λ€() {
throw new UnsupportedOperationException("νμ‘°λ λ μ μλ€.");
}
}
μλΌλ λΆλͺ¨ ν΄λμ€μλ λ λ€λΌλ λ©μλκ° μλλ° νμ‘°μ κ²½μ° μμ ν μ’
λ₯ μ΄κΈ΄ νμ§λ§ λ μλ μλ€.
μ΄ μ²λΌ μμκ΄κ³μμμ λͺ¨νΈν κ΄κ³κ° λ°μν κ²½μ° μ΄λ₯Ό μ μ ν ν΄κ²°ν΄μ€μΌ νλ€.
ν΄λ²μΌλ‘λ λ λ€λΌλ κΈ°λ₯μ μΈν°νμ΄μ€λ‘ λ§λ€μ΄ μ μ ν ꡬννκ² λ§λ€μ΄μ£Όλ©΄ λλ€.
// λΆλͺ¨ ν΄λμ€
class μ {
// 곡ν΅λ μμ± λ° λ©μλ μ μ
}
interface λ μμλ {
void fly();
}
// μμ ν΄λμ€
class μ°Έμ extends μ implements λ μμλ {
@Override
public void λ λ€() {
System.out.println("μ°Έμκ° λ κ³ μλ€.");
}
}
// μμ ν΄λμ€
class νμ‘° extends μ {
}
μΈν°νμ΄μ€ λΆλ¦¬ μμΉμ νΉμ ν΄λΌμ΄μΈνΈλ₯Ό μν μΈν°νμ΄μ€ μ¬λ¬ κ°κ° λ²μ© μΈν°νμ΄μ€ νλλ³΄λ€ λ«λ€λ μμΉμ΄λ€.
κ·Έ μ΄μ λ λ²μ© μΈν°νμ΄μ€μ κ²½μ° κ΅¬νν΄μΌν μΆμ λ©μλλ€μ΄ λ§μ΄ μκΈ° λλ¬Έμ λ΄κ° ꡬννκ³ μΆμ§ μμλ ꡬνν΄μΌλ§ νλ λΆμμ¬κ° μΌμ΄λκΈ° λλ¬Έμ΄λ€.
interface μμ
μ {
void μμ
νλ€();
void μμ¬νλ€();
}
class μ¬λμμ
μ implements μμ
μ {
public void μμ
νλ€() {
System.out.println("μ¬λμ΄ μμ
νκ³ μμ΅λλ€");
}
public void μμ¬νλ€() {
System.out.println("μ¬λμ΄ μμ¬νκ³ μμ΅λλ€");
}
}
class λ‘λ΄μμ
μ implements μμ
μ {
public void μμ
νλ€() {
System.out.println("λ‘λ΄μ΄ μμ
νκ³ μμ΅λλ€");
}
// λ‘λ΄μ λ¨Ήμ νμκ° μμ§λ§, μΈν°νμ΄μ€ λλ¬Έμ μμ¬νλ€() λ©μλλ₯Ό ꡬνν΄μΌ νλ€
public void μμ¬νλ€() {
throw new UnsupportedOperationException("λ‘λ΄μ μμ¬ν μ μμ΅λλ€");
}
}
μμ‘΄μ± μμ μμΉμ΄λ κ³ μμ€ κ°λ μ μ μμ€ κ°λ μ μμ‘΄ν΄μλ μλλ€λ μμΉμ΄λ€. κ·Έλ¦¬κ³ μΆμνλ ꡬ체μ μΈ μ¬νμ μμ‘΄ν΄μλ μλλ©°, ꡬ체μ μΈ μ¬νμ΄ μΆμνμ μμ‘΄ν΄μΌ νλ€λ μλ―Έμ΄λ€.
κ·ΈλΌ μ¬κΈ°μ κ³ μμ€μ λκ³ μ μμ€μ 무μμΌκΉ?
κ³ μμ€ : μ ν리μΌμ΄μ
μ μ μ±
μ μ μνλ κ°λ
μ΄λ€. μ£Όλ‘ λΉμ¦λμ€ λ‘μ§μ ν¬ν¨νλ€.
μ μμ€ : κ³ μμ€ κ°λ
μ μ§μνλ μμμΌλ‘ ꡬ체μ μ ꡬν μΈλΆ μ¬νμ ν¬ν¨νλ€. λ°μ΄ν° λ² μ΄μ€ μ κ·Ό, λ€νΈμν¬ ν΅μ λ±μ μΈλΆμ μΈ κΈ°λ₯μ λ΄λΉνλ€.
interface DataRepository {
void save(Object data);
}
class FileDataRepository implements DataRepository {
public void save(Object data) {
// νμΌ μμ€ν
μ λ°μ΄ν° μ μ₯
}
}
class HighLevelModule {
private DataRepository dataRepository;
public HighLevelModule(DataRepository dataRepository) {
this.dataRepository = dataRepository;
}
public void performAction(Object data) {
dataRepository.save(data);
}
}