Software Development

ALIWEB

Koster, M. 1994. ALIWEB – Archie-Like Indexing in the WEB.

첫번째 WWW 컨퍼런스인 WWW ’94에 발표된 paper.

1990년 11월에 첫번째 웹서버가 생긴 이후로, 웹의 사용자와 정보의 크기는 점점 늘어나고 있었고, 1993년에는 200개 이상의 웹서버가 있다고 알려지게 되었다. 이렇게 되자, 웹에서 어떤 정보를 찾는 것은 점점 힘들어지게 되었고, 이 문제를 해결하기 위한 여러 노력들이 1993년부터 나타나기 시작했다. 그 결과로 나타난 첫번째 웹 검색엔진이 바로 ALIWEB이었다.

도입 부분에서, 웹의 resource discovery 방법이 진화한 과정을 Browsing – Listing – Searching (Catalogue) – Automatic Collection (from Catalogue) – Automatic Discovery의 단계로 설명하고 있는데 흥미롭다. 현재의 검색엔진에서 Automatic Discovery를 당연시하고 있는 것을 생각하면, 마치 FORTRAN Compiler가 탄생했을 때, 이를 Automatic Programming이라고 부르던 느낌이랄까.

한편, Archie란 여러 Anonymous FTP 사이트가 가지고 있는 파일들을 인덱싱하여 검색할 수 있도록 해주는 Anonymous FTP의 검색 엔진이었다. Archie의 동작 방식은 각 Anonymous FTP 사이트에서 파일 리스팅에 해당하는 파일을 받아서 사용자가 검색 가능하도록 해주는 것이었다. 이 paper에서 Archie-Like라고 부르는 것도 그러한 동작 방식을 사용했다는 것을 의미한다.

ALIWEB의 동작 방식은 다음과 같다.

  1. 웹사이트 관리자가 정해진 포맷으로 각 사이트에 대한 인덱스 파일을 만들고 이를 ALIWEB의 웹 인터페이스를 통해 등록한다.
  2. ALIWEB은 등록된 웹사이트들의 인덱스 파일들을 자동으로 받아와서 이를 검색 가능하도록 인덱싱한다.
  3. 검색을 원하는 사용자는 오늘날의 검색엔진 인터페이스와 거의 같은 모습의 ALIWEB의 웹 인터페이스를 통해서 쿼리를 보내고 결과를 볼 수 있다.

이 paper에서 밝히고 있는 ALIWEB의 문제점은 역시

  • 사이트별 인덱스 생성 과정의 어려움, 그리고
  • scalability

이다.

사실, 사이트 관리자에 의한 사이트별 인덱스 생성은, 사이트 관리자가 그 사이트에서 어떤 것이 인덱싱 되어야하는가를 가장 잘 알고 있을 것이라는 합리적인 의도를 가지고 있고, Koster는 이러한 방식이 적어도 medium term에서는 잘 동작할 것이라고 예상했지만, 실제로 이는 실패했다. 물론, 사이트 관리자에 의한 사이트별 인덱스 생성이라는 개념은 현재에도 Google Sitemap과 같은 형태로 존재하지만, 적어도 이러한 메커니즘이 Automatic Discovery의 주요한 역할을 맡고 있는 것은 아니다.

어쩌면, 텍스트를 위주로 한 현재의 웹에 대한 Automatic Discovery가 정점에 이르면, 오히려 장기적인 관점에서, 사이트 관리자에 의한 사이트별 인덱스 생성이라는 개념이 유효해질 가능성도 있다. Semantic Web이나 Web Services와 같은 웹을 구조화된 형태로 만드려는 노력이 어떤 방향으로 진행될지는 아직 미지수다.

Scalability의 문제는 프로토타입의 성격을 지닌 ALIWEB에서 해결되리라고 기대할만한 문제는 아니지만, 사이트별 인덱스를 사이트 내의 상위 레벨 서비스에 대해서만 생성한다든가, 특정 분류나 도메인에 한정된  ALIWEB 사이트를 만들어서 해결한다는 생각은 현재 시점에서 바라볼 때는 실망스럽다.

