최근에 객체지향프로그램인 JAVA의 초기 입문서인 Head First Java를 모두 읽었습니다. 그런데 읽으면서 아주 흥미로운 사실 하나를 읽게되었고 깨닫게 되었습니다. 바로 객체지향에 있어서 어떤 프로그램을 작성하는데 세포단위(즉 더 이상 쪼갤 수 없는 기능이 상실되지 안는 최소한의 단위)로 쪼개어 설계하고 기능을 만들어야 한다는 점 이었습니다.


물론 이런 식의 글은 누군가는 썼을 것입니다. 사실 고찰이라는 제목을 썼지만, 아주 개똥철학일 수 있습니다. 누군가에게 나의 대단함을 내보이려기 보다는 그냥 내 생각을 정리함으로 조금더 확실한 학습을 유도하려는 스스로에대한 글인 것입니다.


돌아 와서 세포단위로 쪼개어 설계하고 기능을 구현한다는 것은 다음을 예를 들어 설명하고 싶습니다.


세포단위 기능구현


예를들어 자바에서는 외부의 파일을 읽어 드리거나 외부 파일을 만들거나 파일에 내용을 기제할 때, InputStream 또는 OutputStream과 같은 객체를 다른 객체와 Chain하여 쓰고 있습니다. 왜 굳이 Stream과 특정 객체를 체인하여 사용할까요?? 그것은 Stream에서 하는일과 각 객체 File 또는 FileWriter에서 하는 일을 불리함으로서 File 또는 FileWriter가 아닌 다른 객체 또는 다른 일(예를 들어서 Stream형태로 외부의 컴퓨터와 통신을 하게 될 때)을 하게 될 때 쉽게 변경 또는 확장하는 것이 쉽기 때문입니다.


이와 같이 객체지향적으로 프로그램을 하려면 최소단위로 그 기능을 쪼개는 시도와 고민을 많이 해야 할듯 하다는 것이 결론입니다. 물론 이 과정에서 List와 ArrayList와 같은 관계가 생길 수도 있습니다. 즉, 인터페이스와 추상클래스와 같은 다형성의 활용이 필요하게 될 수도 있다는 것입니다. 그렇기 때문에 다형성(Polymorphism)을 알아야 하며, 중요하고 중점적으로 파고들어야 하는 핵심중의 핵심이라고 말하고 싶습니다(핵심이다보니 아주 어렵습니다. 하지만 꼭 잘이해를 해야만 하는 부분임은 확실합니다).


세포단위 기능구현에서 주의 할 점


프로그램을 작성하는데 있어서 세포단위로 생각한다는 것은 아주 중요하지만, 주의 할 점이 많다고 생각합니다.


1.세포로서의 생명력(?)이 있어야 합니다.

2.증식 또는 배양을 통하여 또 다른 종으로서 사용할 수 있게해야합니다.


위의 두 가지 규칙은 반드시 존재해야만 하는 기능이라고 필자 스스로는 생각합니다. 이유는 간단합니다. 하나하나 풀어보자면 필자가 "세포단위"라고 말할 때 "세포"라는 단어를 굳이 선택한 이유는 세포라는 것은 최소한이긴 하지만 생명력이 있다는 것을 말하고 싶어서 였습니다. 프로그램에서 생명력이란 하나의 움직임 즉 기능이라고 할 수 있습니다. 가장 기초가 되는 기능 그 것이 바로 "세포단위" 기능 구현인 것입니다.


예를들자면 자바에서 String은 하나의 클래스입니다. String클래스는 그 하위에 많은 메소드들을 가지고 있는데, 이 것이 String클래스를 정의하는 최소한의 기능들입니다. 이 기능들을 활용하거나 확장하여 다른 많은 작업들을 할 수 있습니다. 이 String 클래스에서 구현되어있는 최소한의 기능들은 분리되거나 한다면 그 생명력은 String클래스 하나만으로는 존재할 수 없는 즉 생명력이 없는(다른 클래스가 있어야 기능이 되거나 하는) 클래스가 될 것입니다. 물론 인터페이스나 추상클래스와 같은 것 들은 생명력이 없는 것 아니냐는 질문을 할 수 있지만 그러한 인터페이스나 추상클래스 조차도 어떤 객체에 사용되면 오버라이드가 되지 않는 한 확장 또는 구현(Implements)선언 만으로 구현 되는 기능들이 존재합니다. 차라리 생명력이 있는 하나의 클래스를 만들기 전에 인터페이스나 추상클래스같은 것들을 만들어서 파생적으로 세포로서 생명력이 있는 클래스를 만든다면 다형성의 좋은 예로서 활용될 것입니다.


