2019년 5월 18일 토요일

[책리뷰][켄트벡 전작주의] 켄트벡의 구현패턴

켄트벡은 수 많은 개발을 해오면서, 그것들을 패턴화 시켰다.
그 패턴들은 본능적으로 해오던 것이 아니라, 오랜시간동안 만든 패턴들을 모은 것이다.

그러니까 아무렇게나 짜고보니 패턴이었네?
이런게 아니라 고심끝에 만들어낸 패턴이라는 것이다.

하지만 이 책은 크게 추천하고 싶지는 않다.
1. 읽기가 쉽지 않다.
정말 많은 번역책을 읽었다. 책은 내용이 어려워서 읽기 힘든 경우도 있지만, 번역이 이상하여 읽기 힘든 경우가 있다.
GoF의 디자인패턴을 한 번 보자. 읽기가 쉽지는 않다. 하지만 두어번 읽어보면 GoF는 간결하게 필요한 글을 써놔서 그 글에 적응하면 읽기가 수월해진다. 하지만 이 책은 두서 없이 써나간 책이다. 패턴이라는 말을 붙이고 클래스, 메소드 뭐 이런식으로 내용들을 나눠놨지만 메소드끼리 엮여있다고 그 안에 내용들이 같은 것으로 관통하는 것이 아니다.

겉모습만으로 챕터를 나눠놨기 때문에, 중간을 넘어간 후에 책을 덮고 자세히 생각해보면, 앞 장에서 클래스에서 이야기 했던 패턴과 관통하는 것을 알 수도 있다. 그러므로 내용은 반복되고(반복이라니!) 이 반복과 저 반복이 무슨 차이인지 헷갈린다.

2. 이 책은 패턴을 익히기 위한 책이 아닌 것 같다.
말했다시피, 행동패턴, 구조패턴, 생성패턴 뭐 이렇게 만든것이 아니라. 어떤 상황이 왔을 때 어떻게 할까? 라는 문제를 이야기 한다. 이 상황들은 꽤나 정형적이지 않고, 아주 특별한 경우들이다. 이 경우들이 상상은 가지만 와닿지 않는다. "켄트벡은 정말 많은 프로젝트를 했구나..."라는 생각을 했다. 하지만 이 켄트벡이 제안하는 패턴방식은 어떤 특별한 원칙이 있지 않다. 이 내용은 밑에서 설명할 것인데, 그는 지속적으로 특별한 경우를 만들고, 이것이 어떻게 어려운지를 말하고, 왜 이렇게 밖에 코딩을 할 수 없는지 설명한다. 이런 화법을 쓰면 "어쩔 수 없이 저렇게만 써야 하는건가" 라는 생각이 들게 한다. 그리고 그는 실용성을 많이 따지면서 타인이 읽는 것을 생각하며 코딩하라고 한다. 그는 미학보다는 일을 제대로 끝내는 것에 관심이 있는 것 같다. (이것은 이전 2권을 읽으면서도 느꼈던 것이다. 그래서 더 관심이 갔다.) 하지만 본 책에서 그는 가끔씩 미학을 강조한다. 미학를 추구하는 것이 얼마나 중요한지를 말한다. 그리고 그것이 실효성과는 관련이 없다는 것도 시인한다.

그런면에서 "켄트벡 또한 사람이구나" 싶었다. (아름다움을 추구하는 것은 당연한 것이라고 어떤 철학자가 말했던가)

3. 이 책에서 원칙은 간결성, 객체지향 같은 것이 아니라 켄트벡이 남을 생각하는 마음에 가깝다.
그러므로 켄트벡의 지극한 사견이다. 이 패턴들은 그가 고민했던 내용들은 적어놓고 그것들을 모아놓은 것이다.
사실 그는 말을 번복하는 것처럼 보이지만, 번복하는 것이 아니라 상황마다 다르다는 것을 보여주려고 한 것일 것이다.
그것은 꽤나 미세한 차이로 보일 때도 있다. 전혀 다른 상황처럼 보이는 것들을 자세히 비교하면 결국 어떤 상태를 밖으로 보이게 할 것이냐,
아니면 타입을 어떻게 확인 할 것이냐 하는 것임을 알게 된다. 거기에 어떤 환경을 제시하고, 어떻게 한다.

