메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

혁신적인 아키텍처와 창발적 설계: DSL 사용하기

도메인 특정 언어를 사용하여 관용적 도메인 패턴 캡처

Neal Ford, 소프트웨어 아키텍트, IBM
Neal Ford사진
Neal Ford는 글로벌 IT 컨설팅 업체인 ThoughtWorks의 소프트웨어 아키텍트이자 Meme Wrangler이다. 애플리케이션, 교육용 자료, 매거진 기사 및 비디오/DVD 프리젠테이션을 설계 및 개발하며 다양한 기술과 관련된 서적의 저자 또는 편집자이기도 하다. 최근에 출판된 책으로는 The Productive Programmer가 있다. 대규모 엔터프라이즈 애플리케이션의 설계 및 빌드에 많은 관심을 가지고 있는 그는 전세계의 개발자 컨퍼런스에서 국제적으로 인정 받고 있는 연사로도 활동하고 있다. 그의 웹 사이트를 살펴보자.

요약:  지금까지 Evolutionary architecture and emergent design은 기술적 패턴을 위한 창발적 설계에 주로 주목했습니다. 이번 회에서는 도메인 특정 언어(DSL) 기술을 사용하여 도메인 관용적 패턴 캡처를 다룹니다. 시리즈 저자인 Neal Ford는 예제로 해당 접근방식을 설명하며 관용적 패턴을 채취하기 위해 이러한 추상 스타일의 이점을 보여줍니다.

이 연재 자세히 보기

원문 게재일:  2011 년 6 월 14 일
난이도: 중급 원문:  보기 PDF:  A4 and Letter (58KB | 11 pages)Get Adobe® Reader®
페이지뷰:  6695 회
의견:  


관용적 패턴은 기술 또는 도메인 중 하나가 될 수 있다. 기술 패턴은 유효성 검증, 보안 및 트랜잭션형 데이터를 애플리케이션(또는 애플리케이션 세트) 내에서 처리하는 방법과 같은 일반적인 기술 소프트웨어 문제에 솔루션을 표현한다. 이전 회에서는 메타프로그래밍과 같은 기술을 사용하여 기술 관용적 패턴을 채취하는 것에 집중해왔다. 도메인 패턴은 일반적인 비즈니스 문제를 추상화하는 방법에 관심이 있다. 기술적 패턴이 가상으로 모든 종류의 소프트웨어에 표시되는 반면, 도메인 패턴은 하나의 비즈니스가 다른 비즈니스와 구별되는 것과 마찬가지로 다른 도메인 패턴과 구별된다. 하지만, 풍부한 기술 세트가 이를 채취하기 위해 존재하며, 이는 이 시리즈의 이번 회 및 다음 몇 회차의 주제이다.

이 시리즈의 정보

시리즈의 목적은 소프트웨어 아키텍처 및 설계와 관련하여 자주 논의되지만 정의를 명확하게 내리기 어려운 개념에 대한 신선한 관점을 제공하는 것이다. Neal Ford는 구체적인 예제를 통해 실제 애자일 개발 환경에서 경험하게 되는 혁신적 아키텍처창발적 설계에 대한 견고한 기초 지식을 제공한다. 중요한 아키텍처 및 설계 결정을 최후의 결정 순간까지 미룸으로써 소프트웨어 프로젝트에 해가 되는 불필요한 복잡성을 방지할 수 있다.

이 기사는 도메인 패턴을 채취하기 위한 추상 스타일로 DSL 기술을 사용하는 것에 대한 동기를 부여한다. DSL은 자체적인 패턴 명명법을 비롯하여 풍부한 옵션을 제공한다. Martin Fowler의 가장 최신 저서는 DSL 기술에 대해 심도있게 파헤쳐 조사한다(참고자료 참조). 필자가 특정 기술을 선보이기 시작하면서 다음 회차에서는 그의 패턴 이름 다수 및 그와 필자의 자체적인 예제를 혼합하여 사용할 것이다.

DSL에 대한 동기

