Saturday, December 24, 2016

파이썬 개발 환경 for osx.

pyenv


파이썬 버전 관리

brew install pyenv
https://github.com/yyuu/pyenv

pyenv-virtualenv


파이썬 가상 환경

brew install pyenv-virtualenv
https://github.com/yyuu/pyenv-virtualenv

autoenv


폴더별 SHELL 환경 설정 ( 꼭 파이썬이 아니더라도 )

brew install autoenv
https://github.com/kennethreitz/autoenv

vim


말이 필요 없는

Tuesday, December 20, 2016

[번역][Swift 공식 블로그] Objective-C [id] 를 Swift [Any] 로 사용하기. 1부

Objective-C [id] 를 Swift [Any] 로 사용하기 1부

원문 : Objective-C id as Swift Any 

Swift3를 이전버전에 비해 좀더 강력하세 Objective-C API를 사용할수 있습니다.
예를들어, Swift2에서는 [id](ObjC)형을 값과,Class 종류만을 가질수 있는 [AnyObject](Swift)형으로 사용할수 있었습니다. Swift2에서는 NSString이나 NSArray 혹은 다른 Foundation 에서 제공하는 형을 기대하는 CoCoa API에서 사용될수 있는 [String][Array][Dictionary][Set] 같은 형으로 묵시적으로 캐스팅 하여 사용할수 있었습니다. 이러한 방식은 일관성이 없고, AnyObject에 실제 어떤 형이 들어 있는지 알수 없어, 버그의 소지가 높았습니다.

Swift3에서는 [id] 타입을 class,enum,struct 혹은 다른 Swift type의 어떠한 타입의 값을 서술할수 있는 [Any] 타입으로 매핑합니다. 이러한 변화는 Swift 에서 사용되는 Objective-C API를 더 유연하게 사용할수 있게 합니다. 왜냐하면  Swift로 정의된 데이터를 Objective-C API에 바로 전달함으로써, Swift type를 분리해서 일일이"box" types로 치환하는 작업을 제거하기 때문입니다.  이러한 특성은 NSArray, NSDictionary, NSSet 과 같은 Collection Class 에도 적용됩니다. 예를들어 hashed container인 [Dictionary] 와 [Set] 같은 경우는 [Hashable] protocol을 구현하는 [AnyHashable] 타입으로 변환되게 됩니다.



ObjCSwift 2Swift 3
[id]AnyObjectAny
[NSArray *][AnyObject][Any]
[NSDictionary *][NSObject:AnyObject][AnyHashable:Any]
[NSSet *]SetSet

대부분의 경우, 이러한 변화에 대응하기위해 코드를 많이 바꿀 필요는 없습니다. 
Swift 2에서 동작했던 [AnyObject]로의 묵시적인 변환을 이용한 코드는 Swift3에서 여전히 동작할것입니다. 그러나 Swift3를 제대로 활용하기 위해, 이러한 변수들의 타입 선언문을 바꾸어야합니다. [AnyObject], [NSString]. [NSArray],[NSDictionary] 같은 걸 묵시적으로 이때까지 사용했다면, 명시적으로 [ as NSString ] 혹은 [ as String ]을 사용해줄 필요가 있습니다. Swift3 에서는 더이상 이런 묵시적인 컨버팅은 허용되지 않습니다. 자동치환 도구는 이런 사소한 변화를 자동으로 해주어, Swift 2 에서 3로 이전할때 코드가 지속적으로 컴파일 될수 있게 도와줍시다. 물론 가장 잘 정리된 형태는 아닐껍니다. 이 글에서 우리는 [id]를 [Any]로 사용하는것을 이용할때, 우리가 직접 수정해야 하는 부분과, 주의해야 하는것들에 대해 살펴 볼 예정입니다. 

Method 오버라이딩과 Protocol 구현

Objective-C Class를 상속받아, Method를 오버라이딩하거나, Objective-C protocol을 구현해야할때, Objective-C 에서 [id] 를 사용한다면 Method Signature를 변경해야 합니다. 
흔한 예로, [NSObject]의 [isEqual:] 이나 [NSCopying] Protocol의 [copyWithZone:] 를 구현하는 경우 입니다. 

// Swift 2
class Foo: NSObject, NSCopying {
 override func isEqual(_ x: AnyObject?) -> Bool { ... }
 func copyWithZone(_ zone: NSZone?) -> AnyObject { ... }
}
Swift3 에서는 추가로 [copyWithZone(_:)]를 [copy(with:)]로 이름을 바꿔야 하며, [AnyObject] 대신에 Any를 사용하도록 Method Signature를 변경해야 합니다.

// Swift 3
class Foo: NSObject, NSCopying {
 override func isEqual(_ x: Any?) -> Bool { ... }
 func copy(with zone: NSZone?) -> Any { ... }
}