기존에 켄트벡 저의 2권을 읽인 후, 이 책을 기대했지만 기대에는 좀 아쉬웠다.
이전 책과는 달리... 마치 하루키의 잡문집 같았다.

하지만 그러기에 켄트벡의 마음을 조금이나마 알 수 있었고,
객체지향/함수지향 그런 것보다는 자신/당신/우리를 생각하려는 마음의 중요성을 느꼈다.

사실 개발자는 모두 그런것들을 어렴풋이나마 알고 있었을 것이다.
아니면 큰 의미 없이 그렇게 주장해왔을 것이다.

하지만 그는 아무 생각없이 주장하지 않는다.
그의 구현패턴이 그 증거이다.

2019년 5월 15일 수요일

[책리뷰][켄트벡 전작주의] 테스트 주도 개발

켄트벡이라는 사람의 책의 번역본을 전부 읽어보려고 한다.
이 형은 코드와 설계 그 사이의 간극을 메우기 위해 어떤 행동을 취해야 하는지 알려준다.

그 중에 하나가 익스트림 프로그래밍에서 보여준 반복이다.
돌아가는 작은 것을 만들고, 함께 만들고, 바꾸고, 더 크기를 키우고, 더 복잡하게 하고, 완성한다.

이것의 그가 가진 중요 통찰인 것 같다.
나는 그의 생각을 더 제대로 알기 위해 다른 책을 빌렸다. 바로 [테스트 주도 개발]이다.

이 책은 크게 3가지 파트로 나뉜다.
1. 여러 통화를 가진 Money객체와 그 안에 비즈니스 로직 만들기.
2. TDD 툴을 만들기
3. 테스트 주도 개발을 위한 팁

이렇게 3가지로 나뉜다.

여기서 가장 중요한 진수는 파트 1에 있다고 생각한다.
마치 파트 2는 툴이 없는 사람을 위해 툴을 만들도록 도와주는 것 같았고
파트 3은 여러가지 상황에 따른 대처방법이나 철학을 말한다.

하지만 나에게 필요한 것은 켄트벡이 개발을 하면서 어떤 생각을 하는 지다.
그는 요구사항을 할 일에 적고(이게 중요하다고 생각한다)
일단 테스트로 만든다. (컴파일 에러가 나도 상관없다. 나의 상상 속에서 이것을 어떻게 호출할 지 생각하고 테스트로 일단 적어 보는 것이다. 아무 생각없이 클래스 부터 생성하고 보면 나의 상상과는 다른 설계가 될 수 있을 테니까)
그 테스트를 통과하기 위해 (요행을 써서라도) 빠르게 통과를 시키고
실제 요구사항에 맞게 개발을 하고
리팩토링 할 것을 할일에 적는다.(바로 리팩토링을 하기도 하지만 꼭 할 일에 적는다.)
그리고 한가지 Task를 끝내면 할일에서 줄을 긋는다.


숙련이 된다면 아주 작은 일들을 한꺼번에 처리해도 된다고 켄트벡은 말한다. (한칸 올라갔던 내가 나중에는 두 세 칸씩 올라가는 나를 보면 흐믓할지도 모르겠다.)
파트 1의 내용은 처음부터 마지막 까지 TDD를 이용한 Money객체가 어떻게 변해가는지에 대한 이야기다.
처음 만든 설계와는 전혀 다른 아이가 되어 있다.

상속을 사용해서 만든 Dollar/Franc객체가 사라지는 순간이나 (상속 또한 사라진다)
여러 환율을 서로 더하기 위해 만들어진 Bank/Expression/Sum 객체가 만들어지는 순간은 정말 인상적이다.
TDD에서 특이한 점은 리팩토링을 아주 편하게 할 수 있다는 점이다. 나는 기존의 요구사항보다는 무엇이 바뀌었는지를 신경쓸 수 있다.
그리고 실수를 해도 바로 테스트에서 실패하니 그곳을 확인하면 되는 것이다.

그는 테스트를 통해서 나 뿐만이 아니라 당신 또한 편안해지기를 바란다.
나 뿐만 아니라 팀이 코드를 믿고 쓰기를 바란다.