고작 관용적 패턴을 채취하기 위해서 왜 DSL 작성의 모든 고충을 겪으려 하는가? 필자가 "Leveraging reusable code, Part 2"에서 지적한 대로, 관용적 패턴과 나머지 코드를 차별화하는 가장 훌륭한 방법은 다르게 보이도록 만드는 것이다. 이 시각적 차이는 정규 API를 살펴보지 않는다는 즉각적인 단서이다. 마찬가지로 DSL 사용의 목표 중 하나는 소스 코드처럼 보이지 않게 하고, 해결하려고 시도 중인 문제처럼 보이게 하는 것이다. 이 목표를 달성할 수 있으면(또는 심지어 지금보다 더 가까워지면), 대부분의 소프트웨어 프로젝트에서 중요한 간격인 개발자와 비즈니스 당사자들 사이의 의사소통을 연결하게 된다. 사용자의 코드 읽기를 허용하는 것은 오류가 발생하기 쉬운 태스크인 코드를 자국어로 변환할 필요성이 없어지기 때문에 큰 이점이다. 소프트웨어가 수행해야 하는 내용을 알고 있는 기술자 외의 사람들이 코드를 읽을 수 있도록 하여, 이들과 더 긴밀한 대화를 나눌 수 있다.

이 기술을 사용하기 위해 동기를 부여하는 방법으로 Fowler의 DSL 저서에서 그의 예제를 하나 차용할 것이다(참고자료 참조). 소프트웨어로 제어되는 밀실을 만드는 회사를 위해 작업한다고 가정하자(제임스 본드를 생각해봐라). 회사의 클라이언트 중 하나인 H여사는 침실에 밀실을 설치해주기를 원한다. 하지만 필자의 회사는 소프트웨어를 실행하기 위해 닷컴 습격의 잔재인 Java™ 구동 토스터(toaster)를 사용한다. 비록 토스터가 저렴하다고 해도 그 곳에서 소프트웨어를 다시 활성화하는 것은 비용이 많이 든다. 따라서, 기본 밀실 코드를 작성하고 토스터에 이를 영구적으로 넣은 다음 각 개별 클라이언트의 밀실 요구를 구성하는 방법을 알아봐야 한다. 독자도 인식하는 것처럼 이는 오늘날 소프트웨어 업계의 공통적인 문제이다. 즉, 자주 변경하지 않는 일반 작동이 개별 상황에 대해 변경할 수 있는 구성으로 커플링되는 것이다.

H여사는 먼저 독자가 침실 문을 닫을 때에 밀실이 열리고, 그 다음으로 옷장 두 번째 서랍이 열리며, 마지막으로 침실 등을 켜는 밀실을 원한다. 이러한 활동은 순서대로 발생해야 하고, 어디서나 순서를 중단하면 처음부터 다시 시작해야 한다. 그림 1에서 상태 머신이 설명하는 것과 같이 해당 밀실을 제어하는 소프트웨어를 상상할 수 있다.


그림 1. 상태 머신으로서 H여사의 밀실
상태 머신 다이어그램

내재된 상태 머신 API는 간단하다. 필자는 목록 1과 같이 추상 이벤트 클래스를 작성한다. 이는 다음과 같이 이벤트와 명령을 상태 머신 내에서 처리한다.


목록 1. 상태 머신에 대한 추상 이벤트

public class AbstractEvent {
  private String name, code;

  public AbstractEvent(String name, String code) {
    this.name = name;
    this.code = code;
  }
  public String getCode() { return code;}
  public String getName() { return name;}   

다음 목록 2와 같이 States라는 또 다른 간단한 클래스로 상태 머신에서 상태를 모델링할 수 있다.


목록 2. 상태 머신 클래스의 시작

public class States {
  private State content;
  private List<TransitionBuilder> transitions = new ArrayList<TransitionBuilder>();
  private List<Commands> commands = new ArrayList<Commands>();

  public States(String name, StateMachineBuilder builder) {
    super(name, builder);
    content = new State(name);
  }

  State getState() {
    return content;
  }

  public States actions(Commands... identifiers) {
    builder.definingState(this);
    commands.addAll(Arrays.asList(identifiers));
    return this;
  }


  public TransitionBuilder transition(Events identifier) {
    builder.definingState(this);
    return new TransitionBuilder(this, identifier);
  }

  void addTransition(TransitionBuilder arg) {
    transitions.add(arg);
  }