Untyped Collections

Property lists, JSON 혹은 User Info Dictionary 들은 Cocoa 에서 일반적이고, 이런것들은 Cocoa Native 에서 untyped collection으로 표기됩니다. Swift2에서는 이 요소들을 사용하기 위해, 묵시적 bridging 변화을 사용하여 [AnyObject] 혹은 [NSObject]로 명시된 [Array] [Dictionary] [Set] 을 만들어야 했습니다. 

// Swift 2
struct State {
 var name: String
 var abbreviation: String
 var population: Int

 var asPropertyList: [NSObject: AnyObject] {
  var result: [NSObject: AnyObject] = [:]
  // Implicit conversions turn String into NSString here…
  result["name"] = self.name
  result["abbreviation"] = self.abbreviation
  // …and Int into NSNumber here.
  result["population"] = self.population
  return result
 }
}

let california = State(name: "California",
        abbreviation: "CA",
        population: 39_000_000)
NSNotification(name: "foo", object: nil,
      userInfo: california.asPropertyList)
혹은 Cocoa container class 인 NSDictionary를 사용할수도 있었습니다.

// Swift 2
struct State {
 var name: String
 var abbreviation: String
 var population: Int

 var asPropertyList: NSDictionary {
  var result = NSMutableDictionary()
  // Implicit conversions turn String into NSString here…
  result["name"] = self.name
  result["abbreviation"] = self.abbreviation
  // …and Int into NSNumber here.
  result["population"] = self.population
  return result.copy()
 }
}
let california = State(name: "California",
        abbreviation: "CA",
        population: 39_000_000)
// NSDictionary then implicitly converts to [NSObject: AnyObject] here.
NSNotification(name: "foo", object: nil,
      userInfo: california.asPropertyList)
Swift 3 에서는 이런 묵시적 전환은 더이상 사용할수 없음으로 위의 예제 코드는 더이상 동작하지 않습니다. 자동 변환 도구는 개별 값들을 [as] 를 통환 형변환을 하도록 하여 코드가 동작하게 할것이지만 좀더 좋은 방법이 있습니다.
Swift는 Cocoa API에서 받을수 있는, [Any] 혹은 [AnyHashable]의 Collection을 사용할수 있음으로 우리는 [NSObject:NSObject] 혹은 [NSDictoinary]를 사용하는 대신 [AnyHashable:Any]를 사용함으로써 다른 코드의 치환 없이 동작하는 코드를 만들수 있습니다. 

// Swift 3
struct State {
 var name: String
 var abbreviation: String
 var population: Int

 // Change the dictionary type to [AnyHashable: Any] here...
 var asPropertyList: [AnyHashable: Any] {
  var result: [AnyHashable: Any] = [:]
  // No implicit conversions necessary, since String and Int are subtypes
  // of Any and AnyHashable
  result["name"] = self.name
  result["abbreviation"] = self.abbreviation
  result["population"] = self.population
  return result
 }
}
let california = State(name: "California",
        abbreviation: "CA",
        population: 39_000_000)
// ...and you can still use it with Cocoa API here
Notification(name: "foo", object: nil,
    userInfo: california.asPropertyList)

[AnyHashable] Type

Swift [Any] Type은 어떠한 형도 담을수 있지만, [Dictionary],[Set]은 [Hashable] 한 Key를 필요로 합니다. 또한 [Any]는 너무 범용이죠. Swift3를 시작으로 Swift Standard Library [AnyHashab]e 타입을 지원합니다. [Any] 와 마찬가지로 이것은 모든 [Hashable] 형의 슈퍼 타입입니다. [String][Int] 혹은 다른 hashable 한 타입들이 들어 있을수 있으며, 묵시적으로 [AnyHashable] 형과 값을 가질수 있습니다. [AnyHashable]에 있는 자료형은 [is],[as!][as?]등을 통해 동적으로 체크할수 있습니다. [AnyHashable]은 type이 명시되지 않은 [NSDioctionary] 혹은 [NSSet] 형을 Objective-C를 통해 가져오는데 사용할수도 있지만, 순수 Swift 에서도 다형성을 가진 sets이나 dictionary를 다루는데 사용할수 있습니다. 


2부에서 계속 

Explicit Conversion for Unbridged Context
[AnyObject] Member Lookup
Swift Value Types in Objective-C
Linux Portability
Learning More



Wednesday, December 14, 2016

[Introduction to Algorithm] 4. Heaps and Heap Sort

4. Heaps and Heap Sort

Priority Queue

key를 가지는 각 요소를 가지는 집합이라고 볼수 있으며, 추가, 최대값, 최대값 추출, 키 값 변경등을 할수 있다.

Heap