현재의 웹을 바라보면, 상위 레벨 서비스만 검색되면 되는 것이 아니라, 하위 레벨 페이지들이 실제로 사용자들에게 가장 흥미로운 내용을 포함하고 있고, 검색의 결과로서 적합한 경우도 많다. 한편, 특정 분류나 도메인에 한정된 검색도 물론 유용하지만, 이것이 Scalability 부족의 대안으로 나오는 것은 현재 웹의 크기를 고려할 때 바람직하지 못하다.

ALIWEB 더 읽기"

Bad Smell of Code: Too many top-level classes in a file of Java program

소스 파일(이하, 파일)도 모듈의 일종이다.

어떤 프로그래밍 언어에서는 파일을 언어 자체가 정의하는 개념(예를 들어, C++의 ‘컴파일 단위’)으로 본다. 어떤 프레임워크에서는 특정한 파일은 어떤 특별한 역할을 하는 코드의 집합으로 본다. (예를 들어, RoR의 파일 구성) 마찬가지로, 어떤 프로젝트에서는 정해진 독특한 규칙에 따라 특정 파일에 특별한 역할을 부여할 수 있다.

이런 면에서, 소스 파일의 구성(File Organization)은 소프트웨어 품질에 영향을 미치는 디자인 결정 중의 하나다.

파일이라는 OS라는 낡고 거추장스러운 곳으로부터 나온 (어떤 면에서) 언어 외적인 요소를, 고매하고 청명한 정신으로부터 태어난 자신의 코드와 결부시키는 것이 불편하게 느껴질지도 모르겠다. 언어 자체가 파일 개념에 의존하지 않는다면, 한 프로젝트의 모든 코드가 한 파일에 들어있든, 1억개의 파일에 들어있든 무슨 상관이 있겠는가.

하지만, 아직은 프로그래밍 세계는 파일이라는 요소에 의존하는 편이다. 그럴 듯한 IDE를 사용하지 않는 프로그래머들도 너무나 많다. (당신이 vim을 IDE라고 주장하더라도 notepad는 어떤가?!) 그들에게 파일은 Readability에 직접 영향을 미치는 단위가 된다. 너무 긴 파일은 너무 긴 클래스나 너무 긴 함수의 문제점과 동일한 문제를 유발한다. 읽기 힘들다. 파악하기 힘들다. 소위, 스크롤의 압박이란거다.

한편, 현재의 IDE들은 언어가 파일에 의존하지만 않는다면, 파일이라는 요소를 배제할 수 있는 포텐셜을 가지고 있으나, 단순하게도, 그렇게 하지 않는다! 그나마 우리를 행복하게 해주기 위해 IDE를 제작하는 분들에게 뭔가를 추궁하지는 않겠다. 아직은 우리는 파일이라는 개념에 너무나 익숙하다. 정말로 파일이 싫은가 하면 그렇지도 않단 말이다.

어쨌든, 파일은 모듈이고 다시 말해, decomposition의 단위다. 이것은 파일이라는 모듈에도 높은 cohesion과 낮은 coupling이 요구된다는 것이다.

Java와 같은 언어에서는 (Top-level) 클래스 각각은 그 클래스의 이름을 가진 독립된 하나의 파일을 점유하는 것이 일종의 컨벤션이다.

얼마전에 코드 리뷰를 한 적이 있는데, Top-level 클래스 5-7개 정도가 하나의 파일에 들어가 있는 경우를 발견했다. 이것을 발견하자 내 직관은 뭔가 잘못된 것이라는 알려주었다. 도대체 이 클래스의 범위는 어디까지인거지? 왜 이렇게 길어? 이 클래스로 이동하려면? (난 이클립스를 사용하고 있고, 코드 navigation 기능은 숙지하고 있으니, 친절하게 알려주지 않아도 된다.) 혼자만의 생각이지만, 다른 개발자가 이런 코드를 보더라도 분명 나와 비슷한 느낌을 받으리라고 생각한다. (무슨 소리?)

자, 그럼 직관이 아니라, 뭔가 납득할만한 설명을 필요한 것 같다. 대체 왜 그  클래스들은 한 파일에 있어야만 할까? 클래스들을 자세히 들여다보면, 1) A와 B는 Use 관계에 있으나, 그 역할은 충분히 다르고, 특히 A와 B는 그 파일 밖에 있는 클래스 P와 Q에 의해서 사용되고 있었다. 2) D는 C의 구현이 되어야할 부분을 다시 모듈화한 것이었다.