  void produce() {
    for (Commands c : commands)
      content.addAction(c.getCommand());
    for (TransitionBuilder t : transitions)
      t.produce();
  }
}

여기에서 목록 1목록 2는 참조용에 불과하다. 해결할 흥미로운 문제는 상태 머신의 구성 표현이다. 이 표현은 밀실 설치의 비즈니스를 위한 관용적 패턴이다. 다음 목록 3에서는 상태 머신에 대한 Java 기반 구성을 보여준다.


목록 3. 하나의 구성 옵션: Java 코드

Event doorClosed = new Event("doorClosed", "D1CL");
Event drawerOpened = new Event("drawerOpened", "D2OP");
Event lightOn = new Event("lightOn", "L1ON");
Event doorOpened = new Event("doorOpened", "D1OP");
Event panelClosed = new Event("panelClosed", "PNCL");

Command unlockPanelCmd = new Command("unlockPanel", "PNUL");
Command lockPanelCmd = new Command("lockPanel", "PNLK");
Command lockDoorCmd = new Command("lockDoor", "D1LK");
Command unlockDoorCmd = new Command("unlockDoor", "D1UL");

State idle = new State("idle");
State activeState = new State("active");
State waitingForLightState = new State("waitingForLight");
State waitingForDrawerState = new State("waitingForDrawer");
State unlockedPanelState = new State("unlockedPanel");

StateMachine machine = new StateMachine(idle);

idle.addTransition(doorClosed, activeState);
idle.addAction(unlockDoorCmd);
idle.addAction(lockPanelCmd);

activeState.addTransition(drawerOpened, waitingForLightState);
activeState.addTransition(lightOn, waitingForDrawerState);

waitingForLightState.addTransition(lightOn, unlockedPanelState);

waitingForDrawerState.addTransition(drawerOpened, unlockedPanelState);

unlockedPanelState.addAction(unlockPanelCmd);
unlockedPanelState.addAction(lockDoorCmd);
unlockedPanelState.addTransition(panelClosed, idle);

machine.addResetEvents(doorOpened);


목록 3은 상태 머신의 구성에 대한 Java 코드를 사용하여 몇 가지 문제점을 강조한다. 첫 번째로, 이 내용을 읽어도 내용이 상태 머신에 대한 구성이라는 것이 명확하지 않다. 이는 대부분의 Java API와 같이 차별화되지 않은 코드의 파일이다. 두 번째로 이는 복잡하고 반복적이다. 예를 들어, 필자가 상태 머신의 각 부분에 대해 상태와 전이를 더 설정하면 할수록 변수 이름이 여러 번 되풀이되어 사용된다. 이 모든 중복으로 인해 코드 읽기가 더 어려워진다. 세 번째로, 이 코드는 코드를 재컴파일하지 않고 밀실이 구성 가능하게 되는 원래의 목표에 부합하지 않는다.

실제로 구성 코드에 대해 XML을 선호하는 경향이 있는 Java 영역에서 이와 같은 코드는 더 이상 나타나지 않는다. 목록 4와 같이 XML에서 구성을 쓰는 것은 간단하다.


목록 4. XML에서 상태 머신 구성

<stateMachine start = "idle">
    <event name="doorClosed" code="D1CL"/>
    <event name="drawerOpened" code="D2OP"/>
    <event name="lightOn" code="L1ON"/>
    <event name="doorOpened" code="D1OP"/>
    <event name="panelClosed" code="PNCL"/>

    <command name="unlockPanel" code="PNUL"/>
    <command name="lockPanel" code="PNLK"/>
    <command name="lockDoor" code="D1LK"/>
    <command name="unlockDoor" code="D1UL"/>

  <state name="idle">
    <transition event="doorClosed" target="active"/>
    <action command="unlockDoor"/>
    <action command="lockPanel"/>
  </state>

  <state name="active">
    <transition event="drawerOpened" target="waitingForLight"/>
    <transition event="lightOn" target="waitingForDrawer"/>
  </state>

  <state name="waitingForLight">
    <transition event="lightOn" target="unlockedPanel"/>
  </state>

  <state name="waitingForDrawer">
    <transition event="drawerOpened" target="unlockedPanel"/>
  </state>

  <state name="unlockedPanel">
    <action command="unlockPanel"/>
    <action command="lockDoor"/>    
    <transition event="panelClosed" target="idle"/>
   </state>