Priority Queue의 Array 형식의 구현채로, 시각화하면 거의 완벽한 Binary Tree 형태를 가진다.

Max Heap Property 

주어진 node의 key 값은 항상 해당 node의 children node의 key 보다 항상 크다.

Min Heap 

Max Heap 과 반대의 특성을 가진다.


Heap as a Tree

root of tree : array의 첫번째 element. (i=1)
parent(i) = i/2 : node i 의 부모 node
left(i) = i*2 : node i의 왼쪽 child
right(i) = i*2+1 node i의 오른쪽 child

Binary Heap의 높이는 항상 O(lg n)

Heap Operation

build_max_heap : 정렬되지 않은 array를 max-heap 으로 변환하는 작업

max_heapify : max heap property를 하나만 어기는 경우, 이를 교정하는 작업

insert, extract_max,heapsort

Max_heapify 

* left(i) 와 right(i) 가 max-heaps 라고 가정.
* 만약 A[i] 가 max-heap property를 어긴다면, A[i]를 subtree의 root 와 바꿈으로써 교정할수 있다. 

Max_heapify (example)



Time = ? O(log n)

Max_Heapify Pseudocode

l = left(i)
r = right(i)

if ( l<= heap-size(A) and A[l] > A[i]) then largest = l else larges = i
if (r<= heap-size(A) and A[r] > A[largest]) then largest = r
if largest != i then exchange A[i] and A[largest] Max_Heapify(A, largest)

Build_Max_Heap(A)

for i=n/2 downto 1
    do Max_Heapify(A,i)

n/2 부터 시작하는 이유?

n/2+1....n까지는 Leaf Node 이고, Leaf Node 는 Single-Node Tree로 Max-Heap Property를 만족한다. 

Time =? O(n log n)

Build_Max_Heap(A) Analysis

Max_Heapify는 Leaf 바로위의 Node 에 대해서 O(1) 이 든다. 
일반화해서 보면  Leaf 보다 l level 만큼 떨어진 Node에 대해서는 O(l)이 든다고 할수 있다. 
level 1 nodes : n/4, level 2 node : n/8 .... level log n : 1개의 노드를 가진다고 할수 있다.

결과 적으로 총 loop count는

n/4(1c) + n/8(2c) + n/16(3c) .... 1 ( log n c)

n/4 = 2^k를 대입하면, 

c2^k(1/2^0 + 2/2^1 + 3/2^2 + .... (k+1)/2^k) 가 되면 () 은 수학적으로 상수(constant)가 된다. 

즉 cn/4*c' 가 되어 Build_Max_Heap은 O(n)을 가진다. 

Heap-Sort

1. Max Heap 생성 
2. 최대값 구하기 , A[1]
3. A[n] 과 A[1] 치환 
4. Heap 사이즈를 n-1로 변경 
5. max_heapify를 호출하여, Max Heap으로 재구성.
6. Heap 사이즈가 0이 될때 까지 2번부터 재시작.

* Running Time 

Heap이 비워질때 까지  n번의 loop 이 돌고 매 loop마다 max_heapify:O(log n) 이 호출된다.
즉, O(n log n)


영상 바로가기 :
https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/lecture-videos/lecture-4-heaps-and-heap-sort/

Heap Sort vs x-Sorts ?

Heap Sort 는 best,worst,average case에서 동일하다. 
Heap Sort 는 Memory Complexity 에서 모든 경우에 1을 가진다. 

Heap Sort는 Stable 하지 못한 Sorting 기법이다. 

* Sort에서 Stability 란, 중복된 key가 있는 입력 값에서 해당 key들이일정한 순서(원 입력의 순서)대로 정렬되는지를 의미한다.

https://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms

흐트러진 마음을 잡아 보고자 써보는 '애자일 소프트웨어 개발 선언'


애자일 소프트웨어 개발 선언 

우리는 소프트웨어를 개발하고, 또 다른 사람의 개발을 도와주면서 
소프트웨어 개발의 더 나은 방법들을 찾아가고 있다. 
이 작업을 통해 우리는 다음을 가치있게 여기게 되었다:

공정과 도구보다 개인과 상호작용
포괄적인 문서보다 작동하는 소프트웨어를 
계약 협상보다 고객과의 협력
계획을 따르기보다 변화에 대응하기

가치있게 여긴다. 이말은, 왼쪽에 있는것들고 가치가 있지만, 
우리는 오른쪽에 있는것들에 더 높은 가치를 둔다는 것이다.

애자일 선언 이면의 원칙

우리는 다음 원칙을 따른다:

우리의 최우선 순위는, 가치 있는 소프트웨어를
일찍 그리고 지속적으로 고객을 만족시키는 것이다.

