가치 대상에 대한 시뮬레이션 디지털
이것은 the Jira app in the App Store의 실제 변경 로그의 화면 캡처입니다.내가 그것을 처음 보았을 때, 나는 두 가지 문제를 생각했다.
패턴 정의
가치 대상according to wikipedia의 정의는 다음과 같다.
A small object that represents a simple entity whose equality is not based on identity
비록 그들이 통상적으로 매우 작다고 주장하는 것은 합법적이지만, 나는 그것들이 반드시 작지는 않다고 말하고 싶다.또한 가치 대상은 비강제적이지만 매우 바람직한 특징이 있다.
봉인과 의미를 이용하다
우리의 새로운 우수한 Jira 기능으로 돌아가서 우리는 소수 이야기점을 가진 능력이 이렇게 중요하다고 가정하자. 왜냐하면 a) 이전에는 불가능했기 때문이다. b) 이 뒤에 상당히 많은 일을 해야 하기 때문이다.
Jira에 방대한 코드 라이브러리가 있다고 가정해 봅시다. 이것은 공평한 가설로 보입니다.이것은 거대한 응용 프로그램으로 이미 한동안 존재해 왔다.스토리 포인트가 여기저기 있을 수도 있어요. 왜냐하면 스컬럼의 평균 채택률의 일부이기 때문에 지라는 이 분야에 좀 뛰어나요.
현재 다음 코드 세그먼트를 고려하면 이 코드 세그먼트는 Jira 핸들의 일부 개념에서 비롯될 수 있다(PHP에서는 노출된 코드의 비진실성을 방지하기 위해 명확하지 않다).
class Task {
private string $id;
private string $title;
private int $storyPoints;
public function estimation(): int {}
}
class Sprint {
private TaskList $tasks;
private int $totalStoryPoints;
public function estimation(): int {}
public function addTask(Task $task): void {}
}
class SprintReport {
private int $completedStoryPoints;
public function addCompletedStoryPoints($date, int $amount): void {}
}
int
값에 대한 모든 인용은 사실상 이야기점에 대한 인용이다.현재의 코드와 같이 소수를 허용하는 것은 아주 작은 일이 아니다. 우리는 이 작은 코드에서만 7가지 다른 외관을 바꿀 수 있다.전체 코드 라이브러리, 심지어 여기에서 개술한 방법의 실현을 상상해 보세요.이제 다음 값 객체를 고려하여 스토리 포인트의 개념을 시뮬레이션합니다.
class StoryPoint {
public function __construct(private int $value) {}
public function value(): int {
return $this->value;
}
}
그리고 그것을 사용할 때 코드의 외관:class Task {
private string $id;
private string $title;
private StoryPoint $estimation;
public function estimation(): StoryPoint {}
}
class Sprint {
private TaskList $tasks;
private StoryPoint $totalStoryPoints;
public function estimation(): StoryPoint {}
public function addTask(Task $task): void {}
}
class SprintReport {
private StoryPoint $completedStoryPoints;
public function addCompletedStoryPoints($date, StoryPoint $amount): void {}
}
정수에서 부동점까지의 변화는 소수를 허용하고 두 가지 변화만 의미한다. int
값 대상의 두 개StoryPoint
인용.그리고 지속성 시스템에서 어떤 시사점을 하든지 간에 이야기점을 소수를 지원하는 데이터베이스 열로 바꾸는 것은 필수적이다.모델 정의의 VO에 직면하면 크기가 중요한 부분은 아니지만 이보다 작을 수는 거의 없다.
그것은 그 가치를 통해 식별된다. 이것은 우리가 그 실례나 다른 실례를 상관하지 않는다는 것을 의미한다. 그것이 같은 가치를 가지기만 하면.
$aStoryPointVO = new StoryPoint(2);
$anotherStoryPointVO = new StoryPoint(2);
//using one VO or the other is indifferent
//and would result in an equivalent Task
$aTask = new Task('task-id', 'Task title', $aStoryPointVO);
우리의 VO는 정의를 고수한다. 이것은 매우 좋다.마지막으로...응, 이것은 VO야.상자를 열면 바로 사용할 수 있는 값 대상은 봉인을 제공하여 그들이 대표하는 개념과 의미의 변경을 도입할 때 수정해야 할 위치를 크게 감소시켰다.우리가 앞에서 언급한 또 다른 두 가지 측면, 불변성과 끌림 행위는'내재적'이 아니라 우리의 근면에 달려 있다.흡인 행위
사람을 끌어당기는 행위는 자연스러우며 가치 대상의 봉인성과 의미를 강화한다.불변성도 이와 밀접한 관련이 있다.우리는
addCompletedStoryPoints
예시에서 방법SprintReport
을 사용하여 이 두 가지 방법을 설명할 것이다.이러한 바람직하지 않은 구현 방식을 고려해 보십시오.class SprintReport {
private StoryPoint $completedStoryPoints;
//Don't do this
public function addCompletedStoryPoints($date, StoryPoint $amount) {
$previousValue = $this->completedStoryPoints->value();
$addedValue = $amount->value();
$this->completedStoryPoints = new StoryPoint($previousValue + $addedValue);
}
}
이 조작을 통해 우리는Value 대상이 제공한 봉인을 깨뜨렸다. 클라이언트 코드(방법)는 StoryPoint
의 값의 내부 표시가 정수라는 것을 알고 우리는 이전과 같은 함정에 빠졌다.이 내부 값의 변화로 인해 코드 라이브러리의 몇 가지 부분이 업데이트될 것이다. 값 대상 자체와 그 내부에 대해 너무 많이 알고 위의 코드와 같은 모든 부분을 사용하기 때문이다.VO에 속하는 논리는 VO에 두어야 한다.두 개
StoryPoint
를 추가하는 것은 내부StoryPoint
만 의미 있는 작업이다. StoryPoint
만 내부를 알아야 하기 때문이다.이것이 바로 끌어당기는 행위의 의미이다. 코드의 봉인과 의미를 강화하는 데 매우 뛰어나다.VO 코드가 없는 부분을 고려해 보십시오.
$age = 21;
$storyPoints = 3;
$somethingVeryWrong = $age + $storyPoints;
코드가 원어와 함께 처리된 영역의 개념 (참고로, 이것은 primitive obsession 이라는 코드 맛) 을 처리할 때, 프로그래밍 언어는 이러한 동작을 막을 수 없습니다.유형과 값 대상은 가능합니다.그렇다면 어떻게 스토리를 추가할까요?추가를 위해 add 작업을
StoryPoint
에 넣고 다른 StoryPoint
를 전달합니다.class StoryPoint {
public function __construct(private int $value) {}
public function value(): int {
return $this->value;
}
//We are skipping the return type on purpose. Stay tuned!
public function add(StoryPoint $storyPoint) {}
}
이런 방식을 통해 우리는 VO의 내부 구조를 아무도 모르고 무의미하게 그것들에 무작위 무관치를 추가할 수 있음을 보장한다.불변성
add
VO에서 StoryPoint
작업을 구현하는 경우 다음과 같은 작업을 시도할 수 있습니다.class StoryPoint {
public function __construct(private int $value) {}
public function value(): int {
return $this->value;
}
//Don't do this
public function add(StoryPoint $storyPoint) {
$this->value = $this->value + $storyPoint->value();
}
}
물론 우리는 포장을 견지하지만, 우리도 가변성을 도입했다.우리는 우리의 VO가 가능한 한 변하지 않기를 바란다고 언급했다.변동성은 추적하기 어려운 버그의 출처이기 때문에 피해야 한다.다음 사항을 고려하십시오.$fiveStoryPoints = new StoryPoint(5);
$report = new SprintReport();
$report->addCompletedStoryPoints($today, $fiveStoryPoints);
//Can we trust our $fiveStoryPoints are still five?
우리의 StoryPoint
공공 인터페이스 add
방법이 이전에 실현된 것처럼 실례적인 상태를 바꾸기만 한다면, 그 값이 addCompletedStoryPoints
호출에 변경되지 않았음을 보장할 수 없습니다.물론 우리는 addCompletedStoryPoints
를 열고 거기에 호출되지 않은 add
방법을 검사할 수 있지만 이것은 수동적인 방법이기 때문에 확장이 잘 되지 않는다.VO를 변경하지 않는 방법은 작업 후에 새로운 VO를 반환하는 것입니다.다음은
SprintReport
의 구현 및 사용법입니다.class StoryPoint {
public function __construct(private int $value) {}
public function value(): int {
return $this->value;
}
public function add(StoryPoint $storyPoint) {
return new StoryPoint($this->value + $storyPoint->value());
}
}
class SprintReport {
private StoryPoint $completedStoryPoints;
public function addCompletedStoryPoints($date, StoryPoint $amount) {
$this->completedStoryPoints = $this->completedStoryPoints->add($amount);
}
}
메모리와 자원에 대한 낭비로 보일 수도 있지만, 절대 다수의 경우, 쓰레기 수집은 우리가 관심을 가져야 할 부분이 아니다. 쓰레기 수집은 충분히 빨리 인용되지 않는 실례를 처리하고, 우리가 얻는 가치는 훨씬 크다.일부 문헌에서는 불변성은 VOs의 강제적인 측면이 아니라고 주장한다. 비록 이것은 매우 바람직하지만.솔직히 말해서, 나는 지금까지 가변성이 합리적이라는 것을 발견한 적이 없지만, 이것은 가변성이 없다는 것을 의미하지는 않는다.소프트웨어 개발 중의 모든'규칙'과 마찬가지로 주어진 상하문에서 규칙을 언제 수정할 것인지를 결정하는 것은 개발자의 좋은 추리에 달려 있다.기본값은 변경 불가 VOs입니다. 권장하지 않는 경우 다음을 알려주십시오.)
마지막 한마디
이 글은 가치 대상 모델이 모든 OOP 코드 라이브러리에 제공하는 장점을 잘 이해하고 간단한 예로 설명할 수 있기를 바란다.녹지 응용 프로그램에 도입하거나 원시적으로 푹 빠진 코드에 도입하면 처음부터 보답이 있기 때문에 충분히 사용하도록 격려할 수 없습니다.
다음 글은 Jira 코드 라이브러리로 구성된 이 코드 라이브러리에
StoryPoint
Value 대상을 도입하고 작은 단계에서 재구성 기술을 응용하는 방법을 보여 준다.아마도 OOP에서 가장 강력한 두 가지 도구일 것이다.기대해주세요!
Reference
이 문제에 관하여(가치 대상에 대한 시뮬레이션 디지털), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/xoubaman/a-mockumentary-about-value-objects-3ad8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)