1) A와 B는 충분하게 cohesive하지 않을 뿐만 아니라 파일 외부의 클래스에 의해서도 사용되므로 다른 클래스들과 동등한 자격으로 – 즉, 파일로 노출될 필요가 있다. 2) D는 C의 구현에 해당하고 외부로 노출될 필요가 없으므로 Top-level 클래스가 될 필요가 없다. 즉, D는 C의 임베디드 클래스가 되면 훌륭하다.

이런 식으로 리팩토링을 하고 나니, 하나의 파일에는 하나의 Top-level 클래스만이 남아있었다.

물론 하나의 파일에 무조건 하나의 Top-level 클래스만 써야만 하는 법은 없을 것이다. 내가 알지 못하는 문맥에서의 필요성이 있을 수도 있고, Top-level 클래스를 하나의 파일에 모아두는 것에 페티쉬를 가진 경우도 있을 것이다. 물론, 파일 개념의 철폐를 부르짖는 해방주의자도 빼놓을 수는 없다. 하지만, 대부분의 경우에는 별 생각 없이 한 파일에는 하나의 Top-level 클래스를 두는 것으로 생각하면 별 탈 없을 것이고, 어쩌면 칭찬을 들을지도 모른다.

오늘의 Rule of Thumb: Java 프로그래밍에 있어서 하나의 파일에는 하나의 Top-level class를 두자. 땅땅땅.

Bad Smell of Code: Too many top-level classes in a file of Java program 더 읽기"

Unnecessary Software Complexity

소프트웨어가 해결하려는 문제가 복잡하다면 그 해결책 즉, 소프트웨어도 복잡해진다. 즉, 소프트웨어의 복잡성은 부정적인 효과를 가지지만, 항상 잘못된 것이고 거절할 수 있는 것은 아니다.

따라서, 소프트웨어의 복잡성 문제를 해결하려고 할 때는 불필요한 소프트웨어의 복잡성(Unnecessary Software Complexity)라는 개념을 가지고 얘기해야한다.

한편, 소프트웨어의 복잡성이 문제의 복잡성에 의존하기 때문에, 문제가 달라지면 불필요한 소프트웨어의 복잡성도 달라진다. 다르게 말하면, 문제가 달라지면, 소프트웨어를 평가하는 기준도 달라질 수 있다는 것이다.

이야기를 하나 해보자. 어떤 소프트웨어 팀은 실제로 많은 문제가 있다고 생각해서, 또는 의욕적이어서 많은 문제를 해결하는 소프트웨어를 만든다. 시간이 지나고, 그런 문제를 해결할 필요가 없어졌고, 사람들은 그런 사실을 잊어버렸다고 해보자. 남아있는 소프트웨어는 그 시점에서 불필요한 소프트웨어의 복잡성이 높은 소프트웨어일테고, 그 소프트웨어의 개발자는 비난을 받는다. 이것은 공평하지 못하다. 소프트웨어 엔지니어링에서 얘기하는 것처럼 문제의 합의에 대한 계약서라도 써놓는 것이 이러한 문제를 해결할까? 그렇지는 않다고 생각한다. 사람들은 ‘문제가 변화한다’는 사실에 대한 명확한 인식을 가지고 있어야할 뿐만 아니라 ‘문제를 알고있다’라는 생각에 대해 좀 더 보수적일 필요가 있다.

문제가 언제 변화하냐고? 문제는 항상 변화한다.

Unnecessary Software Complexity 더 읽기"

Software Complexity

생물학자 줄리언 헉슬리(Julian Huxley)는 1912년에 복잡성을 ‘부분들의 이질성’이라고 정의했는데, 이는 일종의 기능적 불가분성을 뜻한 것이었다. 만들어진 신, 리처드 도킨스

어떤 일을 할 때는 항상 그 일에 맞는 ‘생각의 틀’이 필요하다. 최근 4개월 가량 소프트웨어 개발에서 완전히 손을 떼고 있었고, 그 생각의 틀을 조금씩 회복하는 중이다. 그러던 중 읽은 복잡성에 관한 정의는 내가 지금 겪고 있는 소프트웨어 복잡성의 문제를 떠올리게 해주었다.

