The Debugging Chronicles : "코드의 미학"

결합도와 응집도 본문

JAVA/자바 수업 내용

결합도와 응집도

sweetseonah1004 2024. 7. 17. 16:39

 

 프로그래머의 최고의 목표

유지보수 용이한 코드를 작성하는 것

이를 가능하게 하는 두가지 코딩 방법이 있으니... 바로...

 

1)결합도가 낮은 코드 

결합도가 낮은 코드는 조각 조각 분리가 잘되어 있는 코드이다.

즉 모듈화(컴포넌트화, 함수화)가 잘되어있다는 뜻이다.

이는

겹치는 부분이 적고

1개의 변경사항이 발생했을 때, 코드 1곳만 변경가능하게 한다.

ex) 하드코딩 제거하기, 변수화(상수화),...

 

 

2)응집도가 높은 코드

하나의 코드 영역(파일,블록)에 하나의 로직만 담겨있다.

update->update / create -> insert 

하나의 로직이 여기저기에 퍼져있으면 안된다.

조회수 증가, 내용변경, 제목변경 - > update() 한곳 한자리!

 

>>결합도,응집도가 낮은 코드

package model;

import java.util.ArrayList;

// CRUD
// 비즈니스 메서드 , 핵심 관심, 핵심 로직 떄문에 있는 것이다.
public class BoardDAO {
	private ArrayList<BoardDTO> datas;
	public BoardDAO() {
		this.datas = new ArrayList<BoardDTO>();
	
		//데이터 샘플링
		BoardDTO data = new BoardDTO();
		data.setNum(101);
		data.setTitle("샘플");
		data.setContent("sdf");
		data.setCnt(0);
		this.datas.add(data);
	}
	
	public boolean insert(int num,String title, String content) {// 제목,내용
		BoardDTO data =new BoardDTO();
		data.setNum(num);
		data.setTitle(title);
		data.setContent(content);
		data.setCnt(0);
		datas.add(data);
		return true;
	}
	public boolean update(int num) {
		for(BoardDTO data:this.datas) {
			if(data.getNum()==num) {
				data.setCnt(data.getCnt()+1); //현재방문자수== 기존에 가지고 있던 수+1 ; 
				return true;
			}
		}
		return false;
	}
	// 메뉴 4  내용 변경 업데이트
	public boolean update(BoardDTO data) {
		for(BoardDTO b:datas) {
			if(data.getNum() == b.getNum()) {
				 if(data.getContent() == null) {
					 System.out.println(data);
					  b.setTitle(data.getTitle());
					  return true;
				 }else {
					 b.setContent(data.getContent());
					 return true;
				 }
			}
		}		
		return false;
	}
	// 메뉴 5번 제목 변경 업데이트
	public boolean update(String title, int num) {
		for(BoardDTO data:this.datas) {
			if(data.getNum()==num) {
				data.setTitle(title);;
				return true;
			}
		}
		return false;
	}
	public boolean delete(int num) {
		for(int i = 0 ; i <datas.size(); i++) {
			if(datas.get(i).getNum() == num) {
				datas.remove(i);
				return true;
			}
		}
		return false;
	}
	public ArrayList<BoardDTO> selectAll(){
		return this.datas;
	}
	public ArrayList<BoardDTO> selectAll(String searchTitle){
		System.out.println("selectAll searchTitle 시작");
		ArrayList<BoardDTO> datas = new ArrayList<BoardDTO>();
		
		for(BoardDTO data:this.datas) {
			if(data.getTitle().contains(searchTitle)) {
				System.out.println("selectAll searchTitle 중간");
				datas.add(data);
			}
		}
		System.out.println("selectAll searchTitle 끝");
		return datas;
		
	}
	public BoardDTO selectOne(int num){
		for(BoardDTO data:this.datas) {
			if(data.getNum()==num) {
				return data;
			}
		}
		return null;
	}
}

 

>> 결합도 낮추기

만약에  boardDTO에 Private String writer가 추가 되었다고 하자,

그럼 모든 파일에 wirter을 추가하러 다녀야한다.

따라서 결합도를 높이기 위해 CRUD 인자를 DTO로 통합한다

package model;

import java.util.ArrayList;

// CRUD
// 비즈니스 메서드 , 핵심 관심, 핵심 로직 떄문에 있는 것이다.
public class BoardDAO {
	private ArrayList<BoardDTO> datas;
	public BoardDAO() {
		this.datas = new ArrayList<BoardDTO>();
	
		//데이터 샘플링
		BoardDTO data = new BoardDTO();
		data.setNum(101);
		data.setTitle("샘플");
		data.setContent("sdf");
		data.setCnt(0);
		this.datas.add(data);
	}
	