비록 개발의 후반부일지라도 요구사항 변경을 환영하라.
애자일 프로세스들은 변화를 활용해 고객의 경쟁력에 도움이 되게한다.

작동하는 소프트웨어를 자주 전달하라. 두어 주에서 
두어 개월의 간격으로 하되 더 짧은 기간을 선호하라.

비니지스 쪽의 사람들과 개발자들을 프로젝트 전체에
걸쳐 날마다 함께 일해야 한다.

동기가 부여된 개인들 중심으로 프로젝트를 구성하라.
그들이 필요로하는 환경과 지원을 주고
그들이 일을 끝내리라고 신뢰하라.

개발팀으로, 또 개발팀 내부에서 정보를 전하는 가장
효율적이고 효과적인 방법은 면대면 대화이다.

작동하는 소프트웨어가 진척의 주된 척도이다.

애자일 프로세스들은 지속 가능한 개발을 장려한다.
스폰서, 개발자, 사용자는 일정한 속도를 계속 유지 
할수 있어야 한다.

기술적 탁월성고 좋은 설계에 대한
지속적 관심이 기민함을 높인다.

단순성이 -- 안하는 일의 양을 최대화하는 기술이 -- 필수 적이다.

최고의 아키텍처, 요구사항, 설계는 
자기 조직적인 팀에서 창발한다.

팀은 정기적으로 어떻게 더 효과적이 될지
숙고하고, 이에 따라 팀의 행동을 조율하고 조정한다.

원문 : http://agilemanifesto.org/iso/ko/manifesto.html

* 현실에 안주하며, 퇴보적인 내 모습에 반성하며, 굳건히 믿는 애자일 선언문을 다시 써본다. 
언제나 그렇듯 가장 빨리, 최고의 제품을 개발하는것이 1번 순위이다.
모든것에 대해 최선인지 의심하고 하루하루 발전해나가야한다.


Tuesday, December 13, 2016

[Cracking the Coding Interview] Chap.9 System Design and Scalability.

Scalability 질문은 당신이 실제로 어떻게 일하는지를 알기위해 던져진다.
여기에 어떤 함정도, 특별한 알고리즘이 필요 한것이 아니고.
당신이 이런 문제들을 어떻게 해결하는지 보기 위함이다.

질문을 하고, 면접관과 함께 토론해야 한다.

이런 질문에 답하는 방법

이야기를 하라.
넓게 생각하라, 특정 알고리즘 혹은 특정 부분에 몰두 하지 말고, 큰 그림을 봐야 한다.
화이트 보드를 적극 활용하고, 면접관이 우려하는 점에 대해 명확히 이해하라.
조심스럽게 가정하고, 그런 가정들에 대해서 면접관에게 전파해라.
평가는 필요 할때만해라.

Design  : Step-by-Step

혼자서 문제를 풀려고 하지말고, 대화를 하면서 문제를 풀어 나가야 한다.

Step 1 : 문제의 범위 산정하기.

면접자가 요청한 문제가 내가 이해한것과 같은지 확인 해야 한다.

예 : TinyUrl

permenant 한지, UserAccount 시스팀이 필요 한지,  클릭횟수 추적이 필요 한지 등을 물어 봐야 한다. 질문이 끝나고 나면 아래와 같이 리스트업한다.

* Shortening a URL to a TinyUrl
* Analytics for a URL
* Retrieving the URL associated with a TinyURL.
* User accounts and link management.

Step 2 : Make Reasonable Assumptions

어떠한 가정을 하는건 좋지만, 항상 정당한 이유가 있어야한다.
무한한 메모리를 사용한다고 하거나, 하루에 100명만 사용한다고 하거나 하면 안된다.

Step 3 : Draw the major components

Frontend 서버나, Data Store 서버 등의 중요 컴포넌트들을 그리면 된다.
이 단계에 대해서 Scalability 같은거는 접어 두고 가능한한 간단한척 하고 그리는게 좋다.

Step 4 : Identify the Key Issues

기본적인 디자인이 완료 되면, 어떤 문제가 있을지 생각해두는게 좋다.
병목지점이라던지, 이 시스템을 만드는데 있어서 가장 큰 도전이 될만한 것들에 대해서 생각해두도록 하자.

예를들면 TinyURL은 보통 불규칙적인 접근 패턴을 가지는데, 커뮤니티등에 공유되어서 갑자기 엄청 많이 접근 될수도 있다.

Step 5: Redesign the the Key Issues.

정리한 이슈들을 해결할수 있도록 Diagram을 업데이트.
이때 당신이 디자인한 결과의 한계에 대해서 오픈마인드를 가져야한다. 면접과는 이를 인지할테고 그와 적극적으로 소통해야 한다.

Algorithms that Scale : Step-By-Step