  <resetEvent name = "doorOpened"/>
</stateMachine>         

목록 4의 코드는 Java 버전보다 몇 가지 장점이 있다. 첫 번째로 지연 바인딩(late binding)이 있다. 이는 구성 코드를 변경하여 토스터에 넣을 수 있어, XML 구문 분석기가 새 구성을 읽도록 허용한다. 두 번째로, 특정한 문제점에 대해 이 코드는 XML이 컨테이너십(containership)의 개념을 포함하기 때문에 훨씬 더 표현적이다. 즉, 상태는 하위 요소로 해당 구성을 포함한다. 이는 Java 버전에서 나타나는 골치 아픈 중복성을 제거하는 데 유용하다. 세 번째로, 이 코드는 내재적으로 선언적이다. 선언적 코드는 종종 명령문을 작성하기만 하고 ifwhile 구문이 필요하지 않는 경우 읽기에 훨씬 더 간편하다.

잠깐 물러 서서 포함 내용을 살펴보자. 구성을 외부화하는 것은 이를 더 이상 구별된 엔티티로 고려하지 않는 현대의 Java 영역에서 일반적인 패턴이다. 하지만, 이는 가상적으로 모든 Java 프레임워크의 기능이다. 구성은 관용적 패턴이며, 주변 프레임워크의 일반 작동에서 이를 분리하고 차별화하는 이를 캡처하는 방법이 필요하다. 필자는 구성에 XML을 사용하여 외부 DSL(구문이 XML이고 문법은 이 XML 문서와 연관된 스키마로 정의됨)에서 코드를 쓰고 있으므로 이를 변경하기 위해 프레임워크 코드를 재컴파일할 필요가 없다.

XML을 활용하기 위해 XML로 전부 진행할 필요가 없다. 다음 목록 5와 같이 구성 코드의 버전을 고려하자.


목록 5. 사용자 정의 문법 상태 머신 구성

events
  doorClosed  D1CL
  drawerOpened  D2OP
  lightOn     L1ON
  doorOpened  D1OP
  panelClosed PNCL
end

resetEvents
  doorOpened
end

commands
  unlockPanel PNUL
  lockPanel   PNLK
  lockDoor    D1LK
  unlockDoor  D1UL
end

state idle
  actions {unlockDoor lockPanel}
  doorClosed => active
end

state active
  drawerOpened => waitingForLight
  lightOn    => waitingForDrawer
end

state waitingForLight
  lightOn => unlockedPanel
end

state waitingForDrawer
  drawerOpened => unlockedPanel
end

state unlockedPanel
  actions {unlockPanel lockDoor}
  panelClosed => idle
end

이 버전의 코드는 XML 버전의 많은 이점을 보유한다. 즉, 이는 선언적이며 컨테이너십이 있으며 간결하다. 이는 XML과 Java 버전보다 더 유리하다. 왜냐하면 이는 기술 구현에 필요하지만 가독성에 해를 끼치는 소음 문자(예: < and >)를 더 적게 보유한다.

이 버전의 구성 코드는 ANTLR을 사용하여 쓰인 사용자 정의 외부 DSL이다. 이는 사용자 정의 언어를 쓰기 쉽게 만드는 오픈 소스 도구이다(참고자료 참조). 대학교에서 컴파일러 클래스(Lex와 YACC 및 기타 등등 포함)로 인해 골치가 아팠던 기억이 있는 독자라면 해당 도구가 훨씬 더 나아졌다는 것을 안다면 흡족할 것이다. 이 예제는 Fowler의 저서에서 뽑은 것이고, 그는 XML 버전을 빌드하는 것과 사용자 정의 언어 버전을 빌드하는 데 동일한 시간이 걸렸다고 말한다.

다음 목록 6에 Ruby에 쓰여진 또 다른 대안이 들어있다.


목록 6. JRuby에서 상태 머신 구성

event :doorClosed, "D1CL"
event :drawerOpened, "D2OP"
event :lightOn, "L1ON"
event :doorOpened, "D1OP"
event :panelClosed, "PNCL"

command :unlockPanel, "PNUL"
command :lockPanel, "PNLK"
command :lockDoor, "D1LK"
command :unlockDoor, "D1UL"

resetEvents :doorOpened

state :idle do
  actions :unlockDoor, :lockPanel
  transitions :doorClosed => :active
end

state :active do
  transitions :drawerOpened => :waitingForLight,
              :lightOn => :waitingForDrawer
end

state :waitingForLight do
  transitions :lightOn => :unlockedPanel
end

state :waitingForDrawer do
  transitions :drawerOpened => :unlockedPanel
end

state :unlockedPanel do
  actions :unlockPanel, :lockDoor
  transitions :panelClosed => :idle
end   

이는 내부 DSL의 훌륭한 예제이다. 즉, 이는 기본 언어의 구문을 사용하는 DSL이며, 이 DSL은 구문적으로 법적 Ruby 코드이어야 함을 의미한다. (이는 Ruby에 쓰였기 때문에, 독자가 JRuby를 통해 이를 실행할 수 있으며, 이는 토스터가 필요한 전부가 JRuby JAR 파일임을 의미한다.)

목록 6은 사용자 정의 언어와 동일한 장점을 많이 보유한다. 컨테이너로 작동하기 위해 Ruby 블록을 많이 사용한 것에 주목하자. 이는 XML과 사용자 정의 언어 버전과 동일한 종류의 컨테이너십 시맨틱을 제공한다. 이는 사용자 정의 언어보다 소음 문자를 조금 더 많이 사용한다. 예를 들어, Ruby에서 : 접두부는 기호를 표시하며, 이는 기본적으로 이 경우에 ID로 사용되는 불변 문자이다.

목록 7과 같이 Ruby에서 이러한 종류의 DSL을 구현하는 것은 매우 간단하다.


목록 7. JRuby DSL에 대한 부분적 클래스 정의

class StateMachineBuilder
  attr_reader :machine, :events, :states, :commands

