2014. 4. 24. 11:29

[AWS 시작하기]

Amozon Web Services (AWS)는 온라인 어플리케이션을구축할 수 있는 종량제(pay as you go) 컴퓨팅 자원 및 서비스를 제공한다. 예를 들어, 언제라도 접속하고 설정하고, 안전하며 원하는 시점에 실행할 수 있는 물리적 서버와  비슷한 서버를 AWS에서 임대할 수 있다. 직접 소유한 물리적 서버와 AWS의 가상 서버가 다른 점은 가상 서버가 행성 규모(planet-scale)의 네트워크 상에서 AWS에 의해 관리되고 있다는 점이다.


가상 서버는 실행되는 동안만 과금되며, 최초 구매 비용 발생하지 않고, 정기적으로 지불해야 하는 관리 비용도 없다. AWS 네트워크 상에서 운영되는 데다가, 물리적 서버로는 불가능한 어플리케이션 부하 증가 시에 필요에 따라 자동으로 복수의 서버로 확장(복제)되는 기능을 제공한다.


AWS를 이용해 인터넷 어플리케이션을 구축한다는 것은 자체 발전기를 이용해 전력을 생산하기 보다 전력 회사에서 전력을 구매하는 것과 같다. 게다가, 발전기를 자체 운영하는 것과 똑같이 필요에 따라 용량을 조절할 수 있고,  사용량에 따라 비용이 발생하며, 저렴한 비용 등의 장점을 누릴 수 있다. 나아가 대규모 네트워크 운영 경험을 제공 받을 수 있게 된다.


[AWS로 무엇을 할 수 있는가?]

AWS를 이용한다면 물리적 하드웨어를 직접 운영하면서 수행할 수 있는 거의 모든 것을 누릴 수 있다. 웹 사이트, 어플리케이션, 데이터베이스, 모바일 앱, 이메일 발송, 분산시스템 데이터 분석, 컨텐츠 저장소, 그리고 가상 사설망(Virtual Private Network) 등을 구축할 수 있다. AWS 가 제공하는 다양한 서비스들은 면밀히 통합되어 있으며, 수십가지의 서비스가 제공되고 매년 새로운 서비스들이 추가되고 있다.


다음 다어그램은 AWS가 제공하는 기능들을 분류한 것이다.



개별 카테고리에는 하나 이상의 서비스가 포함되어 있다. 예를 들어 AWS는 다섯가지 데이터베이스 서비스를 제공하고 있으며 각각은 용도에 따라 최적화 되어 있다. AWS가 제공하는 다양한 서비스들을 이용해 필요에 맞는 맞춤형 솔루션을 설계할 수 있다.


[가장 먼저 살펴봐야 할 서비스들은 무엇인가?]

AWS는 다양한 서비스들을 제공하기 때문에 무엇부터 시작해야 할지 결정하기 어렵다. 가장 먼저 고려해야 하는 점은 AWS를 이용해 무엇을 할 것인가 이다. AWS의 가장 보편적으로 사용되는 기능 혹은 활용 방식들은 다음과 같다.


  • 파일 저장소
  • 웹 사이트 호스팅
  • 데이터베이스 운영
  • 어플리케이션 실행되는
  • 네트워크 구성
  • AWS 자원 관리


아마존 웹 서비스 홈페이지 자료를 참조해 작성했음을 밝힙니다. (상업적 목적은 없습니다.)

http://docs.aws.amazon.com/gettingstarted/latest/awsgsg-intro/gsg-aws-intro.html



Posted by 곽중선
2014. 4. 22. 23:32

코멘트 (Comment) 리팩토링에 대해 알아보자.

마틴 파울러는 '코드의 부족을 보충하기 위해 상세한 주석이 있는 것' 또한 나쁜 냄새라고 지적했다.


그렇다면 '코드의 부족(lack of code)'이라는 무슨 의미일까? 

작성된 코드가 '대체로 잘 동작하지만, 완벽하다고 말하기는 어렵다는 의미이다.