게다가 그는 겸손하다. 그는 좋은 코드만으로는 성공을 보장하지 못한다는 것을 강조한다. 하지만 나쁜 코드는 성공을 할 수 없게 만든다는 것 또한 잊지 않게 한다.
켄트벡이라는 사람은 성실하고, 실수를 하지 않으려고 고민하는 사람이며 게다가 실행하는 사람이다(테스트가 성공할 때까지 코딩을 하는 사람이다)

켄트벡이라는 사람의 다음 책 또한 기대된다.

아래는 TDD 켄트벡의 책을 이용한 전체 소스이다. (Test 코드 제외)
https://github.com/ssisksl77/java-demo/tree/master/src/main/java/kentbeck/tdd

2019년 5월 12일 일요일

[책리뷰][켄트벡 전작주의] 익스트림 프로그래밍

최근 Object Thinking 이라는 책을 한 반정도 읽다가 포기했다. 수 많은 메타포들과 마치 어학영수시절 글쓰기 시절의 글처럼 한 문장을 지나갈 때마다 의미가 동일해도 무슨 토플 시험 보듯, 단어가 계속 바뀌고 바뀌다 보니 점점 읽어가는 속도가 느려졌다. 그러면서 포기를 하게 되었다. 나중에 읽어야지...

하지만 읽으면서 느꼈던 것이 객체지향 프로그래밍은 애자일/익스트림 프로그래밍이 태어날 때, 함께 자라난 개념이라는 것이었다. 객체지향 시뮬라에서 파생된 C++와 스몰토크에서 스몰토크는 시뮬라의 디자인을 따라가려 했으며, C++는 디자인을 따라가기에는 너무 속도가 느리다고 판단, 시뮬라의 디자인을 완벽하게 구현하지는 않았다고 한다.(Object Thinking 참고)

그후로 계속 익스트림 프로그래밍과 애자일에 대해서 이야기를 한다. 자바,객체지향 책을 읽어서는 객체지향의 진수를 알 수 없고, 겉에 보여지는 것만 알게 될 것이라고 그는 말한다. 그러니까 우리는 겉모습만 따라하고 실재로 무엇이 중요한지 모른다는 말 같다.

마치, 짝프로그래밍을 한다고는 하지만, 정확이 이것으로 무엇을 성취하는지는 모르는... 그런 것일까나?
그리고 자주 언급되는 사람들이 있었다. 나는 Object thinking이라는 책을 덮고 일단 그 사람들에 대해서 그리고 그 언어들에 대해서 공부를 해볼까 한다.

일단 나는 켄트벡 아저씨에 대해 알아보려고 한다. 그는 책을 정말 많이 썼다. 게다가 이분 책을 읽어 본 적이 있다. 바로 [익스트림 프로그래밍] 이다.
처음 개발을 시작할 때, 읽었던 책이다. 그 당시 중간 정도 읽다가 대체 무엇이 중요한 거지? 라는 생각과 기억에 남은 거라곤, 도요타 공장라인에 대한 이야기 뿐이었다. 문제가 생기는 것을 보면 줄을 잡아당겨 모든 생산라인을 정지시키고 모두 함께 문제를 해결하는 것. 그리고 필요한 만큼만 준비하고 생산하는 효율이라는 마인드. 그것뿐이었다.

나는 이전에 봤던 그 책을 한번 다시 보기로 했다.
요즘은 도서관에 갈 필요도 없이 나랑 멀리있는 도서관도 내 집 근처 역으로 배송을 해준다.
나는 익스트림 프로그래밍 책을 빌렸다.

그리고 다시 읽으면서 아... 그때 아무생각 없이 읽었던 내용들이 이런 것들이었구나... 하는 것을 느겼다.
그래도 아마 나는 제대로 이해한 것이 아닐 것이다. 정말로 해보기 전까진 모를 것이다. 정말 닥치기 전까지 자신이 어떤 행동을 할지 모르듯이...

하지만 정말 멋진 방법같다.

====
계속 하나의 프로그램을 작게 쪼개면서 개발을 하는데, 차라리 쪼갠 부분이 하나의 프로그램이라면, 어떨까.
그렇다면 그것을 하나의 프로그램으로 보고 테스트해보고 확인하고 개선하고 또 새로운 프로그램이 탄생하고.
그런 주기를 계속 이어간다는 것.
===