보통은 전체 시스템을 재디자인하라고 하지 않고, 특정 기능이나 알고리즘에 대해서 다시 작성할것을 요구 받는다. 이때 명심해야 할점을 Scalability 를 고려해야한다는 점이다.

Step 1 : Ask Questions

앞서 말한것처럼 요구 사항을 제대로 인지 해야한다.

Step 2 : Make Believe

일단 무한한 메모리를 가진 머신을 통해서 처리할수 있다고 생각하고 답을 작성하라.

Step 3 : Get Real

다시 원래 문제로 돌아가서, 얼마나 많은 데이터를 한번에 처리 할수 있으며, 데이터를 쪼개었을때 나타나는 문제에 대해서 생각해봐야 한다.  보통은 한 머신이 데이터를 볼때 다른 데이터를 어떻게 찾을수 있는지가 문제이다.

Step 4 : Solve Problems

이제 발생할수 있는 문제들에 해결 방안을 제시 해야 한다. 문제가 해결 되었을 수도 있고, 아닐수도 있다. 문제가 해결 되지 않았다거나, 다른 문제가 발생하면 그문제들에 대해서 깊게 고민해야 한다. 지금 당장 완벽한 시스템을 만드는게 중요한것이 아니라, 문제를 찾아내고, 수정하고 하는 과정이 중요한것이다.

Key Concepts

Horizontal vs Vertical Scaling

* Vertical Scaling 은 특정한 node 에 대한 성능향상, 예를 들어서 메모리를 늘리는 등.

* Horizontal Scaling 은 node 수를 늘리는 방식이다. 예를 들면 서버 수를 늘려서 부하를 분산시키는것이다.

Load Balancer 

뭐 말이 필요 없는듯. 말 그대로

Database Denormalization and NoSQL

시스템이 커질수록 RDBMS 에서의 JOIN 연산이 병목지점이 된다.
Denormalization(역정규화)를 하면 이런 문제를 피할수 있다.

NoSQL을 이용해서 처리할수도 있는데, NoSQL은 관계형 DBMS가 아니기 때문에 JOIN 연산이 없고, scale하기 좋게 디자인 되어 있다.

Database Partitioning(Sharding)

DB Sharding은 데이터를 쪼개는 기능이다.

* Vertical Partitioning

가장 기초적인 샤딩 기법으로, 테이블별로 DB를 나누는 것이다.
Vertical Partitioning의 단점은 분리된 DB일지라고 그 DB가 매우 커지면 또다시 다른 방법으로 Partitioning을 해야 한다는것이다.

* Key-Base(or Hash Based) Partitioning

Key 단위로 Table을 분리하는 기법. 문제는 서버를 추가할때 마다, Data Relocating 작업을 해야 하는데, 무지하게 비싼 작업이다.

* Directory-Base Partitioning

내가 찾는 데이터가 어디 잇는지, lookup table 을 통해 관리하는것이다. 서버 추가등의 이슈에 비교적 쉽게 대응할수 있지만, 두가지 결점이 있다.
첫번째로, lookup table에 문제가 생기면, 전체 장애로 이어진다.
두번째로 lookup table에 부하가 많이 걸린다.

대부분의 architecture들을 이런 기법들을 조합해서 사용한다.

Caching

생략.

Asynchronous Processing & Queues

시간이 오래 걸리는 작업을 동기적으로 처리하면, 응답시간이 늦어 지기 때문에,  비동기로 처리해야 한다.

때때로, pre-process  하는 형식으로 처리할수도 있다. 예를 들면 포럼에서 인기 잇는 포스트와 댓글 수 등을 미리 처리 하는것이다. 아주 약간 실데이터와 차이가 있을수 있지만 대부분 용납할수준일것이다. 실시간으로 데이터를 로딩해, 느린 응답시간을 가지는 것보다 훨씬 좋은 선택이다.

또 다른 때에는, 사용자에게 기다리게하고, 작업이 완료된것을 알려줘야 할수도 있다.

Networking Metrics

* Bandwidth

한번에 보낼수 있는 최대 데이터양을 뜻한다. bps,gps 등으로 표기된다.

* Throughput

Bandwith가 한번에 보낼수 있는 최대 데이터양을 뜻하는 반면에 Throughput은 실제로 전송된 데이터의 크기를 뜻한다.

* Latency

end-to-end 과점에서 데이터가 전송되는데 걸리는 시간을 의미한다.

MapReduce

대용량 데이터를 처리하기 위한 기술.

이름에 나와 있듯이 Map 과 Reduce 로 구분된다.

* Map은 데이터를 K,V 쌍으로 나누고.
* Reduce 는 특정 K를 가지고 여러방식으로 "reduce"한후 에 새로우 K,V를 만들어 낸다. 때때로 Reduce는 추가적인 Reduce를 위해 재귀적으로 사용될수 있다.

