활용형 의 프로그램 설계
이 기사는 무엇입니까
예를 들어'사용자 ID와 메일 주소를
String
형으로 드래그하지 않기 위해'유형을 유형으로 사용하는 글을 고려한 것이다.도메인 제어 설계에서 말하는 도메인 객체, 솔리드, 값 객체를 알고
목표는 개요 단계를 통해 역 대상을 활용하는'역 서비스'와'응용 서비스'를 이해하는 것이다.
기본적으로 코드 샘플은 자바로 작성되었고 문장을 구성하는 데 협조했다.
활용형 있어요?
자바라고 쓰여 있으면 당연히
String
형이나 Integer
형이나 List<T>
형을 사용하겠지.그리고 이런 자바 표준형 외에도 스스로 편리한 형을 만들 수 있다고 생각합니다.
너는 그'형'의 개념이 왜 존재하는지 생각해 본 적이 있니?
당신은 금형을 활용하고 있습니까?
유형 코드를 사용할 수 없습니다
Java에서 템플릿은 클래스로 표현됩니다.
클래스 구조기를 사용하여 실례를 만들고 실례 내의 값을 사용하여 시스템 특유의 처리를 한다.
각 처리는 어느 정도 제한된 값으로 처리해야 한다.
예를 들어 사용자의 새 이름은 사용자 이름과 메일 주소가 필요합니다.
이 때 어느 값
null
이든 사용자를 만들 수 없고 "hoge@fuga"
의 값은 메일 주소로 사용할 수 없습니다.null
와 "hoge@fuga"
의 값을 입력하지 않고 처리하기 위해서는 유효성을 가져오는 것이 일반적입니다.예를 들어, 나는 아래의 코드를 쓸 수 있을 것이라고 생각한다.
// bad-example-1: ユーザ作成処理
public User createUser(String userName, String mailAddress) {
if (userName == null || userName.isEmpty()) {
throw new IllegalArgumentException("ユーザ名が不正です");
}
if (mailAddress == null || mailAddress.matches(MAIL_ADDRESS_REGEX)) {
throw new IllegalArgumentException("メールアドレスが不正です");
}
return this.repository.createUser(userName, mailAddress);
}
이것은 비교적 쓰기 좋은 코드로 문제없이 일한다고 볼 수 있다.하지만 이 코드는 형식을 활용했다고 할 수는 없다.
가장 큰 문제점은
userName
/mailAddress
형String
형이다.String
형은 문자열의 길이가 2147483647에 이르는 임의의 문자열을 나타낸다.사용자 이름과 메일 주소는 정말
String
형식으로 처리할 수 있습니까?또한 사용자의 창설 외에 사용자의 업데이트를 설치해야 할 때도 문제가 발생할 수 있다.
// bad-example-2: ユーザ作成処理と更新処理
public User createUser(String userName, String mailAddress) {
if (userName == null || userName.isEmpty()) {
throw new IllegalArgumentException("ユーザ名が不正です");
}
if (mailAddress == null || mailAddress.matches(MAIL_ADDRESS_REGEX)) {
throw new IllegalArgumentException("メールアドレスが不正です");
}
return this.repository.createUser(userName, mailAddress);
}
public User updateUser(String userId, String userName, String mailAddress) {
if (userId == null || userId.isEmpty()) {
throw new IllegalArgumentException("ユーザ ID が不正です");
}
if (userName == null || userName.isEmpty()) {
throw new IllegalArgumentException("ユーザ名が不正です");
}
if (mailAddress == null || mailAddress.matches(MAIL_ADDRESS_REGEX)) {
throw new IllegalArgumentException("メールアドレスが不正です");
}
User user = this.repository.getUserById(userId);
user.setNewName(userName);
user.setNewMailAddress(mailAddress);
return this.repository.saveUser(user);
}
그리고 이런 코드가 중복되지 않도록 UserUtil
같은 걸 만들까요?// bad-example-3: コード重複回避用のクラス
public class UserUtil {
public static void checkUserId(String userId) throws IllegalArgumentException {
if (userId == null || userId.isEmpty()) {
throw new IllegalArgumentException("ユーザ ID が不正です");
}
}
public static void checkUserName(String userName) throws IllegalArgumentException {
if (userName == null || userName.isEmpty()) {
throw new IllegalArgumentException("ユーザ名が不正です");
}
}
public static void checkMailAddress(String mailAddress) throws IllegalArgumentException {
if (mailAddress == null || mailAddress.matches(MAIL_ADDRESS_REGEX)) {
throw new IllegalArgumentException("メールアドレスが不正です");
}
}
}
사용자 ID와 같은 정보를 String
유형으로 처리하면 이렇게 된다.사용자 ID 등가쓰기를 사용하는 경우
"이 값은 따로 지불해야 하나요?""발리 데이터가 어디 있어요?"항상 지켜봐야 하고,
그것은 코드의 실장자에게 매우 큰 부담이다.
활용형 코드
이러한 문제를 해결하기 위해 자바의 대상을 대상으로 학급 구조기를 이용했다.
사용자 이름과 메일 주소에 대해 다음과 같은 종류를 준비하세요.
// good-example-1: ユーザ ID を表すクラス
public class UserId {
private final String id;
public UserId(String id) {
if (id == null || id.isEmpty()) {
throw new IllegalArgumentException("ユーザ ID が不正です");
}
this.id = id;
}
@Override
public String toString() {
return this.id;
}
}
// good-example-2: ユーザ名を表すクラス
public class UserName {
private final String name;
public UserName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("ユーザ名が不正です");
}
this.name = name;
}
@Override
public String toString() {
return this.name;
}
}
그리고 상기 종류를 사용하여 사용자의 제작과 업데이트 처리를 써 보십시오.처리 자체가 매우 유창하게 쓰여 있다.
또한 취득 사용자의 처리
getUserById
는 String
유형이 아니라 요구UserId
유형이다.잘못 썼더라도
getUserById(userName)
컴파일 오류가 발생할 수 있기 때문에 가장 빨리 오류를 발견할 수 있습니다.인코딩에도 유리하다.
아무것도 모르는 새 구성원이 읽기
getUserById
방법의 실현을 원할 때 임시 매개 변수의 유형은 UserId
형이기 때문에우선 실행
getUserById
의 전제 조건에 주의를 기울였다.반면
getUserById
실사자는 실행 방법 시 절대 이상치가 발생하지 않을 것으로 확신할 수 있어 실장에 대한 고려가 줄어들 것으로 보인다.(한숨 돌리고)
이 보도의 목적은 다음과 같다.
예를 들어'사용자 ID와 메일 주소를
String
형으로 드래그하지 않기 위해'유형을 유형으로 사용하는 글을 고려한 것이다.여기까지'활용형'을생각해 본 적이 있는가?
여기서부터 좀 더 깊고 견고하게 활용할 수 있는 지식을 소개한다.
귀에 거슬리는 말이 계속 나오니까 좀 쉬자🍵
...
...그럼 계속 힘내세요.
명명 사고방식: 값 대상
위에서 설명한
UserId
/UserName
/MailAddress
예.필드 드라이브 디자인의 값 대상을 사용한다는 생각의 일부분을 사용합니다.
값 대상은 보호의 성질을 가지고 있다.
대표적으로 다음과 같다.
// good-example-3: メールアドレスを表すクラス
public class MailAddress {
private static final String MAIL_ADDRESS_REGEX = "[\\w\\-._]+@[\\w\\-._]+\\.[A-Za-z]+";
private final String address;
public MailAddress(String address) {
if (address == null || address.isEmpty() || !address.matches(MAIL_ADDRESS_REGEX)) {
throw new IllegalArgumentException("メールアドレスが不正です");
}
this.address = address;
}
@Override
public String toString() {
return this.address;
}
}
// good-example-4: ユーザ作成と更新
public User createUser(UserName userName, MailAddress mailAddress) {
return this.repository.createUser(userName, mailAddress);
}
public User updateUser(UserId id, UserName userName, MailAddress mailAddress) {
User user = this.repository.getUserById(userId);
user.setNewName(userName);
user.setNewMailAddress(mailAddress);
return this.repository.saveUser(user);
}
실체
수치 대상은 등효성을 통해 비교하고,
존재는 등가성이 아니라 동일성 비교의 관련 개념이다.
그것은 실체다.
상기 샘플 코드에서 사용자는 실체이다.
사용자가 사용자 이름과 메일 주소를 변경해도 완전히 다른 사용자는 아니다.
사용자 ID가 같으면 사용자 이름이 다른 사용자 인스턴스도 동일하게 판정됩니다.
// イミュータブルであること
Integer i = 100;
i.setValue(100); // ありえないコード
i = 200; // 再代入でしか変更できない
UserId id = new UserId("001");
id.setValue("002"); // ありえないコード
id = new UserId("002"); // 再代入でしか変更できない
즉 사용자의 설치는 다음과 같다.// 等価性により比較されること
Integer i = 100;
Integer j = 100;
i.equals(j); // true
UserId id1 = new UserId("001");
UserId id2 = new UserId("001");
id1.equals(id2); // true
솔리드 및 값 객체의 통칭:도메인 객체
실체와 값 대상은 매우 밀접하게 관련되어 있다.
따라서 이를 통칭하여 도메인 객체라고 합니다.
실체와 값 대상은 몇 가지 미세한 차이가 있는데,
가격에 대한 제한 등은 대부분 같은 목적으로 쓰인다.
그러나 이번 샘플 코드에서 사용자는 실체다.
그러나 시스템의 요구에 따라 사용자도 값 대상이 될 수 있다.
시스템이 동일성 판정을 해야 하거나 등가성 판정을 해야 하기 때문이다.
이것은 각 시스템에 따라 실장자가 판단해야 한다.
필드 대상에 포함되지 않은 코드
지금까지 우리는 일반적으로 쓴 일부 코드가 도메인 이름 대상에 들어갈 수 있다는 것을 발견했다.
하지만 필드 대상을 사용하여 코드를 쓰면,
불협화음 코드에 직면하다.
예를 들어, 도메인 객체에 특정 ID를 가진 사용자가 데이터 저장소에 이미 있는지 확인하는 프로세스를 적습니다.
낭비가 너무 많은 게 뻔하다.
도메인 기반 설계에서의 서비스
이러한 상태를 해결하기 위해'역 서비스','응용 서비스'라는 생각이 존재한다.
도메인 이름 서비스
도메인 서비스는 도메인 대상에서 잘 쓰이지 않는 처리입니다.
예를 들어 사용자의 존재를 확인하는 처리(상기)는 역 서비스에 쓰일 것이다.
필드 대상이나 필드 서비스는 필요한 기본 처리만 적습니다.
그 외의 것은 후술한 응용 프로그램 서비스에 쓰일 것이다.
어플리케이션 서비스
응용 서비스는 역 서비스와 역 대상을 사용하여 실현하고자 하는 응용의 요구를 작성하는 곳이다.
예를 들어 HTTP의 통신 요구가 응용 프로그램 등급이라고 생각하면 응용 서비스에 쓰일 것이다.
(MVC의 Controller와 같은 버전과는 다릅니다.)
끝말
활용형의 첫걸음으로 역구동 디자인을 소개했다.
역구동 디자인은'디자인'답게 원본 코드 수준에서 제품 디자인을 지원하는 지식입니다.
대상을 향한 관계가 상당히 깊기 때문(또는 대상을 향한 구체적인 방법 중 하나),
그냥 예쁜 코드를 쓰고 싶어요!이런 분들도 도메인 구동 디자인 책을 읽어보는 것을 추천합니다.
대상/역 구동을 위해 필자가 참고한 서적을 소개합니다.
Reference
이 문제에 관하여(활용형 의 프로그램 설계), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/m_takehara/articles/351624df648ce9cb0ed0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)