프로그래밍 규칙보다 일관성을 선호해야합니까?


14

클래스를 설계 할 때 일반적인 프로그래밍 방식보다 동작의 일관성을 선호해야합니까? 구체적인 예를 들자면 :

일반적인 규칙은 다음과 같습니다. 클래스가 객체를 소유 한 경우 (예 : 객체를 생성 한 경우) 완료되면 정리해야합니다. .NET에서는 클래스가 IDisposable객체를 소유하는 경우 수명이 다했을 때 처리해야하는 특정 예가 있습니다 . 당신이 그것을 소유하지 않으면 그것을 만지지 마십시오.

이제 StreamWriter.NET 에서 클래스를 살펴보면 문서에서 기본 스트림이 닫히거나 처리 될 때 닫히는 것을 확인할 수 있습니다. 이것은이 경우에 필요하다 StreamWriter작가가 기본 파일 스트림을 생성하고, 따라서이를 종료해야합니다 같은 파일 이름을 전달하여 인스턴스화됩니다. 그러나 외부 스트림을 전달할 수도 있습니다.

이것은 나에게 많은 시간을 낭비했다.

내 클래스 중 하나에서 이러한 패턴에 도달하면 일반적으로 생성자를 통해 주입 된 ownsFooBar경우 false로 설정되고 FooBar그렇지 않으면 true로 설정 되는 플래그를 만듭니다 . 이렇게하면 인스턴스를 명시 적으로 전달할 때이를 정리하는 책임이 호출자에게 전달됩니다.

이제 일관성이 모범 사례보다 유리 해야하는지 궁금합니다 (또는 내 모범 사례가 그렇게 좋지 않을 수도 있음)? 그것에 대한 논쟁이 있습니까?

설명을 위해 편집

"일관성"이란 의미 : 개체를 만들거나 소유권을 명시 적으로 이전 한 경우에만 개체의 소유권을 가져 오기 위해 클래스의 일관성있는 동작이 항상 소유권 (및 스트림 닫기) 대 "모범 사례"를 취하는 것입니다.

언 노잉하는 예를 들어 보자.

데이터를 생성하고 처리하는 것과 같이 스트림을 사용하여 스트림을 허용하는 두 개의 지정된 클래스 (일부 타사 라이브러리의)가 있다고 가정하십시오.

 public class DataProcessor
 {
     public Result ProcessData(Stream input)
     {
          using (var reader = new StreamReader(input))
          {
              ...
          }
     }
 }

 public class DataSource
 {
     public void GetData(Stream output)
     {
          using (var writer = new StreamWriter(output))
          {
               ....
          }
     }
 }

이제 다음과 같이 사용하고 싶습니다.

 Result ProcessSomething(DataSource source)
 {
      var processor = new DataProcessor();
      ...
      var ms = new MemoryStream();
      source.GetData(ms);
      return processor.ProcessData(ms);
 }

Cannot access a closed stream데이터 프로세서에서 예외 로 인해 실패 합니다. 약간 구성되었지만 요점을 설명해야합니다. 그것을 고치는 다양한 방법이 있지만 그럼에도 불구하고 내가해야 할 일을 해결한다고 생각합니다.


StreamWriter의 동작이 왜 고통을 유발하는지에 대해 자세히 설명해 주시겠습니까? 다른 곳에서 같은 스트림을 사용하고 싶습니까? 왜?
Job

@ JOB : 내 질문을 명확히했다
ChrisWue

답변:


9

이 기술도 사용하고 '핸드 오프'라고하며 패턴의 상태가 필요하다고 생각합니다. 오브젝트 A가 일회용 오브젝트 B를 구성 시간 매개 변수로 승인하면 'handoff'라는 부울 (기본값은 false 임)도 허용하며, true 인 경우 A를 B로 처리합니다.

나는 다른 사람들의 불행한 선택을 확산시키는 것에 찬성하지 않기 때문에 Microsoft의 나쁜 습관을 기존의 관습으로 받아들이지 않을 것입니다. 또한 Microsoft의 불행한 선택을 따르는 다른 사람들의 맹인이 어떤 식 으로든 모양이나 형태에있어 "일관된 행동"으로 간주되지 않을 것입니다 .


참고 :이 패턴에 대한 공식적인 정의는 내 블로그 ( michael.gr : The "Handoff"Pattern)에 게시했습니다 .
Mike Nakis

handOff패턴 의 추가 확장으로서 , 그러한 특성이 생성자에 설정되어 있지만이를 수정하기위한 다른 메소드가 존재하는 경우, 다른 메소드도 handOff플래그를 승인해야합니다 . handOff현재 보유 된 품목에 대해 지정된 경우 해당 품목을 폐기하고 새 품목을 승인하고 handOff새 품목의 상태를 반영하도록 내부 플래그를 업데이트해야합니다. 원래 참조가 "핸드 오프"된 경우 원래 호출자가 보유한 모든 참조를 버려야하므로 메소드는 이전 참조와 새 참조가 동일한 지 점검 할 필요가 없습니다.
supercat

