이것은 귀하의 질문에 따라 초기 의견을보다 잘 작성했습니다. OP가 해결 한 질문에 대한 답변은이 답변의 맨 아래에 있습니다. 또한 같은 장소에 있는 중요한 메모 를 확인하십시오 .
현재 설명하고있는 Sipo는 Active record 라는 디자인 패턴 입니다. 모든 것과 마찬가지로, 이것조차도 프로그래머들 사이에서 자리를 잡았지만 단순한 이유 인 확장 성으로 인해 저장소 와 데이터 매퍼 패턴을 선호하여 버려졌습니다 .
즉, 활성 레코드는 다음과 같은 개체입니다.
- 도메인의 개체를 나타냅니다 (비즈니스 규칙 포함, 사용자 이름 등을 변경할 수 있거나없는 경우 등 개체에 대한 특정 작업을 처리하는 방법을 알고 있음),
- 엔터티를 검색, 업데이트, 저장 및 삭제하는 방법을 알고 있습니다.
현재 디자인과 관련된 몇 가지 문제를 해결하고 디자인의 주요 문제는 마지막 6 번째 지점에서 해결됩니다 (마지막으로 추측합니다). 생성자를 디자인하는 클래스가 있고 생성자가 무엇을해야하는지조차 모르는 경우 클래스가 잘못한 것일 수 있습니다. 그것은 당신의 경우에 일어났습니다.
그러나 엔터티 표현과 CRUD 논리를 두 개 이상의 클래스로 분할하여 디자인을 수정하는 것은 실제로 매우 간단합니다.
디자인이 지금 다음과 같이 보입니다.
Employee
-직원 구조에 대한 정보 (속성)와 엔티티를 수정하는 방법 (변경 가능한 방식으로 결정하는 경우), Employee
엔티티에 대한 CRUD 논리를 포함하고 , Employee
오브젝트 목록을 리턴하고 , Employee
원하는 경우 오브젝트를 승인합니다. 직원을 업데이트하고 다음 Employee
과 같은 방법을 통해 단일 을 반환 할 수 있습니다getSingleById(id : string) : Employee
와우, 수업이 엄청나 네요.
이것이 제안 된 해결책입니다.
Employee
-직원 구조에 대한 정보 (속성) 및 엔티티 수정 방법 (변경 가능한 방식으로 결정한 경우)
EmployeeRepository
- Employee
엔티티에 대한 CRUD 로직을 포함하고 , Employee
오브젝트 목록을 Employee
리턴 할 수 있으며, 직원을 업데이트 할 때 오브젝트를 승인하고 , 다음 Employee
과 같은 메소드를 통해 단일 을 리턴 할 수 있습니다.getSingleById(id : string) : Employee
우려 의 분리에 대해 들어 보셨습니까 ? 아냐, 이제 할거야 이것은 단일 책임 원칙의 덜 엄격한 버전으로, 클래스는 실제로 하나의 책임 만 갖거나 Bob 아저씨가 말한 것처럼 :
모듈에는 변경해야 할 단 하나의 이유가 있어야합니다.
초기 클래스를 명확하게 둥근 인터페이스를 가진 두 개의 클래스로 명확하게 나눌 수 있다면 초기 클래스가 너무 많은 일을하고 있었을 것입니다.
리포지토리 패턴의 장점은 데이터베이스 (파일, noSQL, SQL, 객체 지향 데이터베이스) 사이의 중간 계층을 제공하는 추상화 역할을 할뿐만 아니라 구체적 일 필요는 없습니다. 수업. 많은 OO 언어에서 인터페이스를 실제 interface
(또는 C ++ 인 경우 순수 가상 메소드가있는 클래스) 로 정의한 후 여러 구현을 가질 수 있습니다.
이것은 저장소가 실제 구현인지 여부에 대한 결정을 완전히 해제합니다 interface
. 키워드 로 구조에 실제로 의존함으로써 인터페이스에 의존하고 있습니다. 리포지토리는 데이터 계층 추상화, 즉 데이터를 도메인에 매핑하거나 그 반대로 매핑하는 것을 가리키는 멋진 용어입니다.
(적어도) 두 개의 클래스로 분리 할 때의 또 다른 큰 장점은 이제 클래스가 Employee
다른 어려운 일을 처리 할 필요가 없기 때문에 자신의 데이터를 명확하게 관리하고 매우 잘 수행 할 수 있다는 것입니다.
질문 6 : 새로 생성 된 Employee
클래스 에서 생성자는 어떻게해야 합니까? 이건 간단하다. 인수를 가져 와서 유효한지 확인하십시오 (예 : 연령이 음수가 아니거나 이름이 비어 있지 않아야 함). 데이터가 유효하지 않을 때 오류가 발생하고 유효성 검사가 통과되면 인수를 개인 변수에 할당하십시오 실체의. 데이터베이스를 사용하는 방법을 전혀 모르기 때문에 이제 데이터베이스와 통신 할 수 없습니다.
질문 4 : 대답은 정확히 필요한 것이 무엇인지에 따라 크게 달라지기 때문에 일반적으로가 아니라 전혀 대답 할 수 없습니다.
질문 5 : 이제 두에 비 대한 클래스를 분리 한 것을, 당신이 직접 여러 업데이트 방법을 가질 수 Employee
클래스, 같은 changeUsername
, markAsDeceased
,의 데이터 조작되는 Employee
클래스 에만 RAM의를 다음과 같은 방법을 소개 할 수 registerDirty
로부터 저장소 클래스에 대한 작업 단위 (UOW) 패턴으로, 저장소를 통해이 오브젝트가 특성을 변경했음을 알리고 commit
메소드 를 호출 한 후 업데이트해야합니다 .
분명히, 업데이트를 위해서는 객체에 ID가 있어야하고 이미 저장되어 있어야하며,이를 감지하고 기준이 충족되지 않을 때 오류를 발생시키는 것은 저장소의 책임입니다.
질문 3 : 작업 단위 패턴을 사용하기로 결정하면 create
방법은 다음과 같습니다 registerNew
. 당신이하지 않으면, 아마 그것을 save
대신 호출합니다 . 리포지토리의 목표는 도메인과 데이터 계층 사이에 추상화를 제공하는 것입니다.이 때문에이 방법 ( registerNew
또는 save
)이 Employee
객체를 허용 하고 리포지토리 인터페이스를 구현하는 클래스에 따라 달라지는 것이 좋습니다. 그들은 개체를 꺼내기로 결정합니다. 전체 객체를 전달하는 것이 더 좋으므로 많은 선택적 매개 변수가 필요하지 않습니다.
질문 2 : 두 방법 모두 이제 저장소 인터페이스의 일부가되며 단일 책임 원칙을 위반하지 않습니다. 리포지토리의 책임은 Employee
개체 에 대한 CRUD 작업을 제공 하는 것입니다. 즉, 읽기 및 삭제 외에도 CRUD는 만들기 및 업데이트로 변환됩니다. 분명히, EmployeeUpdateRepository
등등 을 사용하여 저장소를 더 분할 할 수 는 있지만 거의 필요하지 않으며 단일 구현에는 일반적으로 모든 CRUD 작업이 포함될 수 있습니다.
질문 1 : 당신 Employee
은 이제 (다른 속성들 중에서) ID 를 가진 간단한 클래스로 끝났습니다 . ID가 채워 졌는지 비어 null
있는지 (또는 ) 여부는 객체가 이미 저장되었는지 여부에 따라 다릅니다. 그럼에도 불구하고, ID는 여전히 엔티티가 소유 한 속성이며 엔티티의 책임 Employee
은 해당 속성을 관리해야하므로 ID를 관리해야합니다.
엔티티에 ID가 있는지 없는지 여부는 지속성 논리를 시도 할 때까지 일반적으로 중요하지 않습니다. 질문 5에 대한 답변에서 언급했듯이 이미 저장된 엔터티를 저장하지 않거나 ID가없는 엔터티를 업데이트하려고한다는 것을 감지하는 것은 저장소의 책임입니다.
중요 사항
우려의 분리는 훌륭하지만 실제로 기능적 리포지토리 계층을 설계하는 것은 매우 지루한 작업이며 제 경험상 실제 레코드 방식보다 조금 더 어려워집니다. 그러나 훨씬 더 유연하고 확장 가능한 디자인으로 마무리 할 수 있습니다.
Employee
추상화, 질문 4. 및 5. 를 제공 할 수있는 객체를 취해야합니다 . 일반적으로 대답 할 수없고, 필요에 따라 달라집니다. 구조와 CRUD 연산을 두 클래스로 분리하면Employee
데이터를 가져올 수 없습니다. 더 이상 db에서, 그래서 대답 6입니다.