MapReduce 는 대용량 데이터를 Scalable 하게 병렬처리하는 기법이다.

Considerations

시스템 디자인을 할때는 Key Concepts 와 별개로 몇개의 이슈에 대해 생각해봐야 한다.

* Failure

필연적으로 시스템 구성요소 오류가 나기 마련이고, 우리는 다수 혹은 모든 종류의 요소들의 오류에 대한 계획이 있어야 한다.

* Availability and Reliability

Availability 는 시스템 가용시간을 퍼센트 형태로 표기한것이다.
Reliability는 특정시간단위에 대해 시스템이 가용될수 있는 확률을 표기하는것이다.

* Read-heavy vs Write-heavy

읽기, 혹은 쓰기 편향적인 시스템이라면 디자인할때 고려해야 한다.
쓰기 편향이면, write-task를 queuing 하는 식으로 디자인할수 있다. ( 이때 쓰기 실패 일때는 대비해야 한다. ) 읽기 편향이면 cache를 꼭 넣어야 한다.

* Security

우리가 설계한 디자인에서 마주칠 Security 이슈에 대해 생각해봐야 한다.

이런 점들의 장단점에 대해 꼭 면접관과 공유 해야함을 기억해야한다.

There is no "perfect" system

어떤 시스템을 설계하든 한번에 완벽한 시스템 디자인은 없다. 언제나 장단점이 있기 마련이다. 두사람이 같은 시스템을 완전히 다르지만 훌륭하게 디자인할수 있다.

이런 질문들에 대한 우리의 목표는, 요구사항을 이해하고, 문제를 구조화 한다음, 합리적인 가정을 토대로 시스템을 디자인하는것이며, 우리가 디자인한 시스템의 약점에 대해 열린 마음으로 대하는것이다.

Wednesday, December 7, 2016

해외에서 살아보기 #1

언제부터였을까, 개발자로서의 삶이 무료하게만 느껴집니다.
도전과 모험이 넘치는 스타트업 회사들에 몸담은 지도 5년 남짓한 시간.
더는 도전과 모험들은 새롭지 않고, 개발자로서의 역량은 나아가지 않고 뒷걸음만 치고 있는듯한 기분이 듭니다.
이러한 권태를 극복해보고자 해외에서 살아보고자 합니다.

첫 회사에 다닐 때, 운이 좋게도 유럽에서 약 6개월간의 파견근무를 한 적이 있습니다.
그때 보았던 해외 인력들이 작성했던 코드들은 창의적이면서도 구조적으로도 손색이 없었던 기억이 납니다. 코드를 작성하는 일은 논리적이기도 하고 기계적이기도 하지만 개인적으로는 미적인 영역에도 속한다고 생각합니다. 저 역시 그러하지만, 논리적인 코드를 작성하는 데는 익숙하지만 아름다운 코드를 작성해내지는 못하고 있습니다. 물론, 사람에 따라 다르겠지만 새로운 환경에서 다른 문화권의 사람들과 함께 일하는 것이 저에게 많은 자극을 줄 것이라 기대해봅니다.

저는 세상에서 가장 아름다운 여성의 남편이자, 4살 여자아이의 아빠입니다.
다행히, 아내 역시 해외에 살아 보고 싶은 로망이 항상 있었기에 적극적으로 찬성하며 좋아하지만, 해외 거주시 추가로 부담해야 할 렌트비, 육아 비용, 거기에 줄어들 소득을 생각하니 아마득하긴합니다. 아직 대소변도 제대로 가릴지 모르는 아이가 낯선 곳에서 말도 통하지 않는 친구와 선생님을 만나 잘 적응 할 수 있을지도 무척 걱정됩니다.

모든 도전이 그러하듯이 기대와 희망, 그리고 걱정과 불안이 동반합니다. 일단 실행하고 걱정과 불안은 그때그때 슬기롭게 해결할 수 있길 바라며, "해외에서 살아보기" 프로젝트를 시작해 봅니다.


Sunday, November 20, 2016

Lookup expressjs #2 lib/application.js

* application.js



var compileETag = require('./utils').compileETag;

var slice = Array.prototype.slice;


이처럼 function들을 즉각적으로 사용하지 않고,  variable로 사용하는 컨벤션이 있는데,
딱히 좋은지는 모르겠습니다.

compleEtag function 은 그렇다 치더라도,
slice 의 경우 코드에서 Array.prototype.slice 인지, user defined 된 slice 라는걸 알기 어렵다는 단점이 우선 눈에 띕니다..

좋은 점은 반복적으로 사용되면, 코드를 줄이는 효과가 있을것 같기는 한데,
slice 와 같이 well-known function 에 대해서 user define 하지 않는다는 규칙이 Team 에 존재한다면 괜찮을수 있다 생각됩니다.