@supercat 동의하지만 마지막 문장에 문제가 있습니다. 현재 보유한 품목에 대해 핸드 오프가 사실이지만 새로 공급 된 품목이 현재 보유하고있는 품목과 동일하다면 현재 보유 된 품목을 처분하십시오 실제로 새로 공급 된 품목을 폐기합니다. 같은 품목을 재 공급하는 것은 불법이어야한다고 생각합니다.
Mike Nakis

같은 품목을 다시 공급하는 것은 일반적으로 물체가 불변이고 실제로 어떤 자원도 보유하지 않으며 처분 여부를 신경 쓰지 않는 한 불법입니다. 예를 들어, Dispose시스템 브러시에 대한 요청이 무시 된 경우 "color.CreateBrush` 메소드는 여가 시간에 새 브러시를 생성하거나 (폐기해야하는) 시스템 브러시를 반환합니다 (폐기를 무시할 수 있음). 처분에 관심이있는 경우 재사용, 처분하지 않는 경우 재사용 허용
supercat

3

나는 당신이 옳다고 생각합니다. 특히 Microsoft가 설명하는 이유로 StreamWriter 클래스를 망쳤다 고 생각합니다.

그러나 그 이후로 사람들이 프레임 워크가 스트림을 처리하기 때문에 자신의 스트림을 처리하려고 시도하지 않는 많은 코드를 보았습니다. 따라서 수정하면 좋은 것보다 더 해가됩니다.


2

나는 일관성을 가지고 갈 것입니다. 대부분의 사람들에게 언급했듯이 개체가 자식 개체를 만들면 개체를 소유하고 파괴합니다. 그것이 외부로부터 참조를받는다면, 어느 시점에서 "외부"도 같은 물체를 가지고 있고 소유해서는 안됩니다. 외부에서 객체로 소유권을 이전하려면 Attach / Detach 메서드 또는 부울을 허용하는 생성자를 사용하여 소유권이 이전되도록합니다.

완전한 대답을 위해 모든 것을 입력하면 대부분의 일반적인 디자인 패턴이 StreamWriter / StreamReader 클래스와 동일한 범주에 속할 필요는 없다고 생각합니다. MS가 StreamWriter / Reader가 자동으로 소유권을 인수하도록 선택한 이유는이 특정 인스턴스에서 소유권을 공유하는 것이 의미가 없기 때문입니다. 동일한 스트림에서 동시에 읽고 쓰는 두 개의 다른 객체를 가질 수 없습니다. 나는 당신이 어떤 종류의 결정 론적 시간 공유를 쓸 수 있다고 확신하지만 그것은 반 패턴의 지옥 일 것입니다. 스트림을 공유하는 것은 말이되지 않기 때문에 항상 그렇게하자. 그러나 나는이 행동이 모든 수업에서 전반적으로 일반적인 관례가 된 것으로 생각하지는 않을 것이다.

전달되는 객체를 디자인 관점에서 공유 할 수없는 스트림을 일관성있는 패턴으로 간주 할 수 있으므로 추가 플래그없이 리더 / 라이터가 소유권을 인수합니다.


나는 내 질문을 명확히했다-일관성을 가지고 나는 항상 소유권을 갖는 행동을 의미했다.
ChrisWue

2

조심해. "일관성"이라고 생각하는 것은 임의의 습관 모음 일 수 있습니다.

"일관성에 대한 사용자 인터페이스 조정", SIGCHI Bulletin 20, (1989), 63-65. 죄송합니다. 링크가 없습니다. 오래된 기사입니다. "... 15 명의 전문가로 구성된 이틀간의 워크숍에서 일관성의 정의를 만들 수 없었습니다." 예, "인터페이스"에 관한 것이지만, "일관성"에 대해 생각하면 정의 할 수 없다고 생각합니다.


전문가들이 서로 다른 서클에서 모이면 코드를 개발할 때 팀이 이미 잘 알고있는 기존 패턴 (또는 원하는 습관)을 따르는 것이 쉽다는 것을 알게되었습니다. 예를 들어, 며칠 전 우리 직원 중 한 명이 비동기 작업에 대해 문의하고 있었고 30 초 만에 Win32 Overlapped I / O와 동일한 방식으로 동작한다고 말했을 때 30 초 만에 전체 인터페이스를 이해했습니다. 나 자신과 그는 같은 서버 백엔드 Win32 배경에서 왔습니다. 일관성 ftw! :)
DXM

@Bruce 나는 당신의 요점을 얻습니다-나는 일관성으로 의미하는 것이 분명하다고 생각했지만 그렇지 않았습니다.
ChrisWue
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.