들어가며
모든 시스템에는 최소 하나의 컴포넌트가 존재함.
이 컴포넌트가 나머진 컴포넌트를 생성, 조정, 관리함.
저자는 이 컴포넌트를 메인(Main)이라고 부름.
궁극적인 세부사항
메인 컴포넌트는 궁국적인 세부사항으로 가장 낮은 수준의 정책임.
메인은 팩토리, 전략, 시스템 전반에 필요한 객체들을 생성하고 더 높은 수준에 정책에 제어권을 넘긴다.
메인은 클린 아키텍처에서 가장 바깥 원에 위치하는 지저분한 저수준 모듈임.
메인은 고수준의 시스템을 위한 모든것을 로드한 후 제어권을 고수준의 시스템에게 넘김.
→ 예를들면 책에 내용중인 움퍼스 게임에서도 main 함수에서 게임의 메인 루프, 입력 명령어 해석을 처리하지만 명령어의 실제 처리는 다른 고수준 컴포넌트로 위임시킴.
아래 예제 코드는 최신 움퍼스 사냥 게임(Hunt the Wumpus)의 메인 컴포넌트인데 문자열을 로드하는 방법으로, 코드의 나머지 핵심 영역에서 구체적인 문자열을 알지 못하게 하였음에 주목하자.
public class Main implements HtwMessageReceiver {
private static HuntTheWumpus game;
private static int hitPoints = 10;
private static final List<String> caverns = new ArrayList<>();
private static final String[] environments = new String[] {
"bright",
"humid",
"dry",
"creepy",
"ugly",
"foggy",
"hot",
"cold",
"drafty",
"dreadful"
};
private static final String[] shapes = new String[] {
"round",
"square",
"oval",
"irregular",
"long",
"craggy",
"rough",
"tail",
"narrow"
};
private static final String[] cavernTypes = new String[] {
"cavern",
"room",
"chamber",
"catacomb",
"crevasse",
"cell",
"tunnel",
"passageway",
"hall",
"expanse",
};
private static final String[] adornments = new String[] {
"smelling of sulfur",
"with engravings on the walls",
"with a bumpy floor",
"",
"littered with garbage",
"spttered with guano",
"with piles of Wumpus droppings",
"with bones scattered around",
"with a corpse on the floor",
"that seems to vibrate",
"that feels stuffy",
"that fills you with dread",
};
- main 함수에서 HtwFactory를 사용하여 게임을 생성하는 방식을 주목하자.
게임을 생성할 때 htw.game.HunTheWumpusFacase라는 클래스 이름을 전달하는데, 이 클래스는 메인보다도 더 지저분하기 때문이다. 재컴파일/재배포가 되지 않게하기 위함이다. - 그리고 main 함수에서 주목할 점이 하나 더 있다.
바로 입력 스트림 생성 부분, 게임의 메인 루프 처리, 간단한 입력 명령어 해석 등은 main 함수에서 모두 처리하지만, 명령어를 실제로 처리하는 일은 다른 고수준 컴포넌트로 위임한다는 사실이다.
public static void main(String[] args) throws IOException {
game = HtwFactory.makeGame("htw.game.HuntTheWumpusFacade", new Main());
createMap();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
game.makeRestCommand().execute();
while (true) {
System.out.println(game.getPlayerCavern());
System.out.println("Health: " + hitPoints + " arrows: " + game.getQuiver());
HuntTheWumpus.Command c = game.makeRestCommand();
System.out.println(">");
String command = br.readLine();
if(command.equalsIgnoreCase("e"))
c = game.makeMoveCommand(EAST);
else if (command.equalsIgnoreCase("w"))
c = game.makeMoveCommand(WEST);
else if (command.equalsIgnoreCase("n"))
c = game.makeMoveCommand(NORTH);
else if (command.equalsIgnoreCase("s"))
c = game.makeMoveCommand(SOUTH);
else if (command.equalsIgnoreCase("r"))
c = game.makeRestCommand();
else if (command.equalsIgnoreCase("sw"))
c = game.makeShootCommand(WEST);
else if (command.equalsIgnoreCase("se"))
c = game.makeShootCommand(EAST);
else if (command.equalsIgnoreCase("sn"))
c = game.makeShootCommand(NORTH);
else if (command.equalsIgnoreCase("ss"))
c = game.makeShootCommand(SOUTH);
else if (command.equalsIgnoreCase("q"))
return;
c.execute();
}
}
- 마지막으로 지도 생성 역시 main에서 처리한다.
private static void createMap(){
int nCaverns = (int) (Math,random() * 30.0 + 10.0);
while (nCaverns-- > 0)
caverns.add(makeName());
for(String cavern : caverns) {
maybeConnectCavern(cavern, NORTH);
maybeConnectCavern(cavern, SOUTH);
maybeConnectCavern(cavern, EAST);
maybeConnectCavern(cavern, WEST);
}
String playerCavern = anyCavern();
game.setPlayerCavern(playerCavern);
game.setWumpusCavern(anyOther(playerCavern));
game.addBatCavern(anyOther(playerCavern));
game.addBatCavern(anyOther(playerCavern));
game.addBatCavern(anyOther(playerCavern));
game.addPitCavern(anyOther(playerCavern));
game.addPitCavern(anyOther(playerCavern));
game.addPitCavern(anyOther(playerCavern));
game.setQuiver(5);
// 이하 코드 생략
}
- 요지는 메인은 클린 아키텍처에서 가장 바깥 원에 위치하는, 지저분한 저수준 모듈이다.
- 메인은 고수준의 시스템을 위한 모든 것을 로드한 후, 제어권을 고수준의 시스템에게 넘긴다.
결론
메인에서 초기 설정을 구성하고 외부 자원 수집 및 제어권을 고수준 정책으로 넘기는 플러그인이다.
플러그인이므로 애플리케이션별 설정이 다르도록하여 둘 이상의 메인 컴포넌트를 만들 수 있음.
EX) 개발용 메인 플러그인, 테스트용 메인 플러그인, 상용 메인 플러그인.
'IT > architecture' 카테고리의 다른 글
[Clean Architecture 정리] 28장. 테스트 경계 (0) | 2025.02.15 |
---|---|
[Clean Architecture 정리] 27장. '크고 작은 모든' 서비스들 (0) | 2025.02.15 |
[Clean Architecture 정리] 23장. 프레젠터와 험블 객체 (0) | 2025.02.15 |
[Clean Architecture 정리] 22장. 클린 아키텍처 (0) | 2025.02.15 |
[Clean Architecture 정리] 21장. 소리치는 아키텍처 (0) | 2025.02.15 |