마지막으로 "증식 또는 배양을 통하여 또 다른 종으로서 사용할 수 있게해야합니다."는 주의 사항은 내가 만든 클래스를 누군가 확장하거나 재사용이 가능 하도록 만들어야 한다는 것입니다. 바로 위에서 설명했듯이 인터페이스나 추상클래스와 같은 녀석들은 자체적으로 존재할 수 없습니다. Head First Java에서는 추상클래스를 다음과 같이 예를 들었습니다.


동물에는 개과 고양이과와 같은 식의 종의 분류들이 있습니다. 이 종의 분류는 실제하기는 하지만 종의 분류자체가 하나의 동물은 아닙니다. 이와 같이 추상 클래스는 다형성에서 상속과 관련하여 하나의 종의 분류와 같이 사용할 수는 있지만, 그것 자체로서는 하나의 객체가 될 수 없는 것이어야 한다고 말합니다.


인터페이스도 이와 비슷합니다. 다중상속을 허용하고 있지 않은 자바에서 다중상속과 비슷한 역활을 하는 것이 바로 이 인터페이스입니다. 인터페이스는 다음과같이 설명합니다. 상속관계와 무관하게 어떤 객체가 확장성을 위하여 가지고 있어야 하는 특성(또는 하는 일)이 필요할 때 인터페이스를 만들고 이를 구현합니다.


위에 밑줄 친 두 개의 예문은 좋은 예시가 되어 주리라 생각합니다. 어떤 객체를 만들기 앞서 그 객체들의 고통관심사나 공통분모를 찾아 내어서 하나의 추상클래스나 인터페이스화 하는 것 이것은 후에 내 클래스가 누군가에 의해서 확장되는 데에 많은 영향을 줄 것이라고 생각합니다.


마치며...


필자는 최근에 2개의 프로그램을 만들어 보았습니다. 하나는 TelegramSpliter(SVN 주소입니다. 받아서 확장하실 분은 메일 주시거나 댓글로 의사표현을 해주시면 함께 발전해 나갈 수 있었으면 하는 바램입니다)로 전문을 받아서 사용자가 입력해준 전문 길이로 전문을 나누고 사용자가 입력해준 클래스로 자동으로 Wrapping해주는 프로그램을 만들어 보았고, 또 하나는 전문을 가지고 오는 프로그램(각가지 방식-FTP, HTTP, SSH등-으로 통신하는)을 만들어 보았습니다. 이 때 Head First Java에서 배운 내용으 가지고 여러가지 활용을 해보면서 사용해 보았습니다. 앞으로 내공을 더 쌓아서 객체지향 프로그램에서 스프링이나 스트러츠를 만들었던 분들과 같이 되고 싶은 것이 내 바램입니다.

Posted by gofly

댓글을 달아 주세요

먼저 이 글을 Head First Java에서 배운 내용을 잊지않기 위해서 정리차원에서 제가 적어두는 것입니다.
오해없으시길 바랍니다.


자바는 어떤식으로 돌아갈까요?


처음 고려 사항은 애플리케이션 하나를 만들어서 여러 친구들이 가지고 있는 다양한 장치에 보낼 파티 초대장을  만드는 방법입니다.

1.소스->2.컴파일러->3.결과물->4.각 기계(Device)의 가상머신

1.소스: 소스를 만들되 문법을 지켜야 함
2.컴파일러: 소스 코드를 컴파일 처리한다. 이 때 오류가 없는지 체크하고, 통과한 경우에만 최종 결과를 만들어 줍니다.
3.결과물: 소스를 컴파일 하면 바이트코드(Bytecode)라는 코딩된 문서를 만들어 줌. 이것이 기계에 실행명령을 내림.
4.가상머신: 각 기계마다 소프트웨어 자바가상머신(J.V.M)이 있어 3번 결과물을 가상머신에서 실행 시키게 됩니다.

 
 

1.소스: *.java로 된 파일
2.컴파일러: 커맨드 창에 "%javac *.java "와 같이 javac를 실행시켜 *.java파일을 컴파일 합니다.
3.결과물: *.java파일이 컴파일 되면 바이트코드가 담긴 *.class파일이 생성됩니다.
4.가상머신: 커맨드 창에서 "%java *.class"를 실행시키면 *.class파일의 바이트코드를 JVM에서 실행한다. 

뭐 대충 여기까지가 자바의 구동원리 입니다.

아래는 자바의 버전별 클래스 포함의 변천사를 간단히 도표화 한 것입니다.

간단히 정리해 본 자바의 역사

