메소드 매개 변수로서의 식별자 대 도메인 객체


10

객체 / 고유 ID를 메소드 / 함수 매개 변수로 사용하는 것에 대한 객관적인 주장이 있습니까? (및 다른 개체의 구성원?). 특히 정적으로 유형이 지정된 언어 (C # / Java / Scala)와 관련하여

객체 자체의 장점 :

  • 더 안전한 유형의 통화. ID를 사용하면 인수 순서가 잘못 될 위험이 있습니다. 그래도 해당 클래스의 ID 만 저장하는 각 클래스에 대해 '미니'클래스를 유지하면이를 완화 할 수 있습니다.
  • 끈기에서 한 번, 다시 가져올 필요가 없습니다.
  • ID를 사용하여 ID 유형이 변경되면 int-> long과 같이 실수로 보드 전체에서 변경해야합니다. (courtsey : https://softwareengineering.stackexchange.com/a/284734/145808 )

ID 사용의 장점 :

  • 대부분의 경우 실제 객체가 필요하지 않고 uniqueid 만 수행하므로 ID를 유지하면 지속성에서 가져 오는 시간을 절약 할 수 있습니다.

내가 볼 수있는 한,이 기술들의 혼합은 둘 다의 장점과 단점이있을 뿐이다.

이것이 구체적으로 정의 된 문제라는 점을 감안할 때 객관적인 답변이 있기를 바랍니다.

편집 : 의견 제안자에 대한 맥락-유일한 제한은 정적으로 유형이 지정된 언어입니다. 이 응용 프로그램은 범용 응용 프로그램이지만 특정 사용 시나리오를 기반으로 답변을 얻을 수도 있습니다.

편집 : 좀 더 컨텍스트. 책 관리 시스템이 있다고 가정 해 봅시다. 내 모델은 :

Book: { id: Int, isbn: String, donatedBy: Member, borrowedBy: Member }
Member: {id: Int, name: String}

Table- wishlist: { isbn: String, memberId: Int}
Table- borrows:  { id: Int, memberId: Int}  

Method: 
isInWishList( book: Book, member: Member ) vs isInWishList( bookId: Int,  memberId: Int)

handleBorrowRequest( memberId: Int, book: Book ){ 
   //the login system doesn't actually get the entire member structure, only the member id. I don't need the full member yet. can run a query to verify that the memberId has less than max allowed books for borrowing. 
}

정식 회원이 아닌 ID 만 유지하고 싶은 이유는 무엇입니까? 책에 대한 정보를 얻을 때 누가 기부하거나 빌린 사람에 대해 거의 알 필요가 없습니다. donatedBy 및 차용 한 필드를 채우기 위해 전체 정보를 얻는 것은 과도합니다.

물론, 이것들은 나의 요점 일뿐입니다. 나는 물건을 놓치고 있다고 확신하므로 선호하는 점이 무엇인지 알고 싶었습니다.


좀 더 문맥으로 질문을 편집 할 수 있습니까? 시나리오가 무엇인지 명확하지 않습니다. 나는거야 생각 당신이 게으른 로딩 프록시 객체를 의미하는 "미니 클래스"에 의해 (최대 절전 모드와 같은)를 ORM 시스템에 의해 것을 관리하는 객체에 대해 얘기하고있다.
Darien

2
아마도 관련이 있습니까? programmers.stackexchange.com/questions/284634/…
hjk

여기에 주석으로 추가 (모든 기능을 갖춘 답변으로 확장 할 수있는 충분한 컨텍스트를 얻을 수있을 때까지) : 코드에 ID 값을 하드 코딩 하지 않는 한 (큰 아니오), 여전히 ID 값을로드해야합니다 어딘가에서? "대부분의 시간"도 꽤 모호한 IMHO ...
hjk

@hjk 감사합니다. 당신은 여전히 ​​어딘가에서 ID 값을로드해야한다는 점이 있습니다. 그러나 DB를 '손질'하는 것이 아니라 DB의 사용량과 대역폭을 최소화하는 것입니다. 책을 빌리려는 모든 사람들의 신분증을 얻을 수 있지만 실제로 자세한 내용을 얻는 것은 불필요합니다.
0fnt

(1) 사용 사례에 실제 속성 (열)이 필요한지 또는 해당 사용 사례 자체에 따라 ID 만 필요한지 여부; (2) ID-to-attributes 쿼리를 쉽게 수행 할 수있는 일부 캐싱 또는 성능 향상 기술을 사용하는지 여부와 사용 사례가 그러한 캐싱 구성표를 위반하기에 충분히 무겁지 않은지 여부.
rwong

답변:


8

환경 및 문제점 컨텍스트에 따라 데이터베이스를 이동해야 할 필요성을 완화 할 수 있으며 결과적으로 IMO (id 's only) 사용에 대한 인수는 유실됩니다.

예를 들어, PHP의 Doctrine2 ORM은 EntityManager::getReference제공된 id를 사용하여 엔티티에 느리게로드 된 프록시를 생성합니다. 나는 얼마나 많은 다른 ORM이 그렇게하는지 모르지만, 언급 한 "미니 클래스"의 개념과 거의 일치합니다. 대부분의 의도와 목적을 위해, 이것은 완전히 수화 된 엔티티이므로 다른 곳처럼 전달하고 사용할 수 있습니다.

그것이 유효하지 않은 유일한 경우는 유효하지 않은 ID가 주어 졌을 때이며,이 경우 어쨌든 데이터베이스로 이동하여 유효성을 검사하려고합니다. 또한 엔터티를 얻는 데 드는 비용을 줄이기 위해 대부분의 ORM에는 (첫 번째 및 두 번째 수준) 캐싱 기능이 있습니다.

데이터베이스로 이동하는 데 필요한 비용과 비용을 줄이면 엔터티를 매개 변수로 사용하는 전문가가 크게 남습니다.

  1. 타입 안전.
  2. 발신자가 요구하는 지식이 적습니다. 6 개월간 다운 된 개발자는 실수로 잘못된 엔티티의 ID를 전달할 수 없습니다.
  3. 리팩토링 비용 절감 메소드가 엔티티로부터 2 개의 정보를 요구하도록 변경 되었다면, 호출자가 완전히 수화 된 엔티티를 시작했다고 가정하면 호출자를 변경하여 비용을 지불하지 않아도됩니다.
  4. 방법 당 검증이 덜 필요합니다. 많은 메소드가 제공된 엔티티가 ORM에서 왔기 때문에 데이터베이스에 존재한다고 가정 할 수 있으므로 더 이상 ID의 유효성을 검증 할 필요가 없습니다.
  5. (잠재적으로) 더 적은 데이터베이스 호출. ID를 3 개의 메소드에 전달하고 각 메소드가 ID를 검증하거나 엔티티에서 더 많은 데이터를 가져와야하는 경우 엔티티를 페치하는 1 메소드와 2를 조작하는 데이터베이스 호출의 3 배입니다.

물론, ID를 전달하려는 경우도 있습니다. 예를 들어 경계 컨텍스트 경계를 넘을 때 (도메인 기반 디자인에서). 계정을 구성하는 개념 (예 : 재무 대 고객 관계)에 대한 개념이 다른 두 개의 제한된 컨텍스트를 고려할 경우 컨텍스트 A의 계정을 컨텍스트 B에 전달할 수 없습니다. 대신 계정 ID (도메인 언어) 통과.


캐싱은 여러 응용 프로그램 인스턴스가 실행 중이면 확장 성이 떨어집니다. 나만의 캐싱이 있습니다. 포인트는 훌륭합니다.
0fnt

ID에 대한 한 가지 더 중요한 점은 ID를 사용하면 실제로 객체를 가져 오는 유효성 검사 외에도 지속성을 호출한다는 것을 의미합니다.
0fnt

3

이런 종류의 질문에 대해, 나는 프로그래머로서의 의도를 가장 잘 전달할 수있는 솔루션을 위임하고 "Future Greg"의 직업을 가장 쉽게 만듭니다.

객체를 인수로 사용하면 6 개월 후에 메소드 호출을보다 쉽게 ​​얻을 수 있으며이 응용 프로그램의 세부 사항을 잊어 버렸습니다. "이 사람의 위시리스트에있는이 책입니까?"를 기반으로하기 위해이 isInWishList방법은 실제로 책과 멤버의 정수 ID 만 비교하면된다고 가정 해 봅시다 . 실제로이 방법은 작업을 수행하기 위해 두 개의 데이터 만 필요합니다. 이제이 한 가지 방법에서 한 걸음 물러서서 전체 소프트웨어 시스템을 살펴 보겠습니다. 나는 그것이 작동하기 위해 서적 ID와 회원 ID 만 필요하다고 의심합니다. 호출하기 전에 데이터베이스에서 전체 책과 멤버를 가져와야합니다. isInWishList왜냐하면이 메소드 하나만 호출하는 것보다 더 많은 작업이 필요할 수 있기 때문입니다. 어쩌면 당신은 할 수 있지만 대부분의 경우 더 많은 일을해야합니다.

이를 감안할 때 데이터베이스에서 두 객체를 모두 가져오고 매핑하여 성능상 실제로 페널티가 발생하지는 않습니다. 이론적으로는 데이터베이스 호출이 더 적게 필요하지만 실제로는 이것이 사실이 아니라는 것을 알게 될 것입니다. 쿼리 문자열에서 해당 ID를 매개 변수로 서버에 다시 전달하면 데이터베이스에서 위시리스트를 가져와야합니다. 그러나 이것은 전체 응용 프로그램에 대한 매우 좁은 견해입니다. 희망 목록을 확인하는 것 외에 다른 작업을 수행하는 시나리오가 있습니다 (예 : 희망 목록에 책 추가). 중복 항목을 추가하고 싶지 않습니다.

새로운 프로그래머 나 미래의 자아가 이해하기 가장 쉬운 솔루션을 찾으십시오. 이는 미래의 자기 자신 BookMember객체 를 전달하는 것 입니다. 실제 성능 문제를 찾은 후에 만 ID를 전달하는 데 정말로 관심을 가져야합니다.

또는 Java와 같은 정적으로 유형이 지정된 언어는 메소드 오버로드를 제공하므로 케이크를 가지고 먹을 수도 있습니다.

public boolean isInWishList(int bookId, int memberId) {
    // ...
}

public boolean isInWishList(Book book, Member member) {
    return isInWishList(book.getId(), member.getId());
}

이 질문에 대한 진정한 대답은 두 가지 방법을 작성하고 강력한 형식의 버전에서 정수 전용 버전을 호출하는 것이며 Bob은 삼촌입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.