D3의 코드 일부를 감상해보자.

// 다른 전역 변수와 충돌을 피하기 위해 이름공간을 생성한다.
var rj3 = {}

// svg라는 하위 이름공간을 만든다.
rj3.svg = {}

// rj3.svg라는 이름공간에 line함수를 넣는다.
rj3.svg.line = function(){
  var getX = function(point){
    return point[0]
  },
  getY = function(point){
    return point[1]
  },
  interpolate = function(points){
    return points.join('L')
  };

  function line(data){
    var segments = [],
        points = [],
        i = -1,
        n = data.length,
        g;

    function segment(){
      segments.push("M", interpolate(points))
    }

    while(++i < n){
      d = data[i]
      points.push([+getX.call(this,d,i),+getY.call(this,d,i)])
    }

    if (points.length) {
      segment()
    }

    return segments.length ? segments.join('') : null
  }
}

line.x = function(funcToGetX){
  if(!arguments.length) return getX
  getX = funcToGetx
  return line
}

line.y = function(funcToGetY){
  if(!arguments.length) return getY
  getY = funcToGetY
  return line
}

3번보고 이해됨.. 이게 아무렇지 않게 이해될때쯤이면 나는 지금보단 나은 js개발자

TDD

TDD는 애플리케이션코드를 짜기 전에 이 코드가 통과해야 할 단위 테스트를 먼저 작성한다. 마치 애플리케이션을 개발하듯 전체 단위 테스트(unit test) 꾸러미를 만들어 가는 TDD방식을 따르면 단위 정의와 인터페이스 설계에 도움이 많이 된다.

TDD를 실천하는 개발자는 애플리케이션에 어떤 변화가 생길 때마다 다음 단계를 밟는다. 여기서 변화란 완전히 새로운 기능을 추가하거나 기존 시스템을 고치고 버그를 잡는 일니다.

  1. 완벽히 변경하면 성공하나 그렇게 되기 전까지 반드시 실패하는 단위 테스트를 작성한다.(transaction같은거?)
  2. 테스트가 성공할 수 있을 만큼만 최소한으로 코딩한다.
  3. 애플리케이션 코드를 리팩토링하며 중복을 제거한다.

이세단계를 흔이 적색,녹색,리팩터라고 줄여말한다. 적색과 녹색은 각각 새 단위 테스트의 실패와 성공 상태를 가리킨다.

var Users = Users || {}

Users.registration = function(){
  return {
    validateAndRegisterUser: function validateAndDisplayUser(user){
      if(!user || user.name === "" || 
        user.password === "" || 
        user.password.length < 6){
        throw new Error("사용자 인증 실패")
      }

      $.post("http://example.com/user", user)

      $("#user-message").text("가입해주셔서 감사합니다, " + user.name + "님")
    }
  }
}

이함수가 하는 일은 세가지다.

  • user 객체가 올바르게 채워졌는지 검증
  • 검증을 마치면 user객체를 서버로 전송
  • ui에 메시지 표시

관심사는 세가지로 요약된다.

  • 사용자 검증
  • 서버와 직접통신
  • ui직접 다루기

validateAndRegisterUser 함수가 잘 작동하는지 테스트할 조건을 모두 나열해보자.

  • user가 falsy한 값인지 확인(undefined, null 등)
  • user의 name프로퍼티와 password가 비어있으면 에러발생
  • password프로퍼티는 6자 이하이면 에러발생
  • 에러가 발라생하면 서버에 전송하지 않는다.
  • 서버에 전송하지 않으면 메시지를 띄우지도 않는다.
  • 등등등..

테스트할 조건들이 많은데 이 모든 조건들을 validateAndRegisterUser 함수에 모두 맡기지 않고, 관심사에 따라 별개의 객체에서 담당하면 어떻까?

var Users = Users || {}
Users.registration = function(userValidator, userRegister, userDisplay){
    return{
        validateAndRegisterUser: function validateAndDisplayUser(user){
            if(!userValidator.userIsValid(user)){
                throw new Error("사용자 인증실패")
            }
            userRegister.registerUser(user)
            userDisplay.showRegistrationThankYou(user) // 이건ㅋㅋㅋㅋㅋㅋ좀웃긴데 ㅋㅋt
        }
    }
}

서로 다른 관심사는 작고 간단한 모듈로 나누어 만들면 코드작성과 테스트, 그리고 이해가 쉽다. 이런식으로 만든 코드는 장기적으로도 별탈 없이 작동할 가능성이 크다.

TDD를 실천하면 여러가지 혜택이 있다. 첫째, 장기적인 믿음성을 보장하는 단위 테스트 꾸러미를 구축한다. 둘째, 애플리케이션 객체에서 적확한 인터네피스를 설계 할 때 도움이 된다. 셋째, 놀랍게도 단위 테스트를 통해 코드를 더빨리 개발할 수 있다.

results matching ""

    No results matching ""