How to think like a programmer

Tags:

요즘 CS101 과목 조교를 하고 있습니다. 이 과목은 갓 대학에 입학한 학생들이 자바 언어를 배우는 과목입니다. 이 과목의 실험(프로그래밍하고 검사받는..) 조교를 하다보니 ‘일반인’의 사고는 우리 프로그래머와 완전히 다르다는 것을 깨닫게 되더군요.

예를들어, 예외 없이 모든 책들은 hellow world 예제로 시작합니다. 그러면 자바는

public class Blah {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

이 정도까지는 대강 따라합니다. 그냥 되니까요. 하지만 문제는 서서히 드러납니다. 예를들어서 두 점의 좌표를 기억하는 클래스가 있고

class Point {
    private double x;
    private double y;

  public void setX(double x2) {
    x = x2;
  }

  // and some setters and getters
}

나중에 이 Point를 사용해 무언가 유용한 일을 한다고 하죠. 그러면

class Circle {
  private Point center;
  private double radius;
  
  // some setters and getters here
}

오늘 여러 학부생의 코드를 봐주다보니, 여기서 “왜 Point를 써야하는가”, “왜 getter와 setter를 써야하는가”, “getter와 setter의 차이점은 무엇인가(이 질문이 왜 나오는지 이해가 되시나요? 아예 instantiation같은 개념도, 변수에 대한 개념도 거의 없는 상태입니다.)”, “public static void main(String[] args) 는 무엇인가” 등 정말 밑도 끝도 없는 질문들이 많았습니다. 물론 저는 제 나름의 best practice나 제 나름의 식견을 피력하지만, 그것이 얼마나 먹혀들어갈지는 의문입니다.

예를들어, “왜 setter와 getter를 써야하는가”란 질문에 ‘미래의 비즈니스 로직의 변경에 유연한 대처를 하기 위해서 주로 setter와 getter를 쓰는데, 그 로직의 변경이 일어날지 안일어날지도 모르는 상황에서 미리 setter와 getter를 만드는 것이 불필요한 일일 수 있다는 반론이 가능한 것은 사실이다. 하지만 자바에서는 통상적으로 변수를 선언하면 private 으로 만들고 이에대한 getter와 setter를 작성한다’고 대답하지만 이 답의 몇 퍼센트나 이해할까요.

우리가 흔히 아주 당연하게 받아들이고 있는 것들 – Object, Instance, Class, Variable, Method, Parameters, Return statement등 – 을 그 학생들은 전혀 이해하지 못합니다. static도 모르고, array도 모르고….

루비는 어떨까요? 루비는 이런 질문에 답해줄까요? 일단 루비는 2가지 이유로 적당한 대안이 되지 못합니다. 첫번째 이유는 부족한 문서때문이고, 두번째 이유는 어려운 언어이기 때문입니다. 예를 들어 루비는 hello world까지는 다음과 같이 넘어갑니다.

puts "Hello World"

다음, OOP는 반드시 짚고 넘어가게 되겠죠. 그러면 그 순간 또다시 왜 attr_accessor를 써야되는가부터 시작한 질문 러쉬가 들어올 것입니다. 이렇게 놓고 곰곰히 생각해봤더니 문제는 OOP가 무엇인가를 이해시키는 것이 어렵다는 것을 깨달았습니다. 과거에는 기껏해야 프로그램에 구조 – 구조체, 함수 등 – 를 부여하는데 지나지 않았던 문제 해결 기법이 이제는 객체 지향으로 탈바꿈 하면서 learning curve가 갑자기 높아져버린 것입니다. 아마도 한학기가 지나고나면 대다수 학부생들은 OOP가 뭔지는 모르고, 기껏해야 어떻게 하면 상속을 좀 더 할 수 있을까라는 쓸모없는 생각만 머리속에 남겠죠.

BASIC 이 돌아오지 않는한 이 문제는 쉽사리 풀리지 않을 거란 결론을 내린 하루였습니다. ㅎㅎ

Comments

9 responses to “How to think like a programmer”

  1. 영회 Avatar

    기회가 되시면 이 글도 한번 읽어보시죠.
    getter/setter를 안만들 수 있다면 정말 OO 스럽다는 것이 저자의 견지이죠.

    http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox_p.html

  2. MKSeo Avatar
    MKSeo

    잘 읽었어요. 그 글에 나온대로 무신경하게 getter와 setter를 만드는 것은 분명히 잘못이죠. C++ 과 같이 뭐든지 가능한 언어라면 몇개의 필드만 내부에 넣고, 알고리즘은 모두 클래스 밖으로 빼버리는 식의 과감한 분리를 할 수도 있겠죠. 어떤식으로든지간에 클래스에서 무언가 public 이 되면 확정되버리는 것이니까요.

