2022 오픈소스 컨트리뷰션 아카데미 "NHN Toast Power Platform Connector" 프로젝트에 참여하면서 Challengers 기간 동안 배운 내용을 기록하였습니다.
함께 과제 조사하고 정리한 경찬, 예리, 준희 멘티님께 감사를... 🙏
💡 메소드 체이닝(Method)
OOP에서 **여러 메소드를 이어서 호출하는 문법** 메소드가 객체(this)를 반환하여 여러 메소드를 순차적으로 선언할 수 있도록 한다. 모든 메서드를 함께 연결하여 단일 명령문을 형성할 수 있는 일반적인 기술이다.
var translations = new Dictionary<string, string>
{
{"cat", "chat"},
{"dog", "chien"},
{"fish", "poisson"},
{"bird", "oiseau"}
};
// Find translations for English words containing the letter "a",
// sorted by length and displayed in uppercase
IEnumerable<string> query = translations
.Where (t => t.Key.Contains("a")) // Key 값에 a가 있는지 확인
.OrderBy (t => t.Value.Length) // Value 값의 길이 오름차순
.Select (t => t.Value.ToUpper()); // Value 값을 대문자로
// The same query constructed progressively:
var filtered = translations.Where (t => t.Key.Contains("a"));
var sorted = filtered.OrderBy (t => t.Value.Length);
var finalQuery = sorted.Select (t => t.Value.ToUpper());
: 도메인(실세계에서 사건이 발생하는 집합 / 여기서는 비즈니스 Domain으로 유사한 업무의 집합을 의미) 중심으로 설계해 나가는 것
: 기존의 어플리케이션 설계가 비즈니스 Domain에 대한 이해가 부족한 상태에서 설계 및 개발되었다는 반성에서 출발. → 데이터(객체) 주도 설계 탈피!
: DDD에서는 기존의 현업에서 IT로의 일방향 소통구조를 탈피하여 현업과 IT의 쌍방향 커뮤니케이션을 매우 중요하게 생각
💡옷 쇼핑몰에서의 DDD Example
손님들이 주문하는 도메인(Order Domain) / 점주입장에서 옷들을 관리하는 도메인(Manage Domain) / 쇼핑몰 입장에서 월세, 관리비 등 건물에 대한 관리를 담당하는 도메인(Building Domain)
: 같은 객체가 여러 개 존재할 수 있다. 이때 Bounded Context에 따라 객체(Model)의 역할은 완벽히 바뀐다. → 서로 다른 도메인 영역에 영향을 끼치려면 API 호출을 통해서 이루어져야..
EX) 주문 도메인의 옷 == 손님들에게 팔기 위한 객체 정보 ↔ 옷을 관리하는 도메인의 옷 == 점주입장에서 관리하기 위한 객체 정보
💡 DDD Layer
1. Application Layer: 주로 도메인과 Repository를 바탕으로 실제 서비스(API)를 제공하는 계층
2. Domain Layer: Entity, VO(Value Object)를 활용하여 도메인 로직이 진행되는 계층
3. Infrastructure Layer: 쉽게 말하면 외부와의 통신(ORM, DB, NoSql)을 담당하는 계층
한 도메인 안에서 도메인 전문가와 개발자가 동일한 용어를 사용해서 서로 혼란을 피할 수 있게 하는 것
→ 도메인에서 사용하는 용어를 코드에 반영하지 않으면 그 코드는 개발자에게 코드의 의미를 해석해야 하는 부담을 준다.
: 특정 도메인을 적용하는데 특화된 컴퓨터 언어 → 즉 특정용도에서만 사용 가능
: 특정 영역의 문제 해결에는 그 영역에 맞는 특화된 도구를 사용하자는 취지.
: 표현 방식은 해당 도메인의 전문가(비 프로그래머)가 이해할 수 있는 형태여야 함 → 코드가 일반 자연어를 읽는 것과 같이 쉽게 이해됨
📌 정리
라이브러리나 프레임워크등을 도메인 Expert 나 우리같은 일반 프로그래머에게 조차도 사용하기 쉽게 (Fluent 하게) 제공해주는것 자체, 제한된 상황 내에서 고민과 노력으로 이루어진 "깔끔한 문장" 으로 우리에게 제공하는 API 자체가 DSL
DSL은 내부 DSL과 외부 DSL로 구분할 수 있다.
: 특수한 목적을 위해 제한된 방법으로 호스트 언어를 사용하는 방식, 자체적으로 의존하는 무언가를 만드는 경우에 해당
: 임베디드 DSL, Fluent Interfaces 라고도 한다.
: 내부 DSL에서는 API와 DSL의 경계가 모호해 비슷하게 생각하는 경향이 있음 → 좀 더 일반 사용자가 알아보기 쉬운 API가 내부 DSL로 생각해도 될 듯 함
: 사용하던 도구를 그대로 이용할 수 있음, 처리 결과를 쉽게 예측할 수 있음
EX) Ruby, Smalltalk 등
: 호스트 언어가 아닌 다른 언어에서 생성된 DSL이다.
: 대부분 자체적인 문법을 가지지만 기존 언어의 문법을 쓰는 예도 있다.
: 외부 DSL에서는 DSL과 범용 언어(GPL : General Purpose Language)과의 경계가 모호해지는 경향이 있다. 그 차이는 언어 작성자와 언어 사용자의 목적에 있다. 특정 영역에서 언어의 작성자가 아닌 사용자의 목적에 부합하는, 이해를 할 수 있으면 외부 DSL이다.
애저 펑션의 첫 엔트리 포인트에서 만나는 부분
public static IFunctionFactory Factory { get; set; } = new FunctionFactory(new AppModule());
[FunctionName(nameof(XmlToXmlMapperHttpTrigger))]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "mappers/xml/xml")] HttpRequestMessage req,
ILogger log)
{
return result = await Factory.Create<IXmlToXmlMapperFunction, ILogger>(log)
.InvokeAsync<HttpRequestMessage, HttpResponseMessage>(req)
.ConfigureAwait(false);
}
Create, InvokeAsync
와 같이 상당히 직관적