자바 공부를 하면서 노래 추천 해주는 코드를 짜고 있습니다.
객체구성은 다섯가지로 되어 있습니다. -Mumu(전체 총괄하는 클래스) -Engine(행렬곱을 하는 클래스) -Database(사람, 노래간 정보를 가지고 있는 클래스) -Player(사람) -Song(음악)
Engine클래스에서 matrix를 만들기 위해서 Database에 있는 playerList, songList가 필요합니다. Mumu객체에서 Engine객체에게 matrix메소드를 위임할때 Database인스턴스를 전달해 줍니다.
이때 받은 인스터스를 가지고 어떻게 playerList에 접근하면 좋을까요?
1번방법은 받아온 인스턴스를 가지고 playerList를 전체 가지고 와서 메소드를 실행합니다.
2번방법은 받아온 인스턴스를 가지고
playerList의 사이즈(for의 길이를 알기 위해서) findPlayer(행렬 곱을 할 Player인스턴스 찾기) 이렇게 두가지에 접근 합니다.
깔끔하기는 1번이 더 깔끔한 것 같은데, 데이터의 노출은 2번이 더 적은 것 같아서..어떤 방식이 더 좋은지 궁금합니다.
``` / * *makeMatrixPlayer *목적 : player * player matrix 생성 *필요한 메소드 : Database Class_findPlayer() index값에 위치한 player 반환
*필요한 메소드 : Player Class_comparePlayer() 두 값을 비교해서 공통된 노래 리스트 반환 *@param db 인스턴스
*/ public void makeMatrixPlayer(Database db){ //1번방식 ArrayList
for (Player player : playerList) {
ArrayList<ArrayList<Song>> matrixRow = new ArrayList<ArrayList<Song>>(); //행 생성
matrixPlayer.add(matrixRow); //행 추가
for(Player target : playerList){
ArrayList<Song> matrixColumn = player.comparePlayer(target); //행(player)과 열(player)간 공통된 노래 수 비교
matrixPlayer.get(row).add(matrixColumn); //비교한 노래 값 추가
}
row++;
}
//2번방식
int length = db.getPlayerListSize();
for(int row = 0 ; row < length ; row++ ){
ArrayList<ArrayList<Song>> matrixRow = new ArrayList<ArrayList<Song>>(); //행 생성
matrixPlayer.add(matrixRow); //행 추가
Player origin = db.findPlayer(row); //행의 Player 반환
for(int colmun = 0 ; colmun < length ; colmun ++){
Player target = db.findPlayer(colmun); //행과 비교할 열(player) 반환
ArrayList<Song> matrixColumn = origin.comparePlayer(target); //행(player)과 열(player)간 공통된 노래 수 비교
matrixPlayer.get(row).add(matrixColumn);
}
}
}```
2개의 의견 from SLiPP
보통 실 데이터베이스에서 데이터를 조회할 때는 ArrayList와 같은 형태로 직접 가져오기 때문에 첫번째를 사용해도 괜찮다고 생각한다.
하지만 지금 질문의 의도는 그게 아니라고 생각하기 때문에 1번과 2번과 같이 구현할 때의 차이점에 대해 이야기한다면 다음과 같다.
1번과 같이 ArrayList를 외부에 직접 노출하는 경우 이 ArrayList를 사용하는 곳에서 ArrayList에 엘리먼트를 추가하거나 삭제하는 것이 가능하다. 이 경우 ArrayList를 가지고 있는 Database는 자신이 가지고 있는 ArrayList에 변경이 발생했는지 알 수 있는 방법이 없다.
2번의 경우에는 ArrayList를 직접 노출하지 않고, ArrayList가 가지고 있는 Player 엘리먼트만 노출한다. 즉, 외부에서 ArrayList에 엘리먼트를 추가하거나, 삭제할 수 없다. 추가와 삭제가 필요하다면 Database에서 이 작업을 위하 메소드를 추가해야 된다. 즉, Database가 엘리먼트의 추가, 삭제를 알 수 있다. 이 경우는 외부에서 Player의 상태를 변경할 수 있다는 이슈가 있다. 따라서 Player의 인스턴스를 immutable(불변)로 만들 수만 있다면 외부에서 Database 모르게 데이터의 상태를 변경하는 일은 발생하지 않는다.
이와 같이 외부에 많은 상태 정보를 노출하는 경우 외부에서 상태를 변경할 가능성이 높아진다. 이처럼 개발하는 경우 인스턴스의 상태가 변경되었는지를 알 수 없어 버그가 발생하는 경우가 있기 때문에 가능하면 인스턴스 자신의 상태 노출을 최소화하는 것이 좋은 개발 방식이다. 그렇게 할 때 좀 더 객체 지향적인 사고를 할 수 있다.
도움이 되었기를...
@자바지기 감사합니다 !! // 정보를 어떻게 보호해야되고 ,private을 왜쓰는지 조~~금 감이 오는것같습니다 :D
의견을 남기기 위해서는 SLiPP 계정이 필요합니다.
안심하세요! 회원가입/로그인 후에도 작성하시던 내용은 안전하게 보존됩니다.
SLiPP 계정으로 로그인하세요.
또는, SNS 계정으로 로그인하세요.