  def initialize
    @events = {}
    @states = {}
    @state_blocks = {}
    @commands = {}
  end

  def event name, code
    @events[name] = Event.new(name.to_s, code)
  end

  def state name, &block
    @states[name] = State.new(name.to_s)
    @state_blocks[name] = block
    @start_state ||= @states[name]
  end

  def command name, code
    @commands[name] = Command.new(name.to_s, code)
  end

Ruby는 구문에 대해 유연한 규칙이 있으며, 이는 DSL의 이러한 유형에 매우 잘 맞게 해준다. 예를 들어, 이벤트를 선언할 때에 메소드 호출의 일환으로 괄호를 포함하도록 강제 실행되지 않았다. 이 버전에서 자체적인 언어를 쓰거나 꺾쇠괄호로 스스로 괴롭힐 필요가 없다. 이 내용은 Ruby 영역에서 왜 이러한 접근방식이 매우 대중적인지 보여주는 데 유용하다.


DSL의 특성

DSL은 관용적 패턴을 캡처링하기 위해 훌륭한 대안 구문을 제공한다. Martin Fowler가 정의한 대로, DSL은 다섯 가지 핵심 특성이 있다.

컴퓨터 프로그래밍 언어

언어가 DSL이 되려면 컴퓨터 프로그래밍 언어이어야 한다. 이러한 제한사항을 정하지 않으면 독자가 접하는 모든 것이 DSL이라는 안 좋은 길로 빠지기 쉽다. DSL이라는 용어를 너무 광범위하게 정의하면, 컨텍스트화된 모든 대화가 DSL이 될 것이다. 예를 들어, 필자의 동료 중 크리켓 애호가들이 있다. 그들과 같이 걸어가면서 크리켓에 대해 이야기하면 그들이 영어로 이야기하고 있어도 필자는 무슨 내용인지 이해할 수가 없다. 필자는 그들이 이러한 단어를 사용하는 방식을 이해하기 위한 적절한 컨텍스트가 없다. 따라서, 독자는 크리켓과 다른 스포츠의 용어에 DSL이 있다고 따질 수도 있다. 하지만, 정의를 이렇게 광범위하게 두는 것은 유용한 제한조건으로 좁히기 어려워진다 — 그 이유로 컴퓨터 프로그래밍 언어로 이를 제한하는 것에 대해 Fowler가 주장함—.

언어 본질

Fowler의 DSL에 대한 두 번째 기준은 이는 "언어 본질"을 보유한다는 것이며, 이는 DSL이 프로그래머 외의 사람들이 읽기에 적어도 모호하게는 되어야 한다는 점을 뜻한다. 이 언어 본질은 다양한 양식을 취할 수 있으며, 필자가 관용적 패턴을 캡처하는 하나의 방법으로 DSL의 사용을 계속 연구하면서 다음 회차에서 이 중 다수를 소개할 것이다.

도메인 집중

언어가 올바른 DSL이 되려면 특정 문제점 도메인에 제한적으로 집중되어야 한다. DSL을 작성하려는 노력의 위험 중 하나는 이를 너무 광범위하게 만드는 것이다. DSL은 추상 메커니즘이며, 너무 광범위한 추상을 작성하면 추상의 이점이 줄어든다.

제한된 표현력

이는 제한된 표현력을 가지기 위한 DSL의 일반적 성향이다. 예를 들어, 루핑과 의사결정과 같은 제어 구조를 포함한 DSL을 찾는 것은 매우 드물다. DSL은 설명하려고 시도하는 해당 도메인에 온전히 특정하게 집중되어야 한다. 결과적으로 많은 수의 DSL이 명령적이라기 보다는 선언적이다.

튜링 완료되지 않음

앞선 두 가지 기준은 이러한 특성을 제안하지만, 여기에서 이를 공식화할 것이다. DSL은 튜링 완료되지 않아야 한다(참고자료 참조). 실제로 이는 우연히 튜링 완료되기 위해 DSL에서 안티패턴으로 고려된다. 예를 들어, 기존 UNIX® sendmail 구성 파일은 우연히 튜링 완료된다. 독자가 그 쪽으로 마음이 가고 여유 시간이 매우 많다면 운영 체제를 sendmail 구성 파일로 쓸 수 있었다.

이는 우연히 튜링 완료되기 위해 놀랍도록 간편하다. 일부 익숙한 인프라 도구는 변이를 우연히 제작하였다 — 그 예는 XSLT이다. 언어가 DSL인지 여부에 대한 결정은 종종 사용되는 경우에 컨텍스트에 의존한다. XSLT를 사용하여 텍스트를 하나의 버전에서 다른 버전으로 변환하기 위해 사용할 때에, 이를 DSL로 사용하는 것이다. 독자가 하노이 탑(Towers of Hanoi) 문제를 해결하기 위해 XSLT를 사용하는 경우 튜링 완료 언어로 이를 사용하는 것이다(그리고 새로운 취미를 찾기 위해 노력해야 한다).


요약

필자는 이번 회에서 관용적 패턴을 채취하기 위한 추출 메커니즘으로서 DSL을 사용하기 위한 초석을 다졌다. DSL은 정규 API와 간편하게 차별화되고, 본질적으로 선언적으로 되려는 경향이 있으며, 개발자와 개발자 외의 사람들 사이에 프로젝트에 대한 의사소통 피드백 루프를 개선하기 때문에, 이러한 용도로 작업하기에 매우 훌륭하다. 향후 회차에서는 DSL을 구축하기 위한 여러 가지 기술을 조사할 것이다. 다음 몇 가지 회에서는 코드에서 탐색과 설계를 위한 독자의 탐색에서 활용할 수 있는 몇 개의 DSL 기술을 시연할 것이다.


참고자료

교육