그럼으로 몇주일 단위로 배포되던 것들이, 일주일 단위로 그리고 하루 단위로 배포가 되면서 눈 앞에 살아있는 생명처럼 보이기 시작한다면,
우리는 무엇을 만드는지 알 수 있고, 무엇을 개선해야 하는지 빠르게 알 수 있을 것이다.

정말 이런 개발이 가능할까.
정말 이런 문화가 가능한 것일까.

이런 문화를 한번쯤은 겪어보고 싶은 생각이 있다.

켄트벡 아저씨의 책을 더 읽어보고 싶다. 도서관에서 구할 수 없는 책들은 구매도 하고 싶다. 하지만 지금 집에 쌓인게 책들이라... 책을 구매하는 것은 집에 있는 책들을 다 치우고 생각해봐야겠다.

이 책은 개발자만을 위한 책은 아닌 것 같다. 무언가 계획을 관리함에 있어, 익스트림 프로그래밍의 철학과 맞닿는 분야라면 가능하다고 생각한다.
특히 요구사항이 생명체처럼 변하는 세상의 부름처럼 자연스레 바뀌어야 하는 상화이라면 익스트림 프로그래밍이라는 책 읽어볼만 하다고 생각한다.

2019년 4월 26일 금요일

[리뷰][scheme] Programming and Meta-Programming in Scheme 을 읽고

https://www.amazon.com/Programming-Meta-Programming-Undergraduate-Computer-Science/dp/1461272432
이 책은 얼떨결에 읽게 되었다.

Scheme 관련 책을 골라보려고 샘플을 받았는데 페이지를 넘기다가 얼떨결에 구매해 버린것이다!
게다가 만원 2만원도 아닌 60달러 이상이 되는 책이었다.
Scheme에 대해 꽤나 자세하게 되어있고, SICP에서 설명하는 강의의 내용과 꽤나 비슷한 내용들이 많았다.

SICP를 읽기 위한 전과정이라 생각해도 될 것 같다는 생각을 했다.
일단 Scheme책이기 때문에 Scheme에 대한 깊은 내용이 나올 때도 있다. 관심이 없지만 아마 다른 Lisp들도 비슷한 컨셉으로 만들어져있지 않을까 하는 마음이 들어서 계속 읽었다.

매크로에 대한 내용은 생각보다 많이 나오진 않았다.
오히려 개발에 대한 일반철학을 설명할 때가 좋았다. 아마 그런 걸 더 느끼고 싶어서 SICP를 읽어보려는 걸지도 모르겠다.

아쉬운 점은 해당 사이트를 찾아보려고 했는데 잘 작동하는 것 같지 않았다.
http://www.cs.sjsu.edu/faculty/pearce/scheme/index.html

읽으면서 가장 기억에 남는 것은 heap을 구현해보는 것이었다.
아직도 좀 난해한데 나중에 시간 나면 그 부분만 다시 따라쳐보면서 이해해볼까 한다.

글로는 대충 느낌이 오는데 소스코드가 난해하다.
그래서 타입체크 하는 부분을 좀 줄이고 한가지 타입만 저장가능하도록 줄여서 구조를 이해해볼까 한다.

다음은 How to Design Program을 도서관에서 빌려 볼까 한다.

2019년 4월 18일 목요일

[SICP][scheme][javascript] 아무것도 없는 것에서 무언가를 추상화할 수 있을까?

출처 : https://youtu.be/ymsbTVLbyN4

심심할 때마다 SICP의 강의를 들어보고 있다.
내 재주로는 사실 제대로 이해를 할 수 없는 경지임이 틀림없다. 그럼에도 조용히 넘어가다가 엄청난 것을 발견해 버렸다.

바로 아래의 코드이다.
(define (cons a b)
  (lambda (pick)
    (cond ((= pick 1) a)
          ((= pick 2) b))))

(define (car x) (x 1))
(define (cdr x) (x 2))

;; 설명을 위해 더해진 것.
(define A (cons 1 2))
(print (car A))
(print (cdr A))
이 비디오를 보는 사람들 중 몇몇은 이미 이 내용을 설명할 때, 경악을 금치 못했다.
이 코드가 왜 이리 신기한 것일까?
그것은 이 영상의 시작부터 알아봐야 한다.