복잡성에 관한 얘기를 할 때, 소프트웨어의 복잡성은 흔히 생물의 복잡성과 함께 취급되곤 한다. 물론, 생물의 복잡성은 소프트웨어의 복잡성에 비교할 수 없을 정도지만, 소프트웨어의 복잡성에 대한 일반인들의 관용은 생물의 복잡성에 대한 관용보다 높지는 않을 듯하다. 하지만, 소프트웨어 엔지니어 입장에서 복잡한 소프트웨어를 바라보았을 때 ‘손을 댈 수도 없다’는 그 심정은 생물을 다루는 연구자나 중환자의 몸을 다루는 의사의 심정과 크게 다르지 않으리라고 생각한다.

소프트웨어 복잡성의 문제는 다른 과학이나 공학과 마찬가지로, 환원, 특히 기능적 환원으로 해결하는 것이 기본이다. 복잡한 소프트웨어는 하나의 부분을 이해하거나 고치기 위해서는 그 부분과 기능적 불가분의 관계에 있는 여러 부분들을 동시에 이해하고 고쳐야한다. 환원 과정을 통해 프로그래머가 신경써야할 거리를 분리함(separation of concern)으로써, 프로그래머는 한번에 하나의 부분만을 다른 부분과 관계없이 신경쓸 수 있다. 소프트웨어에 있어서는 이러한 과정을 decomposition또는 모듈화(modulization)이라고 부른다. 소프트웨어가 만들어지고 나서 수행하는 decomposition을 특히 리팩토링(refactoring)이라고 부르기도 한다.

생물과 소프트웨어의 또다른 유사성은 바로 계속 변화한다는 것이다. 그리고, 생물이 진화할 수록 그 복잡성이 높아지는 것처럼 (진화의 방향이 항상 복잡도가 높아지는 방향인 것은 아닐테지만, 적어도 현재까지의 생물사에서는 그러했던 것 같다.) 소프트웨어도 성장할될 때마다 복잡성이 높아진다. 생물의 진화는 인위적인 것이 아니므로 복잡성을 ‘해결’할 필요가 없지만, 소프트웨어의 변화에는 (아직은) 인간의 지적인 능력이 필수적이므로, 복잡성은 소프트웨어가 더이상 성장하는 것을 막는 요인이 되고, 심지어는 소프트웨어의 생명을 짧게 만드는 요인이 되기도 한다. 따라서, 소프트웨어가 오랫동안 성장하기 위해서는 복잡성을 일정 수준 이하로 항상 유지시켜야 하고, 이를 위해서는  decomposition에 더욱 많은 시간을 들이고 자주 해야한다.

소프트웨어 복잡성을 해결하는 과정 못지않게 그것을 인지하는 과정도 중요하다. 복잡성을 인지하지 못하면, 해결하려는 노력을 할 수도 없다. 또한, 복잡성을 인지하지 않고 decomposition을 하려는 노력은 무의미하거나 적어도 비용-효율적이지 못할 수 있다.

소프트웨어 복잡성은 소프트웨어를 만드는 과정 뿐만 아니라 소프트웨어의 결함들을 해결하는 과정 또는 그 원인을 분석하는 과정에서도 인지될 수 있다. 그러한 과정에서 프로그래머가 ‘너무 복잡하다’고 느끼는 것은 복잡성의 첫번째 징표다.

  • 결함 해결 과정에서 너무 많은 부분들이 결함 가능성을 안고 있고 어느 부분에 결함이 있는지 가늠하기 어렵다면 그 소프트웨어는 복잡한 것이다.
  • 결함의 원인이 한 부분만의 결함이 아니라 많은 부분들이 서로 영향을 주면서 발생한 결함이라면 그 소프트웨어는 복잡한 것이다.

복잡성을 훌륭하게 해결한 시스템들을 보면 항상 기능적 분화 뿐만 아니라 발생 가능한 결함 자체를 격리한다. 복잡한 시스템들은 그 부분들간에 너무 많은 기능을 서로 의존하고 있을 뿐만 아니라, 설령 기능은 분리되어있다고 하더라도, 발생가능한 결함들은 분리되어있지 않다.