프로그래머가 일정에 밀려서 미치 완성하지 못한 것일 수도 있고, 정말 귀찮아서 보완하지 못한 것일 수도 있다.

아니면, 실력이 없거나... 누구나 완벽한 것이 가장 좋다고 말하지만, 어디 현실이 그러한가? 

어쩔 수 없다는 핑계와 양해를 주거니 받거니 하면서 살아가는 것이다.


하지만, 백번 양보를 해도 코드가 완벽하지 못하니 알아서 잘 쓰라고 (조심하라는 의미에서...)

주석(comment)에 설명을 붙이는 것은 당신이 가는 길에 지뢰가 있으니 알아서 피하라는 표지판과 다름이 없다.


  • 표지판을 못 볼 수도 있다. (모든 개발자가 주석을 보고 나서 함수를 가져다 쓴다는 보장은 없고,
    현실적으로 많은 이들이 주석을 읽으려 하지 않는다.
  • 표지판을 보고도 그냥 지나칠 수 있다.
    설마하는 사람도 있고, 주석을 보고도 함수(혹은 API)를 가져다 쓰는 사람은 자신에게는 아무런 책임이 없다고 생각하기도 한다.
  • 주석은 실행에 아무런 영향을 주기 때문에, 경고성 주석이 유지보수 혹은 코드 정리 과정에서 사라질 수도 있다.


결론은 프로그램에 잠재적인 오류가 있다거나, 오용(잘못된 사용) 가능성이 있다면
주석으로 문제를 영원히 덮을 수 없다는 것이다.


코딩 사례를 보고 이해해보도록 하자. 많은 실무 프로젝트에서 공통 API (common API)를 만들어 사용하게 되는데 회원 정보를 대다수의 사이트에서 '나이를 계산하는 공통 함수'를 만들어 사용한다. 나이를 계산하기 위해서는 '생년월일'을 입력 받아야 하고, 개발 편의성을 높이기 위해, 굳이 Date 타입으로 입력받지 않고 문자열로 태어난 날짜를 입력 받도록 한다. 여기서 '코드의 부족(lack of code' 문제가 자주 발생하게 된다. 공통 함수이다 보니 가져다 쓰는 곳이 많고, 오류가 발생하더라도 원인 파악이 손쉬워야 함에도 불구하고 간단한 함수라 여겨 대충 만드는 일이 많다.


아래 코드는 주석에 잘못된 입력 값이 들어왔을 경우, 적절한 예외가 발생한다는 것을 명시하였다.

만일, 공통 API를 사용하는 개발자가 주석을 읽지 않고 API를 호출하더라도 잘못된 입력 값(인자 혹은 parameter) 오류의 원인을 파악할 수 있는 '메시지'가 예외 객체에 포함되기 때문에 문제를 빨리 해결할 수 있다. 


만일, 예외처리하는 로직 없이 메소드 주석에 날짜 형식은 'yyyyMMdd'이라는 안내문구를 적어둔 경우는 '코드의 부족을 위해 상세한 주석이 있는 나쁜 냄새가 나는 코드'가 되는 것이다.


package common.util;

import java.sql.Date;

import org.joda.time.DateTime;
import org.joda.time.Years;

/**
 * 업무구분 : 공통 (cn)
 * 업 무 명 : 공통 API
 * 파 일 명 : AgeUtils.java
 * 작 성 일 : 2014-04-22
 * 설    명 : 현재 혹은 기준 일자를 기준으로 한국 나이, 만 나이를 계산하는 유틸리티 메소드들을 제공한다.
 */
public final class AgeUtils {

	private AgeUtils() {
		// This class does not provider public constructor
	}

	/**
	 * 현재 날짜를 기준으로 생년월일에서 한국식 나이를 구한다.
	 * 
	 * AgeUtils.getAge("19731201"); = 41 (현재 년도가 2013년인 경우)
	 * 
	 * @param birthDate 생년월일 (yyyyMMdd 형식)
	 * @return 현재 일자를 기준으로 계산된 한국식 나이
	 * @throws IllegalArgumentException null 혹은 잘못된 형식의 날짜를 입력한 경우 예외 발생
	 */
	public static int getAge(String birthDate) {
		return getAge(birthDate, DateUtils.getTodayString());
	}

	/**
	 * 기준일자를 기준으로 생년월일에서 한국식 나이를 구한다.
	 * 
	 * AgeUtils.getAge("19731201", "20121225"); = 40
	 * 
	 * @param birthDate 생년월일 (yyyyMMdd 형식 혹은 yyyy 형식)
	 * @param refDate 기준일자 (yyyyMMdd 형식 혹은 yyyy 형식)
	 * @return 한국식 나이
	 * @throws IllegalArgumentException null 혹은 잘못된 형식의 날짜를 입력한 경우 예외 발생
	 */
	public static int getAge(String birthDate, String refDate) {
		if (StringUtils.isEmpty(birthDate) || StringUtils.isEmpty(refDate)) {
			throw new IllegalArgumentException("birthDate or refDate parameter is empty.");
		} else if (birthDate.length() < 4 || refDate.length() < 4) {
			throw new IllegalArgumentException("birthDate or refDate parameter length is too short (must longer than 3).");
		} else if (!StringUtils.isNumeric(birthDate) || !StringUtils.isNumeric(refDate)) {
			throw new IllegalArgumentException("birthDate or refDate parameter is not numeric data.");
		}
		if (birthDate.length() == 4) {
			return Integer.parseInt(refDate) - Integer.parseInt(birthDate) + 1;
		} else {
			return getAge(DateUtils.toDate(birthDate), DateUtils.toDate(refDate));
		}
	}

	/**
	 * 생년월일과 기준 일자를 비교하여 한국식 나이를 반환한다.
	 * 
	 * Date birthDate = DateUtils.toDate("20120101");
	 * AgeUtils.getAge(birthDate, DateUtils.toDate("20120201")); = 1
	 * AgeUtils.getAge(birthDate, DateUtils.toDate("20130101")); = 2
	 * 
	 * @param birthDate 생년월일 (yyyyMMdd 형식)
	 * @param refDate 기준일자 (yyyyMMdd 형식)
	 * @return 한국식 나이
	 * @throws IllegalArgumentException null 혹은 잘못된 형식의 날짜를 입력한 경우 예외 발생
	 */
	public static int getAge(Date birthDate, Date refDate) {
		if (birthDate == null || refDate == null) {
			throw new IllegalArgumentException("Invalid argument value. birthDate = '" + birthDate + "', refDate = '" + refDate + "'");
		} else {
			return new DateTime(refDate).getYear() - new DateTime(birthDate).getYear() + 1;
		}
	}

	/**
	 * 현재 일자를 기준으로 생년월일에서 만 나이를 구한다.
	 * 
	 * AgeUtils.getRealAge("19731201"); = 39 (현재 년도가 2013년인 경우)
	 * 
	 * @param birthDate 생년월일 (yyyyMMdd 형식)
	 * @return 만 나이
	 * @throws IllegalArgumentException null 혹은 잘못된 형식의 날짜를 입력한 경우 예외 발생
	 */
	public static int getRealAge(String birthDate) {
		return getRealAge(birthDate, DateUtils.getTodayString());

	}

	/**
	 * 생년월일과 기준 일자를 비교하여 만 나이를 계산한다.
	 * 
	 * AgeUtils.getRealAge("19731201", "20121125"); = 38
	 * AgeUtils.getRealAge("19731201", "20121225"); = 39
	 * 
	 * @param birthDate 생년월일 (yyyyMMdd 형식)
	 * @param refDate 기준일자 (yyyMMdd 형식)
	 * @return 만 나이
	 * @throws IllegalArgumentException null 혹은 잘못된 형식의 날짜를 입력한 경우 예외 발생
	 */
	public static int getRealAge(String birthDate, String refDate) {
		return getRealAge(DateUtils.toDate(birthDate), DateUtils.toDate(refDate));
	}

	/**
	 * 생년월일과 기준 일자를 비교하여 만 나이를 계산한다.
	 * 
	 * Date birthDate = DateUtils.toDate("20120101");
	 * AgeUtils.getRealAge(birthDate, DateUtils.toDate("20120201")); = 0
	 * AgeUtils.getRealAge(birthDate, DateUtils.toDate("20130101")); = 1
	 * 
	 * @param birthDate 생년월일 (Date 타입)
	 * @param refDate 기준일자 (Date 타입)
	 * @return 만 나이
	 * @throws IllegalArgumentException null 혹은 잘못된 형식의 날짜를 입력한 경우 예외 발생
	 */
	public static int getRealAge(Date birthDate, Date refDate) {
		if (birthDate == null || refDate == null) {
			throw new IllegalArgumentException("Invalid argument value. birthDate = '" + birthDate + "', refDate = '" + refDate + "'");
		} else {
			return Years.yearsBetween(new DateTime(birthDate), new DateTime(refDate)).getYears();
		}
	}
}



AgeUtils.java


Posted by 곽중선
2014. 4. 22. 22:50

예전에 Effective Java 학습한 내용을 정리해서 올립니다.

(내용은 차차 추가될 예정입니다.)



Effective Java 1 and 2.ppt


Posted by 곽중선
2014. 4. 22. 21:37

꽤 오래전에 써둔 객체지향 개념 관련 문서 올려봅니다.



Welcome to object world.doc


Posted by 곽중선
2014. 4. 22. 15:59

[EC2 (Elastic Compute Cloud)]

아마존 데이터센터 내에서 수행되는 Linux/UNIX 그리고 Windows 서버 인스턴스를 구동(launch)하고 관리(manage)할 수 있는 웹 서비스. EC는 사용자들이 자신만의(own) 어플리케이션을 실행할 수 있는 가상 컴퓨터를 임대할 수 있도록 한다. EC2는 "AMI(Amozon Machine Image)로 부터 부팅할 수 있는 가상 머신(virtual machine)" (Amazon은 인스턴스라고 부른다)에서 동작하는 확장 가능하고 필요한 모든 소프트웨어를 포함한 어플리케이션의 배포를 웹 서비스 상에서 가능하게 한다. 사용자는 서버 잉ㄴ스턴스를 필요할 때마다 생성하고, 실행하고, 종료할 수 있으며서 "elastic" 이라는 용어에서 알 수 있듯이 실제 서버가 실행된 시간만큼 비용을 지불한다.


http://aws.amazon.com/ko/ec2

http://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud


[EBS Elastic Block Store)]