    사실 오늘 수업이 끝나고 잠깐 Point의 좋은 구현을 생각해보았습니다.

    public class Point {
    
        private final double fX;
        private final double fY;
    
        public Point(double x, double y) {
            fX = x;
            fY = y;
        }
    
        public double getX() {
            return fX;
        }
    
        public double getY() {
            return fY;
        }
    }
    
  3. 무책 Avatar

    ㅎㅎ 이제 막 프로그래밍101을 배우는 이들에게 너무 harsh하신거 아니에요? ^^

    제가 공대를 막 들어갔던 80년대에는 Fortran을 101시간에 가르쳤더랬죠. 그 후 Pascal이나 C를 처음 가르치더니 90년대 들어서면서 C++을, 90년대 중 후반을 지나면서 Java를 첫 언어로 가르치는 것 같더군요.

    저는 지금도 처음 배우는 언어로는 C같은 것이 더 낫지 않나 생각합니다. 우선 고차원적인 개념이 적어 조금만 논리적이면 배우기 쉽고, 조금이라도 더 튜링 머신에 가깝게 기계가 동작하는 원리를 배워두는 것이 나중에 어떤 새로운 개념의 언어를 배우더라도 그 underlying behavior를 이해하는데 오히려 더 도움이 될 것이라 생각하기 때문입니다.

    저 같은 경우도 OO라는 것을 알기도 전에 C에서 struct 내에 function pointer 테이블을 써서 일종의 dispatch table을 구현해 쓰곤 했는데, 그 후 C++에서 class라는 것을 보고는 세상 정말 편해졌단란 생각이 들면서 자연스레 OO의 장점을 이해하기 시작했는데, 맨 처음부터 그런 개념을 강제로 머리 속에 집어 넣으려 하면 왜 그래야만 하는지 잘 이해를 못할 것 같아요.

    C에서 조차 처음엔 도대체 왜 int main(int argc, char **argv, char **env)로 시작해야 하는 걸까 의아해 했었던 기억이 나네요. 나중에 crt0.asm 내에 100h로부터 시작해서 결국 _main이란 걸 불러주기 때문이란 걸 알고서야 의문이 풀린 것 처럼, 처음 배우는 이들이야 (특히 그냥 “바담문” 하고 따라하는 스타일이 아닌 사람에겐 더더욱) “원래 이렇게 하는거야”라고 하면 잘 받아들이기 어려울 것 같단 생각이 듭니다.

    지나가다 옛날 생각이 나서 적어봤습니다.

  4. 무책 Avatar

    헉 “바담風” 입니당…

  5. MKSeo Avatar
    MKSeo

    네.. 저도 C부터 하는게 낫지 않은가란 생각이 들었어요. 근데 뭐 커리큘럼을 제가 만드는 것도 아니고 (그냥 전 실습 조교;) 해서.. 그런데 그렇게 생각해보면 기술이 발전할 수록 새로 입문하는 사람은 배워야할게 너무 많아지게 되는 듯 해요.

  6. lepffm Avatar
    lepffm

    객체지향적인 구조의 필요성을 발견해나가도록
    도와주는 방식은 어떨까요.

    예를 들자면 단순히 변수로 접근하는 방식(C style)으로
    만든뒤 기능을 확장하면서 문제가 발생했을때
    (외부에서 데이터 수정, 로직의변경, 변수변경, 상속등)
    어떻게 해결하는게 좋은지 물어보고
    그 해답의 하나로 메세지교환방식(get/set)으로
    수정해서 어떤 면이 더 좋아졌는지
    조금은 체감할수 있도록 소개해주는 겁니다.
    (혹시 tdd 형식으로 진행하면 그런 교체 과정이 빨라질지도 모르겠습니다.)

  7. MKSeo Avatar
    MKSeo

    네.. 그러면 좋을텐데, 문제는 전 강사가 아니라 그냥 애들이 코딩하면 채점만 해주고 질문하면 답하는 정도라서…;; 정말 헤메는 학생이 질문하면 그렇게 가르쳐볼께요. ^^

  8. 영회 Avatar

    많이 고민하시는점 대단하삼입니다. ^^; 실무 프로그래머를 보면 기초는 시간을 투자하는 것이 아니라 원리를 대할때만 쌓이는 것이라는 점을 실감합니다. 그런 면에서 학생때 많은 고민을 하도록 유도하시는 것 같아 보기 좋네요.

  9. MKSeo Avatar
    MKSeo

    하하 네.. 근데 저도 학생이어서 ㅎㅎ
    학생때 아니면 이런 저런것들을 사실 생각해보기 힘든듯해요.

Leave a Reply

Your email address will not be published. Required fields are marked *