그렇지만, new member가 숙지해야 될 규칙이 하나더 생기기에 역시 그렇게 좋은 효과로 보기 어렵습니다.


application.js 는 expressjs application 설정등 초기화하고, application life cycle 로 판단되는데, 일단 살펴 봐야 겠습니다.


app.defaultConfiguration = function defaultConfiguration() {

  var env = process.env.NODE_ENV || 'development';



.....



  debug('booting in %s mode', env);



  this.on('mount', function onmount(parent) {

    // inherit trust proxy

    if (this.settings[trustProxyDefaultSymbol] === true

      && typeof parent.settings['trust proxy fn'] === 'function') {

      delete this.settings['trust proxy'];

      delete this.settings['trust proxy fn'];

    }



    // inherit protos

    this.request.__proto__ = parent.request;

    this.response.__proto__ = parent.response;

    this.engines.__proto__ = parent.engines;

    this.settings.__proto__ = parent.settings;

  });



 ....



  if (env === 'production') {

    this.enable('view cache');

  }



  ...

};


init() -> defaultConfiguration() 을 호출 하는데, 보시는 바와 같이 NODE_ENV 등의 각종 설정들이 초기화 됩니다.
한가지, production 모드 일때 view cache 가 활성화되는걸 볼수 있네요.
이점은 좀 유의 해야 할 필요가 있는것 같습니다.


Look up expressjs #1 ./lib/express.js

개발자로써의 삶을 나태하게 보내는것에 대한 반성으로, 원래 좋아하던 오픈소스 뜯어 보기를 다시한번 하고자 합니다.

지금 주력으로 개발하고 있는 것은 nodejs + expressjs 입니다.
nodejs 는  원래 먼저 보고자 했는데, cpp 로 작성된 프로젝트 이기도 하고, nodejs 코딩 컨벤션에 대해서 좀더 알고 싶은 욕구를 해소하기 위해 expressjs 로 선정했습니다.