블록 수준 저장 볼륨(block level storage volumes)을 제공하는 EC2 인스턴스와 어울려 활용되는 서비스.


http://aws.amazon.com/ko/ebs


[S3 (Simple Storage Service)]

S3는 인터넷을 위한 저장소이며, 개발자가 웹 규모(web-scale) 컴퓨팅을 손쉽게 수행할 수 있도록 설계되었다. S3는 아무 장소, 아무 시간에 파일 용량에 관계 없이 데이터를 웹 상에 업로드 하거나 다운로드할 수 있는 간편한 웹 서비스 인터페이스를 제공한다. S3는 개발자에게 고확장성(high scalable), 신뢰성(reliable), 고속(fast), 저렴한(inexpensive) 데이터 저장 인프라(infrastrucure)를 제공한다.  


http://aws.amazon.com/ko/s3


[AMI (Amazon Machine Image)]

Amozon Elastic Block Store에 암호화(encrypted)되어 저장되어 있는 machine image 이다. AMI 는 컴퓨터 루트 드라이브(root drive)의 상태를 틀(template)에 고정시킨 것이라고 할 수 있다. AMI 는 운영체제(OS)를 담고 있을 뿐만 아니라, 각종 소프트웨어와 데이터베이스 서버, 미들웨어, 웹 서버 등의 어플리케이션 계층을 포함할 수 있다.