가만히 생각해보면 소프트웨어 디자인이 해결하고자 하는 주요 문제는 결국 복잡성의 해결이다. 성능과 같은 비기능적 요소들은 제약조건에 불과하다. 이를테면, ‘성능 요건을 xxx만큼 만족시키면서 복잡성을 yyy만큼 해결하는 것’의 문제란 것이다. 대규모 소프트웨어를 높은 수준에서 바라보는 사람은 복잡성에 관한 생각이 반드시 그의 ‘생각의 틀’에 담겨있어야한다.

Software Complexity 더 읽기"

Web Crawler

web_crawler_20070223.pdf

올해 초에 신입 팀원들을 대상으로 발표한 자료로, Web Crawler의 기본적인 설계와 구현시 신경써야할 기초적인 사항들을 언급하고 있습니다. 대단한 내용이 있는 것은 아니고 단순히 Mining the Web의 Web Crawler chapter를 정리한 내용입니다.

Web Crawler 개발에 있어서 가장 중요한 것은 무엇이냐고 제게 묻는다면 저는 이 발표자료의 Closing에 적혀있는 한 줄로 대신 답하겠습니다.

Understand status quo of Web

사실 어느 정도 숙련된 개발자라면 Web Crawler의 기초적인 기능들은 대단히 단순하기 때문에 별로 어렵지 않다고 느끼실 겁니다. 저도 물론 처음엔 그렇게 생각했구요. 하지만 현재는 약간 생각이 달라졌습니다. 훌륭한 Web Crawler를 만들 수 있는 능력은 바로 웹의 현재 상태에 관한 지식을 얼마나 가지고 있는가 또는 얻을 수 있는가에 달려있다고 생각합니다. 이 발표자료를 쓸 때보다 이러한 생각이 더욱 강하게 드는 요즈음입니다.

Web Crawler 더 읽기"

재설계

사람들이 미술을 처음 시작하면 잘못된 부분을 다시 그리는 것을 꺼려한다. 일단 그 정도로 그린 것에 만족하며, 다시 손을 대다가 혹시 더 망치지나 않을까 염려한다. 그리하여 방금 그린 것이 그렇게 나쁘지는 않다고, 어쩌면 최선의 작품일지도 모른다고 생각하여 스스로를 설득한다. 폴 그레이엄, 해커와 화가

재설계 더 읽기"

Naming Objects

이 글은 2004년 12월 14일, 네오위즈에서 일하던 시절에, 팀 내부에 공유한 메일입니다. (영어 단어나 어법 오류 등은 수정했습니다.) 현재의 제 생각과는 약간 다른 부분도 있지만,

  • 문제 영역의 언어로 이름짓기
  • 적절한 비유의 사용
  • 최소화 인터페이스

등은 저 뿐만 아니라 많은 사람들이 동의하는 프로그래밍의 원칙들입니다.

이름 짓기

바쁜 일정과 많은 업무로 인해서 팀 내에서는 ‘이름 짓기’가 중요하게 여겨지지 않고 있지만, 저는 이름 짓기에 대해서 강한 의견을 가지고 있는 사람입니다. ;-)

객체와 메서드의 이름을 지을 때는 그것이 하는 역할에 맞게 이름을 짓는 것이 좋습니다. 당연히 이 역할은 객체가 해결하려는 문제의 도메인 안에서, 그 도메인의 언어로 정의됩니다. 따라서, 객체와 메서드의 이름은 문제 도메인의 언어로 기술하는 것이 가장 바람직합니다. (일반화된 이름은 원래 문제 도메인의 이름이 아닌 경우가 있지만, ‘일반화’ 역시 일종의 해결하려는 문제입니다)

예를 들어, 6살짜리 어린이가 가게에서 사탕을 사먹는 문제에 대해서 해결 방법을 기술하려면, 6살짜리 어린이가 이해할 수 있어야 하고, 사탕이라는 단어가 거의 반드시 들어가야겠죠.  또한, 사탕을 사 먹어야 하는데, 다른 도메인의 언어, 즉 음표라든가, 양자역학 같은 단어가 나오면 곤란합니다.

junkmemocheck를 희생양으로 삼아 예를 들어보죠. (junkmemocheck는 쪽지를 너무 많이 보내는 사람을 차단하기 위해 사용자별로 최근에 쪽지를 보낸 수를 세어주는 컴포넌트입니다.)