	public boolean insert(BoardDTO boardDTO){// 제목,내용
		BoardDTO data =new BoardDTO();
		data.setNum(boardDTO.getNum());
		data.setTitle(boardDTO.getTitle());
		data.setContent(boardDTO.getContent());
		data.setCnt(0);
		datas.add(data);
		return true;
	}
	public boolean update(BoardDTO boardDTO) {
		for(BoardDTO data:this.datas) {
			if(data.getNum()==boardDTO.getNum()) {
				data.setCnt(boardDTO.getCnt()+1); //현재방문자수== 기존에 가지고 있던 수+1 ; 
				return true;
			}
		}
		return false;
	}
	// 메뉴 4  내용 변경 업데이트
	public boolean update(BoardDTO boardDTO) {
		for(BoardDTO data:datas) {
			if(data.getNum() == boardDTO.getNum()) {
				 if(data.getContent() == null) {
					 System.out.println(data);
					  data.setTitle(boardDTO.getTitle());
					  return true;
				 }else {
					 data.setContent(boardDTO.getContent());
					 return true;
				 }
			}
		}		
		return false;
	}
	// 메뉴 5번 제목 변경 업데이트
	public boolean update(BoardDTO boardDTO) {
		BoardDTO data =new BoardDTO();
		for(BoardDTO data:this.datas) {
			if(data.getNum()== boardDTO.getNum()) {
				data.setTitle(boardDTO.getTitle());
				return true;
			}
		}
		return false;
	}
	public boolean delete(BoardDTO boardDTO) {
		BoardDTO data =new BoardDTO();
		data.setNum(boardDTO.getNum());
		for(int i = 0 ; i <datas.size(); i++) {
			if(datas.get(i).getNum() == boardDTO.getNum()) {
				datas.remove(i);
				return true;
			}
		}
		return false;
	}
	public ArrayList<BoardDTO> selectAll(){
		return this.datas;
	}
	public ArrayList<BoardDTO> selectAll(BoardDTO boardDTO){
		System.out.println("selectAll searchTitle 시작");
		ArrayList<BoardDTO> datas = new ArrayList<BoardDTO>();
		
		for(BoardDTO data:this.datas) {
			if(data.getTitle().contains(boardDTO.getTitle())) {
				System.out.println("selectAll searchTitle 중간");
				datas.add(data);
			}
		}
		System.out.println("selectAll searchTitle 끝");
		return datas;
		
	}
	public BoardDTO selectOne(BoardDTO boardDTO){
		for(BoardDTO b:this.datas) {
			if(data.getNum()==boardDTO.getNum()) {
				return data;
			}
		}
		return null;
	}
}

 

>>> 응집력을 높이기

문제가 발생한다. update에서 오류가 난다. 조회수 증가, 내용변경, 제목변경이  update() 한곳 한자리에 모여 있어야한다.

먼저 DTO에 condition 속성이필요하다. 이는  개발자를 위한 코드를 선언하는 것이다.이는 조건 컨트롤를 가능한다.

private String condition;
public String getCondition() {
    return condition;
}
public void setCondition(String condition) {
    this.condition = condition;
}

 

그리고 DAO 에서 else if -if문을 선언해 주어 조건에 따라 분수되도록 한다.

이때 조건 안에 영어 대문자로 일치하는 문자일때 해당 조건이 나오도록 해준다. 

public boolean update(BoardDTO boardDTO) {
    if(boardDTO.getCondition().equals("VIEW")) {
        for(BoardDTO data:this.datas) {
            if(data.getNum() == boardDTO.getNum()) {
                data.setCnt(data.getCnt()+1); // 현재방문자수+1
                return true;
            }
        }
        return false;
    }
    else if(boardDTO.getCondition().equals("CONTENT")) {
        for(BoardDTO data:this.datas) {
            if(data.getNum() == boardDTO.getNum()) {
                data.setContent(boardDTO.getContent());
                return true;
            }
        }
        return false;
    }
    else if(boardDTO.getCondition().equals("TITLE")) {
        for(BoardDTO data:this.datas) {
            if(data.getNum() == boardDTO.getNum()) {
                data.setTitle(boardDTO.getTitle());
                return true;
            }
        }
        return false;
    }
    return false;
}

 

그리고 컨트롤러에서 해당 조건의 문자를 넣어 주어서 각 각의 조건이 성립할 수 있도록한다.

주의 할 점은  1기능당 1개의 객체가 생성되어야한다는 점이다.

else if(action==2) { // 전체목록출력
    BoardDTO boardDTO=new BoardDTO();
    boardDTO.setCondition("ALL");
    view.printBoardList(model.selectAll(boardDTO));
}
else if(action==3) { // 글 1개 검색 == 글 선택
    int num=view.inputNum();

    BoardDTO boardDTO=new BoardDTO();
    boardDTO.setNum(num);
    BoardDTO data = model.selectOne(boardDTO);
    boardDTO.setCondition("VIEW"); // 방문즉시 조회수++
    boolean flag=model.update(boardDTO);
    if(!flag) {
        view.printFalse();
        continue;
    }

    if(data!=null) {
        view.printBoardData(data);
    }
    else {
        view.printFalse();
    }
}
else if(action==4) { // 내용 변경
    int num=view.inputNum();
    String content=view.inputContent();

    BoardDTO boardDTO=new BoardDTO();
    boardDTO.setNum(num);
    boardDTO.setContent(content);
    boardDTO.setCondition("CONTENT");
    boolean flag=model.update(boardDTO);
    if(flag) {
        view.printTrue();
    }
    else {
        view.printFalse();
    }
}