이 영상의 주제는 추상화이다. 그 중에서도 데이터를 추상화하는 것인데 데이터를 추상화하면 우리에게 많은 특징(이점)이 있다.
1. 개념적으로 부를 수 있게 된다. 우리는 그 데이터에 이름지음으로써 그것을 머릿속으로 다룰 수 있게 된다. 그것은 마치 마술사가 주문에 이름을 부여하는 것처럼 마법과 같다.
2. 우리는 이 개념의 정확한 정의를 나중에 내릴 수 있게 된다. 일단 이름을 부름으로써 나중에 해당 개념에 대한 정의가 바뀌면 그 정의만 바꾸면 되는 것이다.
3. (추가적인 특징) 우리는 이 추상화된 데이터를 강제할 수 있다.

이 책에서 설명하는 rational number에 대해 알아보자.
우리는 일단 데이터를 추상화 해야 한다. 분자 n, 분모 d가 있다. 이것들을 make-rat에 넣어서 하나의 패키지를 생성하는 것이다. 이것을 추상화
(make-rat n d) => rational-number (n,d의 저장형태는 알 필요없음)
(numer rational-number) => numerator 분자
(denom rational-number) => denominator 분모
여기서 make-rat는 constructor, numer/denom은 selector라고 불린다.
하나의 데이터는 이렇게 constructor와 selector로 추상화될 수 있다.

이렇게 유리수를 make-rat, numer, denom으로 추상화 하였다.
한번 더하기를 해보자.
(define (+rat x y)
  (make-rat
    (+ (* (numer x) (denom y))
       (* (numer y) (denom x)))
    (* (denom x) (denom y))))
여기서 x,y는 rational-number이다. 우리는 x,y가 어떻게 구현되어 있는지는 모르지만, make-rat으로 유리수를 만들 수 있고, numer/denom으로 꺼낼 수 있는 것은 알고 있다.
곱하기도 만들자.
(define (*rat x y)
  (make-rat)
  (* (number x) (number y))
  (* (denom x) (denom y)))
자 이제 유리수를 구현해보자. 어떻게 담아야 할까?
(define (make-rat n d) (cons n d))
(define (numer x ) (car x))
(define (denom x) (cdr x))
이렇게 cons를 이용하여 pair(리스트)를 만든다.
그러니 rational-number란 무엇인가? 이것은 사실 pair일 뿐이다. 첫번째와 두번째라는 박스가 있는 자료구조일 뿐이다.
그렇다면 pair라는 것은 무엇인가? 이것도 또한 추상적인 개념이다. 바로!
cons라는 constructor와 car, cdr이라는 selector가 있는 것이다.
그렇다면 pair라는 것이 추상적인 개념이라는 무엇을 기반으로 만들어진 개념일까?
여기서 저자는 아무것도 없는 곳에서 생성된다고 한다.

그리고 등장하는 코드 (위에서 보여줬지만 다시 한번 적자. 중요하니까)
(define (cons a b)
  (lambda (pick)
    (cond ((= pick 1) a)
          ((= pick 2) b))))

(define (car x) (x 1))
(define (cdr x) (x 2))
여기에 데이터가 보이는가? 어떤 자료구조가 보이는가?
쌩뚱맞게 lambda가 보인다. cons는 일단 procedure를 다시 리턴한다.
그리고 pick이라는 변수를 받는데 그것이 1이면 a를 리턴하고, 2이면 b를 리턴하는 함수를 리턴한다.

car를 보자. (x 1)라는 함수가 있는데, 여기서 1이 매개변수 pick에 매핑될 것이다. 첫번째 값(즉 a)이 리턴
cdr에서는 (x 2)로써, pick=2가 되고 두번째 값(b)가 리턴된다.

대체 어디에 a,b는 어떤 자료구조로 저장되는 건가? 아무것도 아닌 것에 저장되는 느낌이다.
closure를 이해한다고 생각했는데 이 코드를 보자마자 '이해한다는 것이 무엇인지조차 모르고 있었구나' 라는 생각이 들었다.

공부를 하면 할 수록, 항상 겸손해야 한다는 생각을 할 수 밖에 없다.
겸손하지 않으면, 배울 수가 없으니...