메서드 이름 짓기

제가 이해한 바로는, junkmemocheck(이하, 줄여서 JMC)에 관련된 시나리오는 다음과 같습니다.

  1. 사용자 A가 쪽지를 보낼 때, A가 쪽지를 보냈음을 JMC에 알려줍니다.
  2. 사용자 A가 미리 정해진 시간 내에, 쪽지를 보낸 수를 얻거나, 너무 많이 보냈다는 정보를 얻어옵니다.

이를 좀 더 단순한 말로 적어보죠.

  1. 특정 사용자가 쪽지를 보냈다.
  2. 특정 사용자가 최근에 쪽지를 보낸 수를 주세요.

메서드 이름으로 바꿔보죠.

쪽지는 Memo라는 용어로 대치하고, ‘미리 정해진 시간 내에’라는 requirement에 대해서 ‘Recently’라는 단어를 도입했습니다.

  1. sentMemo(user)
  2. getCountOfMemoSentRecently(user)

좀 더 줄이면,

  1. sentMemo(user)
  2. getRecentMemoSent(user) 또는 getMemoSent(user)

클래스 이름 짓기

이러한 역할에 비추어보면, junkmemocheck는 (Sent)MemoCounter 같은 이름이 더욱 적당하지 않을까 싶습니다. (사실 ‘정해진 시간 내’라는 제약 조건이 있어서, “Counter”라는 비유가 약간 부적절해 보이므로, 좀 더 나은 비유가 있으면 좋을 듯 하네요.)

MemoCounter
+ increaseCount(user)
+ getRecentCount(user)

일반화된 이름 짓기

나중에 다른 요구사항이 생겨서, 쪽지만이 아니라 다른 곳에도 이 어플리케이션이 사용되기도 결정되었다고 합시다. 우리는 “Counter”라는 비유를 이미 사용했으므로, 이를 그대로 사용하면 될 것 같습니다. 사용자 대신 슬롯(slot)이라는 개념을 사용합니다.

Counter 클래스의 역할(Role)은 다음과 같습니다.

  1. k 슬롯의 카운터를 하나 증가시킨다.
  2. 일정 시간 내에 k 슬롯에 증가된 카운터 값을 가져온다.

이를 바탕으로 다음과 같이 이름을 지을 수 있겠네요.

Counter
+ increaseCount(k)
+ getRecentCount(k)

개선된 디자인

사실 Counter 안에 k라는 슬롯을 찾는 것보다는, k라는 이름의 Counter가 있는 것이 더욱 직관적입니다. Counter의 메서드에 k를 명시하기 보다는, k에 해당하는 Counter 객체가 있는 것이 낫겠죠.

kCounter = CounterCollection.getCounter(k)
kCounter.increaseCount()
kCounter.getRecentCount()

좀 더 단순하게 만들어볼까요? CounterCollection에 Count가 있는 것은 당연하고, Count를 increase하는 것은 당연하므로,

kCounter = CounterCollection.get(k)
kCounter.increase()
kCounter.getRecent()

성능 고려하기

MemoCounter 든, Counter든 역할에 따라 두개의 operation으로 분리했습니다. 하지만, 내부적인 구현에 따르면, 각각이 server로 메시지를 따로 보내야 한다면, 그리고 거의 항상 두 operation이 같이 쓰인다면, 이러한 분리는 비효율적입니다. 한번에 물어볼 수 있는 방법이 필요합니다.

Counter
+increase(k)
+getRecent(k)
+increaseAndGetRecent(k)

가능한 한 원래의 인터페이스가 직관적이므로 유지하는 것이 좋다고 생각하지만, 이를 유지하면서 성능을 개선할 수 있는 더 나은 방법이 있을지도 모르겠습니다.

인터페이스 최소화

거의 항상 단순한 인터페이스가 좋습니다. 필요없는 인터페이스는 사용자를 혼란스럽게 합니다. 예를 들어, increaseAndGet(k)만이 사용되고, 다른 메서드는 사용될 가능성이 별로 없다면,

Counter
+increaseAndGetRecent(k)

만으로도 충분합니다.

결론