  • The Productive Programmer(Neal Ford 저, O'Reilly Media, 2008년): 이 시리즈의 다양한 주제를 확장해 놓은 Neal Ford의 최신 저서이다.

  • ANTLR: ANTLR은 언어와 문법을 빌드하기 위한 강력한 오픈 소스 도구이다.

  • Domain Specific Languages(Martin Fowler저, Addison-Wesley, 2010년): Fowler의 신간을 베타 형식으로 확인할 수 있다.

  • Turing completeness: 이 개념에 대한 Wikipedia의 글을 읽어보자.

  • 기술 서점에서 다양한 기술 주제와 관련된 서적을 살펴보자.

  • developerWorks Java 기술 영역: Java 프로그래밍과 관련된 모든 주제를 다루는 여러 편의 기사를 찾아보자.

토론

필자소개

Neal Ford사진

Neal Ford는 글로벌 IT 컨설팅 업체인 ThoughtWorks의 소프트웨어 아키텍트이자 Meme Wrangler이다. 애플리케이션, 교육용 자료, 매거진 기사 및 비디오/DVD 프리젠테이션을 설계 및 개발하며 다양한 기술과 관련된 서적의 저자 또는 편집자이기도 하다. 최근에 출판된 책으로는 The Productive Programmer가 있다. 대규모 엔터프라이즈 애플리케이션의 설계 및 빌드에 많은 관심을 가지고 있는 그는 전세계의 개발자 컨퍼런스에서 국제적으로 인정 받고 있는 연사로도 활동하고 있다. 그의 웹 사이트를 살펴보자.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=자바
ArticleID=679271
ArticleTitle=혁신적인 아키텍처와 창발적 설계: DSL 사용하기
publish-date=06142011
author1-email=nford@thoughtworks.com
author1-email-cc=jaloi@us.ibm.com

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.