http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html


[ELB (Elastic Load Balancing)]

둘 이상의 EC2 인스턴스 간에 수신 트래픽(incoming traffic)을 분산시켜 어플리케이션 가용량(availability)를 증가 시켜주는 웹 서비스.


http://aws.amazon.com/elasticloadbalancing


[Route 53]

Amazon Route 53은 고가용성(high available) 및 확장성 있는 DNS(Domain Name System) 웹 서비스이다.


http://aws.amazon.com/ko/documentation/route53/


[CloudWatch]


[CloudFront]


[Edge Server]


[Auto scaling]


[Simple DB]


[DynoDB]


[RDS (Relational Database Service)]


[ElastiCache]


[SQS (Simple Queue Service)]


[CloudFormation]



Posted by 곽중선
2014. 4. 22. 15:23

On-premise software

On-premises 소프트웨어 (때로는 "on-prem" 이라는 약어로 표현)는 소프트웨어를 사용하는 사람 혹은 기관이 위치한 장소(혹은 빌딩)의 하드웨어에 설치되고 실행되는 것을 말한다. 인터넷 상에 위치한 server farm 혹은 클라우드와 같은 원격지에 존재하는 소프트웨어와 반대되는 개념이다. [Wikipedia 참조]

Posted by 곽중선
2014. 4. 22. 13:27