저는 메서드 이름부터 새로 짓기 시작했지만, 좀 더 일반적인 방법은,

  1. 문제 해결에 필요한 객체의 이름과 역할을 정합니다. 객체를 정할 때는 문제를 해결하기 위한 비유를 생각해보면 좀 더 쉽게 지을 수 있습니다. 문제는 얼마나 적절한 비유인가인데, 어떤 비유가 객체의 역할 즉, 문제의 해결방법에 얼마나 근접하느냐를 따져야할 것입니다. 객체의 이름은 항상 문제 도메인의 언어나, 비유의 이름으로 짓습니다.
  2. 객체 역할에 따라 메서드를 추가합니다. 하나의 동작에 하나의 메서드를 추가합니다. 메서드 이름 역시 항상 문제 도메인의 언어로 짓습니다.
  3. 이 후에도 얼마든지 성능 고려나 인터페이스 최소화를 할 수 있습니다.

Naming Objects 더 읽기"

Dynamics of Software Development

Dynamics of Software Development by Jim McCarthy

요즈음 널리 유행하는 방법론들처럼 체계화 되어있는 것은 아니지만, 이 책은 소프트웨어 개발의 여러 부분들에 걸친 조언을 담고 있는 책이다. 그 범위는 소프트웨어 개발에서 어떤 것이 바람직한 리더쉽인가, 어떻게 팀을 만들 것인가, 고객이나 비즈니스 부문 등의 팀 외부와 어떻게 소통할 것인가, 경쟁 시장에서 어떻게 포지셔닝할 것인가,빌드와 출시, 개발 일정과 주기는 어떻게 할 것인가, 사람은 어떻게 뽑을 것인가와 같이 소프트웨어 개발 팀에 관련된 거의 모든 부문을 다루고 있다고 해도 과언이 아니다.

저자는 소프트웨어 개발팀을 생태계와 같은 것으로 보고 있다. 팀원들은 팀장의 지시에만 따르고, 미리 정해진 역할을 수행하는 것이 아니라, 팀장은 팀원에게 권한을 위임해야하며 (지식노동에 있어서 이것은 이미 황금률이다.) 팀원들은 자신의 능력이 다른 팀원들과 조화를 이루도록 역할을 진화시켜 나간다. 이러한 관점은 소프트웨어가 지식 노동의 산출물이기 때문에 무엇보다도 팀원들부터 아이디어가 자유롭게 나오고 그 중에서 최상의 아이디어가 선택되어야한다는 이유에 비롯한다.

애자일 소프트웨어 개발 프랙티스 (이를테면 XP와 같은)에서와 비슷한 주장들을 1995년에 쓰여진 이 책에서 하고 있는 것도 재미있는 점이다. (참고로, C3 프로젝트는 1996년에 시작되었고, Kent Beck이 유명한 Extreme Programming Explained를 내놓은 것은 1997년의 일이다.) 신속하게 개발주기를 반복한다든가, 알려진 상태를 유지하는 것, 고객과의 관계의 강조 등에서 그러한 것들을 엿볼 수 있다. Scrum과 같은 방법론은 1993년에 적용되기 시작했고, Iterative and Incremental Development: A Brief History와 같은 문서를 보면, 1980년대에 이미 점진적인 개발 방법이 소프트웨어 개발계에 떠들썩하게 떠오르고 있음을 할 수 있다.

설령 책이 제시하는 세부적인 방법들에 동의를 하지 않는다고 하더라도 한번이라도 팀에서 소프트웨어 개발을 해본 경험이 있다면, 지난 날의 경험을 회상하며 이 책의 조언에 대해 깊히 생각해보는 것은 매우 유익한 일일 것이다. 다만, 저자는 인문학적인 배경이 있는지 몰라도 문학이나 철학에 기원한 개념들을 자주 빌려쓰고 있을 뿐만 아니라 전체적인 문체도 간명한 편은 아니어서, 읽기가 쉽지 않은 면이 있다. 단지 번역의 탓만은 아닌 듯 보인다. 반대로 이러한 점 때문에, 한문장 한문장을 곱씹어볼 경우 여러가지 경우에 여러 의미로 다가올 수도 있을 것이고, 비단 저자의 조언을 곧이곧대로 받아들이기보다는 풍부한 고민의 원천이 될 수 있는 면도 있을 것이다.

