문제

이 두 가지 방법이 있다고 가정합니다.

Number 1:

void AddPerson(Person person)
{
  // Validate person
  if(person.Name != null && IsValidDate(person.BirthDate)
    DB.AddPersonToDatabase(person);
}

2 번:

void AddPerson(string name, DateTime birthDate)
{
  Person p = new Person(name, birthDate);
  DB.AddPersonToDatabase(person);
}

두 가지 방법 중 가장 좋은 방법은 무엇입니까? 나는 첫 번째 것이 더 정확하다는 것을 알고 있지만, 두 번째는 더 읽을 수 있다고 생각하며 매개 변수가이를 확인하므로 객체가 유효 할 필요가 없습니다. 나는 단지 내가 전달하는 객체를 매개 변수로 전달하는 곳을 검증하는 것을 좋아하지 않습니다. 다른 접근법이 있습니까?

편집 : 모든 답변에 대한 thx. 명확히하기 위해, 생성자와 IsValid 방법에서 검증하는 것은 물론 좋은 접근법이지만, 내 코드에서 사람의 유효한 상태는 종종 컨텍스트에 의존하며 방법마다 다를 수 있습니다. 이것은 물론 나쁜 디자인의 표시 일 수 있습니다.

코드는 문제를 설명하는 예일뿐입니다.

도움이 되었습니까?

해결책

첫 번째는 person.name과 person.birthdate를 검증 할 필요가 없습니다. Person 건설자. 다시 말해, 당신이 사람을 통과한다면, 당신은 그것이 유효하다는 것을 알아야합니다.

반면에, 당신은 그것을 확인해야합니다 person 널 참조가 아닙니다.

때로는 두 번째 버전과 같은 편리한 방법을 사용하는 것이 좋습니다. 보통 전화를해야합니다 Person 생성자 후 작업을 첫 번째 양식으로 위임하십시오.

다른 팁

첫 번째는 기존 코드를 깨지 않고 사람의 정의를 변경할 수 있다는 장점이 있으며, 재 컴파일 만 필요합니다. 두 번째는 더 읽기 쉽다고 생각할 수도 있지만 첫 번째는 더 관리하기 쉽고 선택합니다.

또 다른 옵션은 다음과 같습니다.

void AddPerson(Person person)
{  // Validate person  
   if(person.IsValid)
   {
     DB.AddPersonToDatabase(person);
   }
}

그 사람이 건설 될 때 그 사람이 스스로를 검증하지 않는다고 가정합니다. 객체가 일시적 인 동안 유효하지 않은 상태가 될 수있는 경우 경우에도 어떤 경우에는 실행 가능합니다.

API의 객체에 대한 결합을 줄이기 때문에 전자 (물체를 통과) 선호합니다. 당신이 변경하면 Person 물체, 예를 들어, 새로운 속성을 추가합니다 Nickname 이전에는 필요하지 않은 첫 번째 경우에는 공개 API를 변경할 필요가 없지만 두 번째는 메소드를 변경하거나 새 오버로드를 추가해야합니다.

나는 그것이 상황에 전적으로 의존한다는 데 동의하며, 이것에 대한 절대적인 규칙은 없습니다. 제 생각에는 이와 같은 방법을 갖는 것은 말도 안됩니다.

person.SetBirthDate(Person person)
person.ResetPassword(Person person)

그러나이 경우 나는 Greg Beech가 말했듯 이이 방법이 도메인 객체에 대해 아무것도 알지 못해야하기 때문에 전자를 선호합니다.

그건 그렇고, 과부하를 고려하십시오 (건조 - 스스로 반복하지 마십시오) :

void AddPerson(Person person)
{
  if(person.Name != null && IsValidDate(person.BirthDate)
    DB.AddPersonToDatabase(person);
}

void AddPerson(string name, DateTime birthDate)
{
  Person p = new Person(name, birthDate);
  this.AddPerson(p);
}

매개 변수로 많은 원시 유형이 아니라 사람의 물체를 통과하는 것이 좋습니다. 다음 두 가지 방법을 비교하십시오


public static void Withdrawal(Account account, decimal amount)
{
    DB.UpdateBalance(account.AccountNumber, amount);
}

public static void Withdraw(int accountNumber, decimal amount)
{
    DB.UpdateBalance(accountNumber, amount);
}

두 가지 방법은 거의 동일하게 보이지만 두 번째 방법은 안전하지 않습니다. int는 어디서나 올 수 있으므로 다음을 작성하면 나사로 나사입니다.

private void CloseTransaction(Transaction tran)
{
    BankAccounts.Withdrawal(tran.Account.RoutingNumber, tran.Amount);
        // logic error: meant to pass Account.AccountNumber instead of Account.RoutingNumber
}

컴파일 오류 또는 런타임 예외를 던지지 않기 때문에 최악의 오류입니다. 충분히 글을 쓰면 자동화 된 테스트 에서이 오류를 포착 할 수 있지만이 버그는 놓치기 쉽고 발견되지 않고 몇 달 동안 숨길 수 있습니다.

저는 Bank Software를 작성한 회사에서 일했으며 실제로 이런 유형의 생산 버그를 가로 질러 실행했습니다. 그것은 특정 종류의 금고 이송 중에 만 발생했으며, 우리 은행 중 하나가 월말 프로세스를 실행할 때마다 GL 잔액이 몇 달러에 이르는 것을 발견했을 때만 발견되었습니다. 은행은 몇 달 동안 직원 도난을 의심했지만, 신중한 코드 검토를 통해서만 누군가가 소프트웨어의 버그에 문제를 추적했습니다.

나는 대부분의 시간에 첫 번째로 갈 것입니다.

두 번째는 모든 변화에 대한 서명을 깨뜨릴 것입니다.

상황에 따라 다릅니다.

모든 호출 방법이 사람 객체를 다루는 경우 첫 번째는 올바른 솔루션입니다.

그러나 호출 방법 중 일부가 이름과 생년월일을 다루고 일부는 사람 대상을 다루는 경우 두 번째 예는 올바른 해결책입니다.

나는 단지 두 가지 모두에 대한 과부하를 만들 것입니다. 특히 자동으로 생성 될 수 있다는 점을 고려하십시오.

나는 방법이 Person 유형. 그 점을 염두에두고 나는 둘 다 다른 유형에 대한 지식이 너무 많다고 생각합니다 (Person) IMO. 첫 번째 버전은 유효한 사람 인스턴스의 생성을 검증 할 필요가 없습니다. 이것이 발신자의 책임이라면 모든 발신자가이를 수행해야합니다. 부서지기 쉬워요.

두 번째 버전은이 유형의 인스턴스를 만듭니다.

첫 번째 버전을 선호하지만 해당 코드의 조각에서 유효성 검사 부분을 이동할 것입니다.

나는 존이 그것을 거의 못 박았다고 생각한다. Person 유효한 사람이 생성자가 생성되도록하는 책임이어야합니다.

창조하거나없는 공명에 대해 Person 객체 (AddPerson 메소드 또는 발신자), 읽기

http://en.wikipedia.org/wiki/grasp_%28object_oriented_design%29#creator

OOP의 책임 문제에 관한 것입니다. 애드 패더가 호출을 DB 인터페이스로 포장하는 경우 특정 경우에도 확실하지 않습니다. 그것은 그 컨텍스트 외부에서 그 사람 객체가 사용되는 것에 달려 있습니다. 데이터베이스에 추가 할 데이터를 포함 할 목적으로 전적으로 AddPerson 메소드로 작성하는 것은 클래스 사용자가 사람 클래스에 대해 알지 못하는 것을 분해하기 때문에 좋은 아이디어 일 수 있습니다. .

개체를 사용하는 경우 더 나은 캡슐화; 그것이 그들이하는 것입니다. 사람들이 프리미티브를 너무 많이 사용할 때 문제가 발생한다고 생각합니다.

유효하지 않은 사람을 만들 수는 없습니다. 생성자는 유효한 매개 변수를 확인하고 불법적 인 매개 변수를 던지거나 유효하지 않은 경우 어설 션에 실패해야합니다. 이것이 계약에 의한 프로그래밍의 모든 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top