2009-05-12 6 views
2

컨테이너의 get 접근 자 또는 나쁜 접근자를 통해 설정된 접근자를 통해 속성에 값을 할당하고 있습니까?

다음 코드를 고려하십시오.

class Program 
{ 
    static void Main(string[] args) 
    { 
     Department deathStar = new Department { Name = "Death Star" }; 

     Console.WriteLine("The manager of {0} is {1}.", deathStar.Name, deathStar.Manager.FullName); 

     deathStar.Manager.FirstName = "Lord"; 

     Console.WriteLine("The manager of {0} is {1}.", deathStar.Name, deathStar.Manager.FullName); 

     Console.ReadLine(); 
    } 
} 

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    public string FullName 
    { 
     get 
     { 
      return this.FirstName + " " + this.LastName; 
     } 
    } 
} 

public class Department 
{ 
    public string Name { get; set; } 

    public Person Manager { get; private set; } 

    public Department() 
    { 
     this.Manager = new Person { FirstName = "Darth", LastName = "Vader" }; 
    } 
} 

다음 출력을 생성합니다.

The manager of Death Star is Darth Vader. 
The manager of Death Star is Lord Vader. 

Manager를 Person의 다른 인스턴스 또는 새 인스턴스로 변경할 수는 없지만 접근 자), 속성을 변경할 수 있습니다 (public set 접근자를 가짐).

그래서, 컨테이너의 get 접근 자나 나쁜 점을 통해 접근자를 통해 속성에 값을 할당하고 있습니까? 다른 말로하면, 이것은 코드 냄새입니까?

EDIT :

이것은 하나의 요점을 설명하기위한 샘플입니다. 이 샘플에만 개인 W 부서가 작성되었습니다.

답변

2

필요하지 않습니다.

예를 들어, SqlCommand 개체의 매개 변수 컬렉션을 확인하십시오. 컬렉션의 항목을 변경할 수는 있지만 명령 개체에 새 매개 변수 컬렉션을 할당 할 수는 없습니다.

사용자 개체를 유지 관리하는 UI가 있고 명칭을 변경해야하는 경우 사용자 이름을 변경하고 성 및 PersonId 필드 만 남기고 데이터베이스를 업데이트하는 것이 좋습니다 PersonId 필드를 사용하는 테이블.

그것은 모두가 나에게 OK 소리가

0

그 라인 말하고 싶지만 :

deathStar.Manager.FirstName = "Lord"; 

는 의도에서 완벽하게 명확를, 그래서 그것은 나를 귀찮게하지 않습니다.

나를 괴롭히는 것은 관리자의 개인 세트입니다.

부서를 만든 후에는 관리자를 변경할 수 없습니다.

현실을위한 모델로서, 이것은 큰 냄새입니다.

+0

부서 내 구성원 만 관리자를 변경할 수 있다면 ID는 현실을 모델링한다고 말할 수 있습니다. 매니저가 결코 바뀔 수 없다는 말은 아닙니다. 당신 (외부인)이 그것을 바꿀 수 없다는 것입니다. – Kekoa

+0

우리는 비즈니스 규칙에 대해 아무것도 모르기 때문에, 우리는 정말로 그 측면에 대해서 논쟁 할 수 없습니다. 냄새를 맡을 필요가있는 냄새입니다. 또한 코드가 냄새를 맡으므로 그것이 잘못되었다는 것을 의미하는 것이 아니며 반드시 고쳐야한다는 의미는 아닙니다. 그것은 단지 (은유를 바꾸는) 깃발이 물결 치고 있음을 의미하며 그 부분을보아야합니다. 문제가있는 곳에서 완벽하게 맞을 수 있습니다. 주위를 냄새 맡고 확인하십시오. –

-1

나는 이것이 기능적인 언어를 너무 많이 사용하는 이유 중 하나라고 생각합니다. "부작용"이 없습니다. 기술적으로 문제가 있다고 생각하지 않지만 유지 관리가 매우 어려울 수 있습니다. Jurrasic Park의 말을 바꾸려면 "... 당신이 뭔가를 할 수 있다고해서, 꼭해야만하는 것은 아닙니다!"

+0

동의 - 나에게 기능을하는 프로그래머가 불안감을 느낀다. 덜 불안한 것은 불변의 Person 타입이다 : deathStar.Manager = new Person() {FirstName = "Lord"; 성 = deathStar.Manager.LastName}; –

0