Dynamics of Software Development 더 읽기"

소프트웨어 공학의 사실과 오해 Facts and Fallacies of Software Engineering

우리가 미처 알지 못한 소프트웨어 공학의 사실과 오해우리가 미처 알지 못한 소프트웨어 공학의 사실과 오해, by Robert L. Glass

Robert Glass의 이 책은 내가 읽은 소프트웨어 엔지니어링에 관한 문헌들에서 자주 인용되기에 꼭 한번 읽어봐야지 하고 생각하고 있던 책이다.

제목 그대로 이 책은 소프트웨어 엔지니어링에 관한 사실들과 오해들을 열거하고, 각각에 관한 논쟁과 저자의 의견들을 정리해놓은 책이다. 각각의 항목들은 다른 유명한 저작들에서 언급된 내용이 많아서 ‘집대성’의 느낌이 든다. 이 책의 가장 큰 목적은 저자가 서론에 언급한대로 ‘기본적이면서도 중요’한 사실들인데도 ‘자주 잊혀지’는 사실들을 사람들이 ‘반복해서 배우게’하는 것일 것이다. 한편으로는 사실들의 원저작에 해당하는 개개의 저작들을 읽을 때와는 다르게, 여러 사실들과 논쟁을 한곳에 정리해놓음으로써, 소프트웨어 엔지니어링에 대한 생각을 정리하고 관점을 만들어낼 수 있도록 도와준다.

대부분의 사실들은 말그대로 ‘사실’로 통용되는 것들이지만, 몇몇은 아직 논쟁거리인 경우도 있고, 개인적으로 동의하고 싶지 않거나 또는 그동안 믿지 않았던 것들도 있었다. 사실 이러한 점들을 읽는 도중에 메모를 해서 정리했어야 하는데, 그러지 못한 것이 후회된다. 하지만, 이 책은 한번 더 읽어볼 기회가 있을 듯하고, 그 때는 반드시 그에 관한 글을 따로 써야겠다.

저자가 채택한 사실에서 몇가지 경향을 찾아본다면, 다음과 같다.

  • 사람이 중요하고 도구와 기술은 그보다 중요하지 않다.
  • 어떤 문제에서든 은탄환은 없다.
  • 소프트웨어 개발 프로세스의 초기 단계들(요구사항, 설계)은 중요하다.
  • 소프트웨어 개발 프로세스의 몇몇 단계들은(테스팅, 검토, 유지보수)은 대단히 중요하지만 과소평가되고 있다.
  • 대규모 또는 범용적인 재사용은 어렵다.

저자는 소프트웨어 엔지니어링 학계에서 널리 받아들여지고 있는 사실들은 단정적으로 받아들이고 있으며, 소프트웨어 엔지니어링에 있어서의 최근의 변화에 대해서는 어느 정도 긍정적인 점들은 인정하기는 하나 약간 망설이는 느낌이 든다. 한마디로 말해 보수적이다. 어떻게 보면, 학계가 바라보는 현재의 소프트웨어 엔지니어링에 대한 시점이 이 책에 그대로 반영되어있다는 느낌이 든다. (이를테면, 학계에서도 인정이 되고 있는 패턴에 대해서는 항목을 하나 할애해서 재사용에 대한 해법 중 하나로 인정하고 있다. 반면 오픈소스나 XP에 대해서는 약간 방어적이다.)

하지만, 그러한 태도가 이 책의 단점이라기보다는 장점이라고 생각한다. 소프트웨어 엔지니어로서 우리는 새로운 기술, 도구, 프랙티스가 우월하므로 도입해야만 한다는 강박관념에 항상 시달려왔다.  우린 오히려 좀 더 신중해야할 필요가 있다.

이 책을 읽으면서 자꾸만 내가 겪었던 현실들이 떠오르면서 나 또는 다른 사람들이 기본적이면서도 중요한 사실들을 얼마나 자주 잊고 있는가를 되돌아보게 되었다. 저자에게 동의하지 않을 수 없는 것은 이러한 사실들은 정말로 반복해서 배우는 수밖에 없을 것이라는 점이다.

소프트웨어 공학의 사실과 오해 Facts and Fallacies of Software Engineering 더 읽기"