강의 교수님이 한 말씀을 여기 기록하지 않을 수가 없다.
So in some sense, we don't need data at all to build these data abstractions.
We can do everything in terms of procedures.

procedures are not just the act of doing something.
procedures are conceptual entities, objects.

강의가 끝나고 한 지적인 학생이 엄청난 질문은 하는데 그것은 바로
(cons 1 2)의 값과 1초 후 동일한 프로시저호출인(cons 1 2)는 동일한 녀석인가? 이다.

이 말은 (+ 2 2)와 4는 동일한 녀석인가?

를 고민하는 문장인데, 한시간의 수업에서 대체 이런 질문이 어떻게 나올 수 있었을까? 라는 생각이 든다.
이 질문에 대해 교수님은 당장은 대답할 수 없지만, 곧 하게 될 것이라는 말을 하며 끝낸다.

언제 저 답을 알 수 있을까? 빨리 다음을 알고 싶다.

여담으로 아래 scheme코드를 js로 변경해보자.
function cons (a , b) {
  return function(pick) {
    switch(pick) {
    case 1 : 
      return a;
    case 2 :
      return b;
    default:
      return;
    }
  }
}

function car(x) { return x(1); }
function cdr(x) { return x(2); }

var procedure = cons(10,20);

car(procedure);
cdr(procedure);

2019년 3월 20일 수요일

[리뷰][Coursera] 코세라의 [Concurrent Programming in Java] 수강을 마치며

Coursera에서 수강할 수 있는 Concurrent Programming의 수강을 마쳤다.

이번에는 lock와 readwritelock에 대해 배웠으며, Actor의 개념도 살짝 나왔다.

실제로 Actor를 제대로 구현해서 사용하는 것은 아니지만 개념정도 알고 어떻게 사용되는
지만 알아도 Actor가 좀 더 친근해진 느낌이다.


조금 어려운 내용이 나오기도 했지만 프로젝트 자체는 어렵지 않고, 친절하게 프로젝트 자체를 설명해주기 때문에, 잘 넘길 수 있었다. 내 생각에 이 코스에서 중요한 부분은 프로젝트 어사인먼트가 아니라 QUIZ인 것 같다.

개념을 잘 이해해야 하는 경우가 있으며, 내가 어떤 부분을 헷갈려 하는지 알 수 있기 때문에 같은 부분을 계속 듣고 확인하게 만들어 준다.

괜찮은 강의였으나, 좀 더 설명이 길었으면 하는 아쉬움이 있다.

2019년 3월 5일 화요일

[javascript] 그래서 커리를 어떻게 쓰려고?

내가 처음 커리를 써야겠다고 생각했던 것은 로직이 계속 겹치고 있었기 때문이다.

예를들어보자. 인풋별로 유효성을 체크하는데 유효성을 체크할 때마다 하는일이 조금씩 다르다.

// 핸드폰 인풋 묶음 3개 유효성검사
var phone_1 = trim($("#phone_1").val());
var phone_2 = trim($("#phone_2").val());
var phone_3 = trim($("#phone_3").val());

if (phone_1 < 3 && phone_1 ...) { // 여러 and문과 유효성검사
  $("#phone_1").focus();
  alert("휴대폰 유효성검사실패");
  return;
}
... phone_2, phone_3