간단히 정리해 본 자바의 역사




자바는 예전 C와 같이 프로그래머가 필요한 부분을 일일이 구현할 필요가 없이, 제공되는 클래스(또는 API)를 통하여 간단하게 호출하여 사용하기만 하면 됩니다. 이 것이 프로그래머들에게 아주 매력적인 요소중에 하나죠.

*Head First Java의 참 재미있는 부분은 가끔 나오는 QnA입니다.

Q: 위에 있는 표에 보니까 자바 2랑 자바 5.0은 있는데, 자바 3하고 자바 4는 어디 있어요? 그리고 자바 5.0이라고 나와 있는데, 자바 2는 왜 자바 2.0이라고 안쓰죠?

A: 마케팅의 세계란 정말 심오하죠... 자바 버전이 1.1에서 1.2로 올라갔을 때, 바뀐 것이 정말 많았어요. 그러다 보니 마케팅 팀에서 아예 이름을 새로 정해야 되겠다는 생각에 "자바 2"라는 이름을 붙였죠. 실제 자바 버전은 1.2였는데도 말예요. 버전 1.3하고 1.4는 계속 자바2로 간주되었습니다. 자바 3나 4 같은 건 없었죠. 자바 1.5가 나올 때도 정말 많은 변화가 있었습니다. 그래서 마케팅 팀에서는 (개발자들도 대부분 동의했죠) 새로운 이름이 필요하다는 생각에 어떤 이름을 쓸까 고민을 했습니다. 사실 숫자 상으로 볼 때 "3"이 와야 했는데, 자바 1.5를 "자바 3"이라고 부르려니 오히려 더 혼란 스러울 것 같다는 생각이 들어서 그냥 버전 "1.5"의 "5"에 맞춰서 "자바 5.0"이라고 부르기로 했습니다.

그래서 오리지널 자바는 버전 1.02(처음으로 공식 릴리스된 버전)부터 1.1까지는 "자바"였습니다. 버전 1.2, 1.3, 1.4는 "자바 2"였죠. 그리고 버전 1.5부터는 "자바5.0"이라고 부릅니다. 하지만 종종 (.0을 빼고) "자바 5"라고 부르기도 하고, 또는 (코드명을 따라서) "타이거"라고 부르기도 합니다. 다음 릴리즈에 어떤 이름이 붙을지는 저희도 잘 모르겠네요.


*개인적으로 저는 이런 비하인드 스토리를 알게 되면 뭔가 재미가 느껴질 까?? ㅎㅎㅎㅎ


자바 코드의 구조


자바코드의 구조

자바코드의 구조



1.소스파일에는 무엇이 들어 있을까?

소스 코드파일(java라는 확장자자 붙은 파일)에서는 클래스(class) 각각 한 개씩을 정의합니다. 클래스는 보통 프로그램의 한 부분이라고 할 수 있지만 아주 작은 애플리케이션 중에는 클래스 단 하나만으로 이뤄진 것도 있습니다. 클래스는 한 쌍의 중괄호({ })안에 들어가야 합니다.

public class Dog {

//클래스



2.클래스 안에는 무엇이 들어있을까요?

클래스에는 메소드(method)가 한 개 이상 들어갑니다. 예를 들어, (개를 나타내는) Dog 클래스에는 (짖는 것을 의미하는) bark라는 메소드가 들어갈 수 있으며, 이 메소드에는 개가 짖는 방법을 지시하는 내용이 들어가면 될 것입니다. 메소드는 클래스 안에서(즉, 클래스 전체를 감싸는 중괄호 안에서) 선언해야 합니다.

public class Dog {

    void bark() {

    } // 메소드

//클래스 



3.메소드 안에는 무엇이 들어있을까요?

메소드를 감싸는 중괄호 안에는 메소드에서 처리할 일을 지시하는 내용이 들어갑니다. 메소드 코드는 기본적으로 일련의 선언문을 모아놓은 것이므로 지금은 메소드를 일종의 함수나 프로시저와 비슷한 것으로 생각해도 됩니다.

public class Dog {