SPOF (Single Point Of Failure)

load balancer,web server, database 등의 시스템을 구성하는 요소 중에서 이중화 구성이 되지 않아 장애가 발생하면 시스템 전체에 영향을 주는 요소를 말한다. 단일 고장점이라고도 표현함. 예를 들어 웹 서버가 이중화 되어 있지 않아 웹 서버가 중단되면 서비스 전체가 중단되므로, 이 때 웹 서버가 SPOF가 된다.

 

Posted by 곽중선
2014. 4. 22. 13:23

NAT (Network Address Translation)

private network 내의 서버를 에서 public network에 있는 서버에 접근할 때, private network로 통신하는 IP address 와 public network로 통한하는 IP address 를 상호 변환하는 것으로, public network의 IP address 하나로 여러 개의 private IP addresss를 운용할 수 있도록 하는 기술이다.


NFS (Network File System)

네트워크를 통해 파일을 공유하기 위한 시스템. 공유 파일을 저장하는 NFS 서버와 원격으로 파일에 접근하는 NFS 클라이언트로 구성된다. 여러 대의 NFS 클라이언트에서 한 대의 NFS 서버에 접근할 수 있어 여러 대의 클라이언트에서 파일을 공유할 수 있다.


Proxy / Reverse Proxy

조직이나 기업의 네트워크에서 외부 네트워크에 접속할 경우, 내부의 클라이언트가 직접 외부와 통신하지 못하도록 하고 클라이언트를 대신하여 외부의 서버와 통신하는 서버를 proxy 라고 한다. 반대로 외부에서 들어오는 통신을 받아 내부 서버의 접속을 대신하는 하는 서버를 revservse proxy 라고 한다. 접속 장소의 정확한 위치를 감추거나, 통신 데이터를 필터링(filtering)할 수 있는 잇점이 있다.

Posted by 곽중선
2014. 4. 20. 23:32
중복된 코드를 리팩토링(refactoring)하는 방법을 알아보자. 
아래 예제 소스는 자바에서 '정수형 연산'과 '실수형 연산' 처리의 수행 시간 차이를 대략적으로 알아보기 위해 작성되었다.
잘 살펴보면 중복된 코드가 눈에 띈다. 수행 시간(elapsed time)을 계산하는 로직이 2번에 걸쳐 반복되어 코딩되어 있다.
   
import java.util.Calendar;

public class DuplicatedCodes {

	private static long timeInMillis;

