제품 품질 저하 없이 개발팀을 확장하는 방법
개발팀을 확장하고 계신가요? 제품 품질을 저하시키지 않고 성장하는 방법을 알아보세요. 이 가이드에서는 확장할 시기의 징후, 팀 구조, 채용, 리더십 및 도구와 더불어 The Codest가 어떻게...
정의를 참조하면 DSL(도메인 특정 언어)은 특정 애플리케이션 도메인에 특화된 컴퓨터 언어입니다. 즉, 특정 요구 사항을 충족하기 위해 개발되었습니다.
이 글을 읽으면 DSL이 무엇이며 루비와 어떤 공통점이 있는지 알게 될 것입니다.
정의를 참조하면 DSL(도메인 특정 언어)은 특정 애플리케이션 도메인에 특화된 컴퓨터 언어입니다. 즉, 특정 요구 사항을 충족하기 위해 개발되었습니다. DSL에는 두 가지 유형이 있습니다:
An 외부 자체 구문 분석기가 필요한 DSL. 잘 알려진 예로 SQL 언어를 들 수 있는데, 이 언어를 사용하면 데이터베이스가 생성되지 않은 언어로 데이터베이스와 상호 작용할 수 있습니다.
An 내부 자체 구문이 없는 대신 특정 프로그래밍 언어의 구문을 사용하는 DSL입니다.
짐작할 수 있듯이 두 번째 DSL 유형에 계속 집중할 것입니다.
기본적으로 루비 메타프로그래밍을 활용하면 자신만의 미니 언어를 만들 수 있습니다. 메타프로그래밍은 프로그래밍 기법입니다. 코드 런타임에 동적으로(즉석에서) 설정할 수 있습니다. 잘 모르실 수도 있지만, 여러분은 매일 다양한 DSL을 사용하고 있을 것입니다. DSL의 기능을 이해하기 위해 아래의 몇 가지 예를 살펴보겠습니다. 이 모든 예에는 공통된 요소가 하나씩 있는데, 이를 가리킬 수 있을까요?
Rails.application.routes.draw do
루트로 'home#index'
resources :users do
get :search, on: :collection
end
end
```
Rails를 사용해 본 사람이라면 누구나 알고 있습니다. config/routes.rb 파일에서 애플리케이션 경로를 정의합니다(HTTP 동사와 URL을 컨트롤러 동작에 매핑). 하지만 어떻게 작동하는지 궁금한 적이 있으신가요? 사실 루비 코드일 뿐입니다.
FactoryBot.define do
factory :사용자 do
company
sequence(:email) { |i| "user_#{i}@test.com" }
sequence(:first_name) { |i| "사용자 #{i}" }
last_name 'Test'
role 'manager'
end
end
테스트를 작성하려면 종종 객체를 제작해야 합니다. 따라서 시간 낭비를 피하려면 프로세스를 최대한 단순화하는 것이 좋습니다. 이것이 바로 FactoryBot 는 기억하기 쉬운 키워드와 사물을 설명하는 방법을 제공합니다.
'sinatra/base' 필요
클래스 WebApplication < Sinatra::Base
get '/' do
'Hello world'
end
end
```
시나트라 는 웹 애플리케이션을 처음부터 만들 수 있는 프레임워크입니다. 요청 방법, 경로, 응답을 더 쉽게 정의할 수 있을까요?
다른 DSL 예는 다음과 같습니다. 레이크, RSpec 또는 활성 레코드. 각 DSL의 핵심 요소는 블록 사용.
이제 후드 아래에 무엇이 숨어 있는지, 그리고 구현이 어떤 모습일 수 있는지 이해할 차례입니다.
다양한 제품에 대한 데이터를 저장하는 애플리케이션이 있다고 가정해 봅시다. 사용자 정의 파일에서 데이터를 가져올 수 있는 기능을 추가하여 애플리케이션을 확장하고 싶습니다. 또한 필요한 경우 파일에서 값을 동적으로 계산할 수 있어야 합니다. 이를 위해 DSL을 만들기로 결정했습니다.
간단한 제품 표현은 다음과 같은 속성을 가질 수 있습니다(product.rb):
클래스 제품
attr_accessor :이름, :설명, :가격
end
실제 데이터베이스를 사용하는 대신 작업을 시뮬레이션할 것입니다(fake_products_database.rb):
클래스 FakeProductsDatabase
def self.store(product)
puts [product.name, product.description, product.price].join(' - ')
end
end
이제 제품 데이터가 포함된 파일을 읽고 처리하는 클래스를 만들겠습니다(dsl/data_importer.rb):
모듈 Dsl
데이터 임포터 클래스
모듈 구문
def add_product(&block)
FakeProductsDatabase.store product(&block)
end
private
def product(&block)
ProductBuilder.new.tap { |b| b.instance_eval(&block) }.product
end
end
포함 구문
def self.import_data(file_path)
new.instance_eval File.read(file_path)
end
end
end
```
클래스에는 다음과 같은 메서드가 있습니다. import_data 인자로 파일 경로를 기대합니다. 파일이 읽혀지고 그 결과가 인스턴스_평가 메서드가 클래스 인스턴스에서 호출됩니다. 어떤 기능을 하나요? 인스턴스 컨텍스트 내에서 문자열을 루비 코드로 평가합니다. 이는 다음을 의미합니다. self 의 인스턴스가 될 것입니다. 데이터 임포터 클래스. 원하는 구문/키워드를 정의할 수 있기 때문입니다(가독성을 높이기 위해 구문은 모듈로 정의됩니다). 언제 add_product 메서드가 호출되면 메서드에 주어진 블록은 다음과 같이 평가됩니다. 제품 빌더 인스턴스를 빌드하는 제품 인스턴스입니다. 제품 빌더 클래스는 아래에 설명되어 있습니다(dsl/product_builder.rb):
모듈 Dsl
제품 빌더 클래스
속성 = %i[이름 설명 가격].freeze
ATTR_READER :제품
def initialize
@product = Product.new
end
ATTRIBUTES.each do |attribute|
define_method(attribute) do |arg = nil, &block|
value = block.is_a?(Proc) ? block.call : arg
product.public_send("#{attribute}=", value)
end
end
end
end
```
이 클래스는 다음과 같이 허용되는 구문을 정의합니다. add_product 블록을 추가합니다. 약간의 메타프로그래밍을 통해 제품 속성에 값을 할당하는 메서드를 추가할 수 있습니다. 이러한 메서드는 직접 값 대신 블록을 전달하는 것도 지원하므로 런타임에 값을 계산할 수 있습니다. 속성 판독기를 사용하면 마지막에 빌드된 제품을 얻을 수 있습니다.
이제 가져오기 스크립트(import_job.rb):
필수 'dsl/데이터임포터' 요구사항
필수 'dsl/productbuilder'
리퀘이러티브 '가짜제품데이터베이스'
필수 '제품'
Dsl::DataImporter.import_data(ARGV[0])
```
마지막으로 DSL을 사용하여 제품 데이터가 포함된 파일(dataset.rb)을 가져옵니다:
```ruby
add_product do
name '충전기'
설명 '생명을 구하는'
가격 19.99
end
add_product do
name '자동차 전복'
description { "#{Time.now.strftime('%F %T')}에서 전복됨" }
price 0.01
end
add_product do
name 'Lockpick'
설명 '문은 닫히지 않습니다'
price 7.50
end
```
데이터를 가져오려면 명령어 하나만 실행하면 됩니다:
ruby import_job.rb dataset.rb
그 결과는...
충전기 - 인명 구조 - 19.99
자동차 난파 - 2018-12-09 09:47:42에 난파 - 0.01
자물쇠 따기 - 문이 닫히지 않음 - 7.5
..성공!
위의 모든 예시를 보면 DSL이 제공하는 가능성을 어렵지 않게 알 수 있습니다. DSL을 사용하면 필요한 모든 로직을 숨기고 가장 중요한 키워드만 사용자에게 노출함으로써 일부 일상적인 작업을 단순화할 수 있습니다. 이를 통해 더 높은 수준의 추상화를 달성할 수 있고 유연한 사용 가능성(재사용성 측면에서 특히 가치 있는 기능)을 제공합니다. 반면에 DSL을 추가하면 프로젝트 메타프로그래밍을 사용한 구현은 확실히 이해하고 유지 관리하기가 훨씬 더 어렵습니다. 또한 동적이기 때문에 견고한 테스트 스위트가 필요합니다. DSL을 문서화하면 더 쉽게 이해할 수 있으므로 반드시 문서화할 가치가 있습니다. 자신만의 DSL을 구현하는 것은 보람된 일이지만 반드시 보상을 받아야 한다는 점을 기억하는 것이 좋습니다.
이 주제에 관심이 있으신가요? 그렇다면 알려주세요 - 최근 프로젝트 중 하나에서 요구 사항을 충족하기 위해 만든 DSL에 대해 알려드리겠습니다.