$("#hidden_phone_").val(phone_1 + "-" phone_2 + "-" + phone_3);
이런 코드가 있다. 익숙하다. 일단 커리를 쓰기 전에 여기서 if문에 있는 모든 유효성검사는 하나의 함수로 추상화 해놓자.
if (validate(phone_1) { // 여러 and문과 유효성검사
  $("#phone_1").focus();
  alert("휴대폰 유효성검사실패");
  return;
}
if (validate(phone_2) {
  $("#phone_2").focus();
  alert("휴대폰 유효성검사실패");
  return;
}
if (validate(phone_3) {
  $("#phone_3").focus();
  alert("휴대폰 유효성검사실패");
  return;
}
이런 코드를 본 적 없는가? 여기서 분명 우리는 뭔가 더 할 수 있을 것 같다. 어떻게 해야 할까? 맞다 객체를 넘기는 것이다.
function validateAndFocus(phone, $phone) {
  if (!validatePhone(phone) {
    alert("휴대폰 유효성검사 실패");  
    $phone.focus();
    return false;
  }
  return true;
}
이제 이걸 사용해보자
if(!validateAndFocus(phone_1, $("#phone_1")) {
  return;
}
if(!validateAndFocus(phone_2, $("#phone_2")) {
  return;
}
if(!validateAndFocus(phone_3, $("#phone_3")) {
  return;
}
...
뭔가 여기도 겹치는 것 같다.
if (!(validateAndFocus(phone_1, $("#phone_1")) &&
      validateAndFocus(phone_2, $("#phone_2")) &&
      validateAndFocus(phone_3, $("#phone_3"))) {
  return;
}
undersocre.js의 and가 있다면 더 좋을 것 같다. 끝이 없을 것 같으니 여기서 넘어가자. underscore를 쓸 수 없어서 curry만 임시 사용하는 것이다. 이정도만 깔끔해보인다. 그런데 여기 주민번호와 카드번드까지 추가되었다.
var card1 = $("#card1");
var card2 = $("#card2");
var card3 = $("#card3");
var card4 = $("#card4");

var national_id_1 = $("#national_id");
var national_id_2 = $("#national_id");

우리는 validateAndFocus를 사용할 수 있는가? 사용할 수 없다. 1. 휴대폰번호의 유효성과 아이디의 유효성은 다르다. (predicate의 분리 필요) 2. 유효성 검사 이후 하는 일이 각각 다를 것이다. 하지만 형태는 동일하다. 1. 주어진 값의 유효성을 검사한다. 2. 통과하면 true 실패하면 false를 리턴한다. 3. 유효성검사에 실패하여 false를 리턴하기 전에 각각 해야하는 일이 있다.
// 동일한 형태의 일을 하는 함수 템플릿 정의
function validateTemplate(pred, func, obj1, obj2, obj3) {
  if (pred(obj1, obj2, obj3)) {
    func(obj1, obj2, obj3);
    return false;
  }
  return true;
}
자 이 형태를 만들었다. 이제 어떻게 사용할지 보자. 유효성 검사를 분리해서 넣을 것이다. 그렇다면 이렇게 될 것이다.
var curried = curry(validateTemplate);
var validatePhoneCurried = curried(function(n) {
  return validatePhone(n);
});
var validateCardCurried = curreid(function(n) {
  return validatePhone(n);
});
var validateNationalidCurreid = curried(function(n) {
  return validateNationalid(n);
});
뭐 대충 이렇게 코딩했다. 현재까지는 pred를 커리하고 이제는 각 pred마다 할일을 다르게 넣을 수 있겠다. 첫번째 인자를 _로 한 이유는 focus나 val("") 등 DOM조작을 위한 객체를 따로 넘긴다고 하자.
var validatePhoneFinal = validatePhoneCurried(function(_, $dom) {
  alert("헨드폰문제!");
  $dom.focus();
});

var validateCardFinal = validateCardCurried(function(_, $dom) {
  alert("카드문제");
  $dom.focus();
});

var validateNationalidFinal = validateNationalidCurreid (function(_, $dom) {
  alert("주민번호문제");
  $dom.focus();
});
이렇게 만들었다 치자. 이제 위에 코드를 저것들로 바꾸면 된다.
if (!(validatePhoneFinal(phone_1, $("#phone_1")) &&
      validatePhoneFinal(phone_2, $("#phone_2")) &&
      validatePhoneFinal(phone_3, $("#phone_3"))) {
  return;
}

....
if (!(validateCardFinal(card_1, $("#card_1")) &&
      validateCardFinal(card_2, $("#card_2")) &&
      validateCardFinal(card_3, $("#card_3")) &&
      validateCardFinal(card_4, $("#card_4"))) {
  return;
}
...
if (!(validateNationalidFinal(national_id_1 , $("#national_id_1")) &&
      validateNationalidFinal(national_id_2 , $("#national_id_2"))) {
  return;
}
여기서 map이나 every 같은 것을 이용하는 것이 큰 도움이 될 것 같지만 그러진 않겠다. 오늘의 주제는 커리니까.
curry라는 함수 한번 가지고 놀아봤다.