	/**
	 * 정수형 및 실수형 연산 처리 속도를 비교하는 테스트 프로그램
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		long elapsedTime;

		timeInMillis = Calendar.getInstance().getTimeInMillis();
		int intSum = 0;
		// 정수형 변수를 100만번 더한다.
		for (int i = 0; i < 1000000; i++) {
			intSum += 100;
		}
		elapsedTime = Calendar.getInstance().getTimeInMillis() - timeInMillis;
		System.out.println("정수형 : " + elapsedTime + "밀리초");

		timeInMillis = Calendar.getInstance().getTimeInMillis();
		float floatSum = 0;
		// 실수형 변수를 100만번 더한다.
		for (int i = 0; i < 1000000; i++) {
			floatSum += 100.0;
		}
		elapsedTime = Calendar.getInstance().getTimeInMillis() - timeInMillis;
		System.out.println("실수형 : " + elapsedTime + "밀리초");
	}
}


눈에 잘 띄는 중복 코드는 아래와 같다.

elapsedTime = Calendar.getInstance().getTimeInMillis() - timeInMillis;


리팩토링을 실시하기 전에 '중복된 코드를 리팩토링 해야 하는 이유는 무엇인가?' 라는 질문에 답해보자.


  • 재사용성(reuseablity)가 떨어지기 때문이며, 동일한 코드를 반복해서 사용하는 것은 노동력이 많이 소모된다.
  • 중복된 코드는 버그가 발견되거나 수정 사항이 발생할 때마다 고쳐야 하는 노력이 많이 든다.
    (중복된 횟수 만큼의 수정 작업을 반복해야 한다.)
  • 여러 위치에 흩어져 있기 때문에 로직(logic)에 대한 문서화 혹은 설명을 작성하기 이렵다.
  • 중복된 상태로 그대로 두었다가 누군가 흩어진 중복 코드 중에서 한 곳만 고쳐야 할 경우,
    원래의 의도와 달리 처음에는 같은 기능을 하던 코드들이 다른 방식으로 동작하게 되는 문제가 발생할 수 있다.


중복된 코드를 리팩토링하는 것은 다음과 같은 장점을 가지고 있다.


  • 다양한 리팩토링 기법 중에서 가장 우선순위를 높여서 해야 한다. (아무리 바쁘고  시간이 없더라도...)
  • 리팩토링 기법 중에서 가장 효과가 좋다. (중복 코드 제거를 안한 코드의 유지보수, 장애 처리 비용은 상상을 초월한다.)
  • 설계를 개선하고, 코드의 품질을 높이는 가장 빠르고, 확실한 방법이다. (개발자의 레벨이 상승한다.)
  • 중복된 코드가 제거된 코드는 문서화 하기 용이하고, 코드 가독성(readability)가 향상될 가능성이 높다.


반면에 다음과 같은 단점도 있다. (과유불급, 지나치면 모자르니만 못하다.)


  • 자칫하면 코드의 복잡도가 높아져 코드를 이해 하기 어렵게 된다.
  • 중복 코드를 방지하는 과정에서 미약하나마 성능 저하가 발생할 수 있다.
  • 지나치게 '중복 방지'에 집착하다보면, 제한된 시간과 노력을 낭비할 가능성이 있다.
    (중복 코드가 많지 않거나, 아주 단순한 코드임에도 리팩토링을 하려고 애쓸 필요는 없다.)


중복된 코드를 제거하는 방법은 반복적인 코드 블럭을 함수(function or method)로 변경하는 것이다.

앞서 제시한 예제에서 중복된 코드를 리팩토링한 결과는 다음과 같다.   

import java.util.Calendar;

public class DuplicatedCodes {

	private static long timeInMillis;

	/**
	 * 정수형 및 실수형 연산 처리 속도를 비교하는 테스트 프로그램
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		timeInMillis = Calendar.getInstance().getTimeInMillis();
		int intSum = 0;
		// 정수형 변수를 100만번 더한다.
		for (int i = 0; i < 1000000; i++) {
			intSum += 100;
		}
		System.out.println("정수형 : " + calcElapseTime() + "밀리초");

		float floatSum = 0;
		// 실수형 변수를 100만번 더한다.
		for (int i = 0; i < 1000000; i++) {
			floatSum += 100.0;
		}
		System.out.println("실수형 : " + calcElapseTime() + "밀리초");
	}

	/**
	 * 경과 시간을 계산한다.
	 * 
	 * @return 경과된 시간을 밀리초(millseconds) 단위로 반환한다.
	 */
	private static long calcElapseTime() {
		long currentTimeMillis = Calendar.getInstance().getTimeInMillis();
		long elapsedTime = currentTimeMillis - timeInMillis;
		timeInMillis = currentTimeMillis;

		return elapsedTime;
	}

}