* expressjs ( http://express.js.com )

사이트 소개에 따르면 expressjs 는 경량하고도 유여한 Web Application Framework 입니다.
대부분의 nodejs로 구춘된 web application 은 expressjs 를 사용하고 있으며, 저도 현재 프로젝트에 사용하고 있습니다.

원래 이런 framework 선정 전에 먼저 살펴보고, 대안을 찾아 보고 장단점을 비교해봐야 하는데 귀찮아서 바빠서 이과정을 생략하고 도입했습니다. 참 바보 같은 삶을 살고 있습니다.

지금이라도 늦기전에 살펴보도록 하겠습니다.

* index.js , lib/express.js

두파일이 expressjs lookup journey 의 입구 입니다.
예측해보건데, index.js 는 껍데기 이고, lib/express.js 는 좀더 디테일 한 껍데기 일것입니다.

네 index.js 는 lib/express.js를 require하여 export 하는 역할만 하니, skip
lib/express.js 를 살펴보겠습니다.

이 파일도 역시 application.js router.js response.js request.js 를 require 하는 껍데기에 가까운데, application object 생성하는 createApplication() function 이 정의 되어있고, 일부 deprecated method 에 대한 warning 을 담당하고 있습니다.


function createApplication() {

  var app = function(req, res, next) {

    app.handle(req, res, next);

  };



  mixin(app, EventEmitter.prototype, false);

  mixin(app, proto, false);



  app.request = { __proto__: req, app: app };

  app.response = { __proto__: res, app: app };

  app.init();

  return app;

}


음.. 모르는게 한두가지 보이네요
mixin 과 __proto__

* mixin

https://en.wikipedia.org/wiki/Mixin

mixin 은 다른 class 의 method 를 상속하지(inherit) 하지 않고, 가져오는 (include) 개념이다.
언어에 따라 include 라고 하기도 한다고 하니, 그정도로 이해할수 있겠다.

nodejs application object가 EventEmitter와 proto를 mix 인해서 사용하는것으로 보면 될테고,
app 내에서, request, response module을 접근하고자 app.request, app.requese할 assign 하는 개념으로 보면 될것이다.

음.. 여기서 proto 는 또 뭐지 ㅎ


var proto = require('./application');


proto 는 application module 임으로, application은  EventEmitter, Application 모듈이 mixin 되었다고 보면 되겠다.


* __proto__

http://i5on9i.blogspot.kr/2014/09/proto-prototype.html

Tuesday, September 27, 2016

User Interface Testing - Testing with Xcode


Concepts and APIs

UI Testing 은 unit testing과 근본적으로 다르다.
Unit Testing은 app 스코프안에서 앱의 변수, 상태 등등을 전체적으로 접근 하며, function이나 method를 테스트 한다.
반면에 UI Testing은 User Level에서 테스트함으로 앱안의 함수등을 접근 할수 없다.
즉 User 관점에서 테스트 하는것이다.

APIs

- XCUIApplication
- XCUIElement
- XCUIElementQuery

** 가이드 문서에 별다른 내용이 없다 ㅠ
이건 가이드라기 보다 introduction에 가까운거 아닌가, 맨땅에 헤딩좀 해야 겠다.

Writing Tests of Asynchronous Operations- Testing with Xcode


XCTest에서 expectation 을 통해 Async Op.을 테스트 할수 있다.
XCTestCase+AsynchronousTesting.h 참조.


// Test that the document is opened. Because opening is asynchronous,

// use XCTestCase's asynchronous APIs to wait until the document has

// finished opening.

- (void)testDocumentOpening

{

    // Create an expectation object.

    // This test only has one, but it's possible to wait on multiple expectations.

    XCTestExpectation *documentOpenExpectation = [self expectationWithDescription:@"document open"];



    NSURL *URL = [[NSBundle bundleForClass:[self class]]

                              URLForResource:@"TestDocument" withExtension:@"mydoc"];

    UIDocument *doc = [[UIDocument alloc] initWithFileURL:URL];

    [doc openWithCompletionHandler:^(BOOL success) {

        XCTAssert(success);

        // Possibly assert other things here about the document after it has opened...



        // Fulfill the expectation-this will cause -waitForExpectation

        // to invoke its completion handler and then return.

        [documentOpenExpectation fulfill];

    }];



    // The test will pause here, running the run loop, until the timeout is hit

    // or all expectations are fulfilled.

    [self waitForExpectationsWithTimeout:1 handler:^(NSError *error) {

        [doc closeWithCompletionHandler:nil];

    }];

}


Test Basics - Testing with Xcode


* 모든 소프트웨어는 각 컴포턴트(혹은 모듈을) 조합함으로써 만들어지고,
좋은 테스트라함은 해당 소프트웨어의 기능을 모두 아우를수 있는 레벨의 ( 콤포넌트 단위/ 혹은 콤포넌트를 조합하는 High Level)의 테스트를 수행하는것이다.
이를 위해 XCTests가 있다.


* Unit Tests

하위레벨의 콤포넌트(Model, ViewController, etc)를 테스트 하기에 적합.

> xcode 는 앱 뿐만 아니라, Library도 테스트 할수 있게, App/Library 두가지의 Context를 제공한다.

* Performance Mesure

특정 연산에 대한 성능 분석

* UI Tests.

어플리케이션의 workflow를 테스트 할수 있는 도구.



공부하는 사람.

공부하는 사람.

내가 소프트웨어 엔지니어링을 매력적으로 느끼고, 직업으로 삼게 된 가장 큰 계기는,
이 직업은 꾸준히 공부할 수 있는, 아니 해야만 하는 직업이기 때문이다.

요 몇 년 나는 제대로 된 공부를 하지 않았다.
새로운 기술을 익히고 프로젝트에 적용 하는 것은 그 이전에도 해왔던 것으로 나에게 공부 코스트가 그렇게 큰일은 아니다.

삶의 권태를 느끼고 나를 둘러싼 환경을 변화시키고자 아등바등하고 있는 요즘,
또 한 번 내 이런 모습을 실감하고 나 자신부터 다시 붙잡고자 노력하고 있다.

공부하는 사람.
참 아름다운 말 아닌가. 꾸준히 나아가보자.

Monday, September 26, 2016

Testing with Xcode.


  • Quick Start. Beginning with Xcode 5 and the introduction of the XCTest framework, the process of configuring projects for testing has been streamlined and automated with the test navigator to ease bringing tests up and running.
  • Performance Measurement. Xcode 6 and later includes the ability to create tests that allow you to measure and track performance changes against a baseline.
  • UI Testing. Xcode 7 adds capabilities for writing tests that exercise an app’s UI. It includes the ability to record UI interactions into source code that you can transform into tests.
  • Continuous Integration and Xcode Server. Xcode tests can be executed using command-line scripts or configured to be executed by bots on a Mac running Xcode Server automatically.
  • Modernization. Xcode includes a migrator for converting projects that have OCUnit tests to have XCTest tests. 


See Also



Monday, February 29, 2016

블로깅의 재시작.

2010년이 마지막 포스트 였네요.

최근 몇년사이, 개발에 관심이 좀 떨어진것도 사실.
그에 따른 성능저하도 사실.

모든것을 인정하고 다시 시작한다는 기분으로 블로깅을 다시시작.

요새 관심 많은 nodejs 와 새롭게 꾸린 팀 Management에 대한 고민들로 가득찰듯합니다.