Functorium 프레임워크 통합
Functorium 프레임워크의 값 객체 타입 계층 구조를 학습하고 실전에서 활용하는 방법을 다룹니다.
학습 목표
섹션 제목: “학습 목표”- 프레임워크 타입 계층 구조 이해
SimpleValueObject<T>활용법ComparableSimpleValueObject<T>활용법- 복합
ValueObject구현
프레임워크 타입 계층 구조
섹션 제목: “프레임워크 타입 계층 구조”IValueObject (인터페이스 — 명명 규칙 상수) └── AbstractValueObject (기본 클래스 — 동등성, 해시코드, ORM 프록시) ├── ValueObject (CreateFromValidation<TVO, TValue> 헬퍼) │ └── SimpleValueObject<T> (단일 값 래퍼, CreateFromValidation<TVO> 헬퍼, protected T Value) └── ComparableValueObject (IComparable, 비교 연산자) └── ComparableSimpleValueObject<T> (단일 비교 가능 값 래퍼, protected T Value)실행 방법
섹션 제목: “실행 방법”cd Docs/tutorials/Functional-ValueObject/04-practical-guide/01-Functorium-Framework/FunctoriumFrameworkdotnet run예상 출력
섹션 제목: “예상 출력”=== Functorium 프레임워크 통합 ===
1. SimpleValueObject<T> 사용 예시──────────────────────────────────────── 유효한 이메일: user@example.com 오류: 유효한 이메일 형식이 아닙니다.
2. ComparableSimpleValueObject<T> 사용 예시──────────────────────────────────────── 정렬 전: 30, 25, 35 정렬 후: 25, 30, 35
3. ValueObject (복합) 사용 예시──────────────────────────────────────── 주소: 서울 강남구 테헤란로 123 (06234)
4. 프레임워크 타입 계층 구조──────────────────────────────────────── ...핵심 코드 설명
섹션 제목: “핵심 코드 설명”SimpleValueObject<T>
섹션 제목: “SimpleValueObject<T>”
Value속성은protected이므로, 외부에서 값에 접근하려면 명시적 변환 연산자(explicit operator T)를 사용하거나 별도의 public 속성을 정의합니다.
public abstract class SimpleValueObject<T> : ValueObject where T : notnull{ protected T Value { get; }
protected SimpleValueObject(T value) { Value = value; }
protected override IEnumerable<object> GetEqualityComponents() { yield return Value; }
// 명시적 변환 연산자 (외부에서 값 접근) public static explicit operator T(SimpleValueObject<T>? valueObject) => ...;
// CreateFromValidation 헬퍼 public static Fin<TVO> CreateFromValidation<TVO>( Validation<Error, T> validation, Func<T, TVO> factory) where TVO : SimpleValueObject<T>;}ComparableSimpleValueObject<T>
섹션 제목: “ComparableSimpleValueObject<T>”
ComparableValueObject를 상속하며,SimpleValueObject<T>와는 별도의 계층입니다.
public abstract class ComparableSimpleValueObject<T> : ComparableValueObject where T : notnull, IComparable{ protected T Value { get; }
protected ComparableSimpleValueObject(T value) { Value = value; }
protected override IEnumerable<IComparable> GetComparableEqualityComponents() { yield return Value; }
// 명시적 변환 연산자 (외부에서 값 접근) public static explicit operator T(ComparableSimpleValueObject<T>? valueObject) => ...;}ValidationRules<T> 시스템
섹션 제목: “ValidationRules<T> 시스템”// 타입 파라미터를 한 번만 지정하는 검증 시작점ValidationRules<Email>.NotNull(value) .ThenNotEmpty() .ThenNormalize(v => v.Trim().ToLowerInvariant()) .ThenMaxLength(MaxLength) // public const int MaxLength = 320; .ThenMatches(EmailRegex(), "Invalid email format");
// DomainError.For<T>() 패턴DomainError.For<Email>(new Empty(), value, "Email cannot be empty");DomainError.For<Password>(new TooShort(MinLength: 8), value, "Password too short");FAQ
섹션 제목: “FAQ”Q1: SimpleValueObject<T>와 ComparableSimpleValueObject<T>는 어떤 기준으로 선택하나요?
섹션 제목: “Q1: SimpleValueObject<T>와 ComparableSimpleValueObject<T>는 어떤 기준으로 선택하나요?”A: 값의 대소 비교나 정렬이 필요하면 ComparableSimpleValueObject<T>를, 동등성 비교만 필요하면 SimpleValueObject<T>를 사용합니다. 예를 들어 Email은 정렬이 불필요하므로 SimpleValueObject<string>을, Age는 비교가 필요하므로 ComparableSimpleValueObject<int>를 상속합니다.
Q2: Value 속성이 protected인 이유는 무엇인가요?
섹션 제목: “Q2: Value 속성이 protected인 이유는 무엇인가요?”A: 외부에서 내부 값을 직접 접근하면 값 객체의 캡슐화가 깨질 수 있기 때문입니다. 외부에서 값이 필요한 경우 explicit operator T 변환 연산자를 사용하거나, 도메인에 맞는 public 속성을 별도로 정의합니다.
Q3: ValidationRules<T> 시스템은 반드시 사용해야 하나요?
섹션 제목: “Q3: ValidationRules<T> 시스템은 반드시 사용해야 하나요?”A: 아닙니다. if 문과 DomainError.For<T>() 패턴으로 직접 검증해도 됩니다. ValidationRules<T>는 NotNull, ThenNotEmpty, ThenMaxLength 같은 공통 검증을 체이닝으로 간결하게 표현하고 싶을 때 사용하는 편의 시스템입니다.
다음 단계
섹션 제목: “다음 단계”ORM 통합 패턴을 학습합니다.