위와 같이 코드를 변경했을 때, 어떤 효과를 기대할 수 있을까? 혹은 무엇이 좋아진 것일까?


  • 요건 혹은 기능이 변경되었을 때, 손쉽게 고칠 수 있다. (예를 들어, 수행 시간을 초 단위로 출력하게끔 바꾸어야 하는 경우)
  • 중복된 코드 블록을 함수로 모듈화하면서, 코드 길이가 짧아진다.
  • 함수 명칭을 통해 기능을 파악할 수 있으므로, 로직을 파악하기 쉬워지고,
    함수에 주석을 추가하는 방식으로 문서화를 할 수 있다.

DuplicatedCodes.java



Posted by 곽중선
2014. 4. 20. 22:02

마틴 파울러가 언급한 22가지 코드의 악취(Bad Smells in Code)


 중복된 코드 (Duplicated Code)

 코드가 여기저기 겹쳐 있다.

 너무 긴 메소드  (Long Method) 메소드가 너무 길다.
 거대한 클래스 (Large Class) 클래스의 파일이나 메소드가 너무 많다. 
 너무 많은 인수 (Long Parameter List) 메소드에 전달하는 인수의 수가 너무 많다.

 변경의 발산 (Divergent Change)

 사양변경이 발생한 경우 수정할 곳이 여기저기 흩어져 있다.
 변경의 분산 (Shotgun Surgery)

 어떤 클래스를 수정하면 다른 클래스도 수정하지 않으면 안 된다. 

 속성, 조작의 부적절한 관계 (Feature Envy)

 언제나 다른 클래스의 속성을 건드리고 있다.

 데이터 덩어리 (Data Clump)

 정리해서 다룰 수밖에 없는 여러 개의 데이터가 하나의 클래스에 정리되어 있지 않다. 

 기본 데이터형의 집착 (Primitive Obsession)

 클래스를 만들지 않고 int같은 기본 데이터형만을 사용한다.

 switch문 (Switch Statements)

 switch문이나 if문을 사용하여 동작을 분할하고 있다.

 평행 상속 구조 (Parallel Inheritance Hierarchies)

 서브클래스를 만들면 클래스 계층에 따로 서브클래스를 만들어야 한다. 

 게으름뱅이 클래스 (Lazy Class)

 클래스가 별로 하는 일이 없다. 

 추측성 일반화 (Speculative Generality)

 언젠가 이렇게 확장하겠지 하고 기대하는 지나친 일반화 

 일시적 속성 (Temporary Field)

 일시적으로 사용할 필드가 있다.

 메시지의 연쇄 (Message Chains)

 메소드가 호출하는 연쇄가 너무 많다.

 중개자 (Middle Man)

 위양(권리를 위임)하고 자신이 하는 일은 없는 클래스가 있다. 
 부적절한 관계 (Inappropriate Intimacy)

 필요 없는 쌍방향 링크가 걸려 있거나 IS-A 관계가 아니면서 상속을 사용한다

 클래스의 인터페이스 불일치
 (Alternative Classes with Different Interface)
 API가 부적절하다.
 미숙한 클래스 라이브러리
 (Incomplete Library Class)
 기존의 클래스라이브러리가 사용하기 힘들다.

 데이터 클래스 (Data Class)

 필드와 getter 메소드와 setter 메소드만 가지고 있는 클래스가 있다.
 상속거부 (Refused Bequest) 상속하고 있는 메소드면서 그것을 호출하면 문제가 발생한다.

 코멘트 (Comment)

 코드의 부족을 보충하기 위해 상세한 코멘트가 있다 


Posted by 곽중선