    void bark() {

        statement1; //선언문
        statement2;

    }// 메소드

}
//클래스



클래스를 해부합시다.

JVM이 실행되면 명령행에서 지정했던 클래스를 살피게 됩니다.
그리고 나서 main() 메소드를 찾아 봅니다.

public static void main(String[] args) {
    //코드가 들어갈 자리
}

 
이런 메소드를 찾으면 JVM에서는 main 메소드의 중괄호({ }) 안에 있는 것을 모두 실행시킵니다.
모든 자바 애플리케이션에는 
최소한 클래스한개가 있어야 하며 적어도 main 메소드 하나가 있어야 합니다.(클래스마다나씩이 아니라 애플리케이션마다 하나씩 있어야 합니다. *참고로 WAS와 같은 웹서버는 main메소드를 따로 구성하실 필요가 없겠죠^^ main메소드로 WAS가 이미 구동중이니까요^^)

main이 들어있는 클래스 만들기

자바에서는 모든 것이 클래스 안에 들어갑니다.
우선 소스 코드(.java 확장자가 붙어있는) 파일을 입력한 다음 컴파일해서(.class 확장자가 붙어있는) 새로운 클래스 파일을 만들면 됩니다. 프로그램을 실행시킨다는 것은 사실 클래스를 실행시키는 것이라고 할 수 있습니다.

프로그램을 실행시킨다는 것은 자바 가상 머신(JVM Java Virtual Machine)에 "Hello 클래스를 불러 오고 그 main() 메소드를 시작하라. 그리고 main() 메소드에 있는 모든 코드가 실행될 때까지 계속 실행시켜라"라는 뜻의 명령을 내리는 것입니다.

클래스에 대한 자세한 내용은 다음 포스팅에서 알아보기로 하고, 지금은 실행 가능한 자바 코드를 만드는 방법에 대해 살펴보기로 하겠습니다. 그러면 우선 main()부터 시작해보죠.
 
프로그램 실행 절차가 시작되는 부분은 바로 main()메소드입니다.

프로그램이 아무리 커도(바꿔 말하자면 프로그램에서 얼마나 많은 개수의 클래스를 사용하든 상관없이)프로그램을 실행시키려면 반드시 main() 메소드가 필요합니다. 

1.저장 -> 2.컴파일 -> 3.실행 

main 메소드란?

일단 main 안으로 들어가면 (또는 어느 메소드든) 본격적으로 뭔가가 돌아갑니다. 즉
대부분의 프로그래밍 언어에서 컴퓨터로 하여금 어떤 일을 하게 만드는 모든 일반적인 지시사항은 메소드 안에 들어있습니다.

코드에서는 JVM에 다음과 같은 것을 지시할 수 있습니다.

1.뭔가를 하는 것

선언문: 선언, 대입, 메소드 호출 등

int x = 3;
String name = "Dirk";
x = x* 17;
System.out.print("x 는 " + x + "입니다.");
//주석은 이렇게 씁니다.


2.뭔가를 여러 번 반복하는 것

순환문: for와 while

while (x > 12) {
    x = x -1;
}

for(int x -0 ; x < 10; x = x+1) {
    System.out.print("x의 값은 "+x+ "입니다.");
}



3.조건에 따라 뭔가를 하는 것

분기문: if/else 테스트

if(x== 10) {
    System.out.print("x가 10이군요.");
} else {
    System.out.print("x가 10이 아닙니다.");
if((x< 3) & (name.equals("Dirk"))) {
    System.out.print("Gently");
}
System.out.print("이 선언문은 무조건 실행됩니다.");


돌리고 돌리고 돌리고...

자바에는 while, do-while, for의 세 가지 표준 순환 구조가 있습니다. 순환문에 대한 자세한 내용은 나중에 알아보기로 하고 일단 여기서는 while만 생각해 보겠습니다.

문법이 워낙 간단하기 때문에 설명이 지루하게 느껴질지도 모르겠네요. 어떤 조건이 만족되기만 하면 순환문 블록(block) 안에 들어있는 작업을 모두 처리합니다. 중괄호 한 쌍 안에 들어가는 내용ㅇ이 바로 순환문 블록이며 반복하고자 하는 내용은 그 블록 안에 집어넣으면 됩니다.

순환문에서 가장 중요한 것은 바로 조건 테스트 부분입니다. 자바에서 조건 테스트의 결과는 부울 값(boolean)입니다. 즉, 참(true) 또는 거짓(false) 값을 가지게 됩니다.

"iceCreamInTheTub 가 참인 동안 계속 아이스크림을 퍼라"와 같은 것이 바로 부울 테스트라고 할 수 있습니다. 통 안에 아이스크림이 있거나 없거나 둘 중 하나기 때문이지요. 하지만 이 때 참과 거짓이 분명하지 않으면 안 됩니다. 반드시 참과 거짓이 명확하게 구분되는 것만 조건 테스트로 사용할 수 있습니다.


'Develop Story > Head First Java' 카테고리의 다른 글

2.객체 마을로의 여행  (0) 2011.03.26
1 껍질을 깨고  (0) 2011.03.25
Posted by gofly

댓글을 달아 주세요