"나쁜 것"입니까? 본질적으로 아닙니다. 그것은 당신이 수업의 디자인을 재검토해야한다는 표시입니까? 예. Person 개체를 수정하는 Department이 생성되는 이유는 무엇입니까? 대신 DepartmentChangeManager 메서드를 구현해야합니까? 그럴 수도 있고 아닐 수도 있고. 그러나 질문 할 가치가있는 질문입니다.

1

예, 이것은 코드 냄새입니다.

공개 속성은 클래스의 필드를 임의로 변경하고 구현 세부 정보에 불필요한 의존성을 부여합니다. 구조체를 사용할 수도 있습니다.(구조체가 나쁘다는 것을 의미하지는 않습니다. 절차 적 프로그래밍은 OOP만큼 유용합니다.) 문제의 해결 방법에 따라 달라집니다. 캡슐화의 핵심은 클래스의 종속 항목에서 구현 세부 사항을 숨기는 것입니다. 오히려 종속 클래스가 구현을 알 필요없이 내부 데이터를 수정할 수 있도록하는 추상 인터페이스를 노출해야합니다. 다음의 예를 고려해

public interface Vehicle { 
    double FuelTankCapacityInGallons{get;} 
    double GallonsOfGasoline{get;} 
} 

public interface Vehicle { 
    double getPercentFuelRemaining(); 
} 

두 인터페이스는 당신에게 남아있는 휘발유의 양을 얻을 것이다. 첫 번째는 구체적인 용어이고 두 번째는 추상화입니다. 탱크의 크기가 변경되거나 유럽식 차량을 구현해야하는 경우 첫 번째 예에서는 차량과 차량을 사용하는 모든 클래스를 변경해야합니다. 두 번째 단계는 Vehicle 구현 만 변경하면됩니다.

내가 사용한 예는 Robert C Martin이 작성한 Clean Code - Agile Software Craftsmanship 핸드북에서 발췌 한 것입니다.

나는 또한 Law of Demeter을 조회 할 것이다.

+0

+1, 나는 비록 개인적으로 Demeter의 법칙이 법 이라기보다는 가이드 라인이라고 생각한다. 나는 그 "법"에 복종하려고 애 쓰고있는 자신의 엉덩이를 보았다. IMHO, 이러한 교장은 당신을 위해 일해야합니다, 만약 당신이 그들을 위해 일하는 것을 발견한다면, 당신은 그것을 너무 멀리 가져 가야합니다. –

+0

예. Demeter의 법칙은 경험적이며, 따라 서면 맹목적으로 당신을 원으로 이끌 것입니다. 다른 휴리스틱과 마찬가지로 주어진 상황에 적용하지 않는 경우도 있습니다. 예를 들어 데이터 구조에는 동작이 없기 때문에 Demeter는 전혀 적용되지 않습니다. –

0

Person이 구조체가 아닌 한 Manager의 속성이 Person의 복사본을 반환하고 부서의 Manager가 아닌 해당 복사본의 FirstName 속성을 설정하게됩니다 . 하지만 어쨌든, 컴파일러는 당신이 그것을하려고한다면 비명을 질 것입니다 ...

0

그것은 OOP 순도의 문제입니다.
코드의 일부가 순수 OOP가 아니어야합니다. 프로젝트 복잡성, 관련 프로그래머 수, 유지 보수성 등의 문제입니다.
예제가 매우 간단하므로 많은 의견을 읽을 수 있습니다.
간단한 예제와 함께 OOP의 장점을 설명하기는 어렵습니다.

어쨌든, 내 생각 :
냄새가 난다.
정말 그것은 쉽게 사용 4 개 클래스를 참조

deathStar.Manager.Address.City.Name = "Paris" 

그래서 한 줄의 코드처럼 뭔가 변경할 수 있습니다

deathStar.Manager.FirstName = "Lord"; 

입니다 귀찮게 코드의 라인! 이것은 모든 4 개의 클래스의 결합이 동일하게 유지된다는 매우 강한 가정을합니다. 즉, 클래스를 고도로 결합 된 상태로 유지합니다.
구체적인 클래스가 아닌 인터페이스로 작업하여이를 해결할 수 있으며 "묻지 않음"지침 (Yahoo search; 예, Yahoo)을 채택 할 수 있습니다.
Here's a nice PDF (OOP 및 리팩토링에 대해서는 Java에서 설명하지만 쉽게 이해할 수 있음) "과도 적 결합"섹션을 참조하십시오.

관련 문제