문제

SO에 대한 토론에 이어 나는 이미 가변 구조체가 "악"이라는 말을 여러 번 읽었습니다. 질문).

C#의 가변성 및 구조체와 관련된 실제 문제는 무엇입니까?

도움이 되었습니까?

해결책

스트러크는 값 유형으로, 통과 할 때 복사됩니다.

따라서 사본을 변경하면 원본이 아닌 다른 사본이 아니라 해당 사본 만 변경합니다.

구조물이 불변 인 경우 가치별로 통과하여 발생하는 모든 자동 사본은 동일합니다.

변경하려면 수정 된 데이터로 구조물의 새 인스턴스를 작성하여 의식적으로 수행해야합니다. (사본 아님)

다른 팁

시작 장소; -p

Eric Lippert의 블로그 항상 인용에 좋습니다.

이것이 변이 가능한 가치 유형이 악한 또 다른 이유입니다. 항상 가치 유형을 불변으로 만드십시오.

첫째, 당신은 아주 쉽게 변화를 잃는 경향이 있습니다 ... 예를 들어, 목록에서 물건을 얻는 것 :

Foo foo = list[0];
foo.Name = "abc";

그 변화는 무엇입니까? 유용한 것은 없습니다 ...

속성과 동일하게 :

myObj.SomeProperty.Size = 22; // the compiler spots this one

당신이해야 할 일 :

Bar bar = myObj.SomeProperty;
bar.Size = 22;
myObj.SomeProperty = bar;

덜 비판적으로 크기 문제가 있습니다. 변한 물체 추세 여러 속성을 갖기 위해; 그러나 두 가지가있는 구조물이 있다면 ints, a string, ㅏ DateTime 그리고 a bool, 당신은 많은 기억을 빠르게 태울 수 있습니다. 클래스의 경우 여러 발신자가 동일한 인스턴스에 대한 참조를 공유 할 수 있습니다 (참조는 작습니다).

나는 말하지 않을 것이다 사악한 그러나 돌연변이 성은 종종 프로그래머 측에서 최대의 기능을 제공하기 위해 과잉의 징후입니다. 실제로, 이것은 종종 필요하지 않으며, 그 결과 인터페이스를 더 작고 사용하기 쉽고 사용하기가 더 어렵습니다 (= 더 강력한).

이것의 한 예는 인종 조건에서 읽기/쓰기 및 쓰기/쓰기 충돌입니다. 쓰기는 유효한 작업이 아니기 때문에 불변의 구조에서는 발생할 수 없습니다.

또한, 나는 그것을 주장합니다 돌연변이는 거의 실제로 필요하지 않습니다, 그냥 프로그래머 생각합니다 그것은 그 ~할 것 같다 미래에 있어야합니다. 예를 들어 날짜를 변경하는 것은 의미가 없습니다. 오히려 오래된 날짜를 기반으로 새 날짜를 만듭니다. 이것은 저렴한 작업이므로 성능은 고려 사항이 아닙니다.

돌연변이 성 구조는 악하지 않습니다.

고성능 상황에서는 절대적으로 필요합니다. 예를 들어 캐시 라인 및 또는 쓰레기 수집이 병목 현상이 될 때.

나는이 완벽하게 유효한 유스 케이스 "Evil"에서 불변의 구조물을 사용한다고 부르지 않을 것입니다.

C#의 구문이 값 유형 또는 기준 유형의 구성원의 액세스를 구별하는 데 도움이되지 않는다는 점을 알 수 있습니다. 선호합니다 불변성, 불변성을 시행하는 불변의 구조, 상호의 구조.

그러나 불변의 구조를 단순히 "악"으로 표시하는 대신, 언어를 받아들이고 더 도움이되고 건설적인 경험의 규칙을 옹호하는 것이 좋습니다.

예를 들어: "structs는 기본적으로 복사되는 값 유형입니다. 복사하지 않으려면 참조가 필요합니다." 또는"먼저 Readonly Structs와 함께 일하려고 노력하십시오".

공개 변경 가능 필드나 속성이 있는 구조체는 나쁘지 않습니다.

"this"를 변경하는 구조체 메서드(속성 설정자와 구별됨)는 다소 사악합니다. 단, .net이 이를 그렇지 않은 메서드와 구별하는 수단을 제공하지 않기 때문입니다."this"를 변경하지 않는 구조체 메서드는 방어 복사가 필요 없이 읽기 전용 구조체에서도 호출 가능해야 합니다."this"를 변경하는 메서드는 읽기 전용 구조체에서 전혀 호출할 수 없어야 합니다..net은 "this"를 수정하지 않는 구조체 메서드가 읽기 전용 구조체에서 호출되는 것을 금지하고 싶지 않지만 읽기 전용 구조체가 변경되는 것을 허용하지 않기 때문에 방어적으로 구조체를 읽기 전용 구조체로 복사합니다. 상황만 설명할 뿐이며 두 세계 모두에서 최악의 결과를 얻을 수 있습니다.

그러나 읽기 전용 컨텍스트에서 자체 변경 메서드를 처리하는 데 따른 문제에도 불구하고 변경 가능한 구조체는 변경 가능한 클래스 유형보다 훨씬 우수한 의미 체계를 제공하는 경우가 많습니다.다음 세 가지 메서드 서명을 고려하세요.

struct PointyStruct {public int x,y,z;};
class PointyClass {public int x,y,z;};

void Method1(PointyStruct foo);
void Method2(ref PointyStruct foo);
void Method3(PointyClass foo);

각 방법에 대해 다음 질문에 답하십시오.

  1. 메서드가 "안전하지 않은" 코드를 사용하지 않는다고 가정하면 foo를 수정할 수 있습니까?
  2. 메서드가 호출되기 전에 'foo'에 대한 외부 참조가 존재하지 않으면 이후에도 외부 참조가 존재할 수 있습니까?

답변:

질문 1:
Method1():아니요 (명확한 의도)
Method2():예 (명확한 의도)
Method3():예 (의도 불확실)
질문 2:
Method1():아니요
Method2():아니요 (안전하지 않은 경우 제외)
Method3():예

Method1은 foo를 수정할 수 없으며 참조를 얻지 못합니다.Method2는 foo에 대한 단기 참조를 가져오며 반환될 때까지 foo의 필드를 순서에 관계없이 여러 번 수정할 수 있지만 해당 참조를 유지할 수는 없습니다.Method2가 반환되기 전에 안전하지 않은 코드를 사용하지 않는 한 'foo' 참조로 만들어졌을 수 있는 모든 복사본이 사라집니다.Method2와 달리 Method3은 foo에 대해 난잡하게 공유 가능한 참조를 가져오며 이를 사용하여 무엇을 할 수 있는지 알 수 없습니다.foo를 전혀 변경하지 않을 수도 있고, foo를 변경한 다음 반환할 수도 있고, foo에 대한 참조를 다른 스레드에 제공하여 임의의 미래 시간에 임의의 방식으로 변경할 수도 있습니다.Method3가 전달된 변경 가능한 클래스 개체에 대해 수행할 수 있는 작업을 제한하는 유일한 방법은 변경 가능한 개체를 읽기 전용 래퍼로 캡슐화하는 것입니다. 이는 보기 흉하고 번거롭습니다.

구조 배열은 훌륭한 의미를 제공합니다.Rectangle 유형의 RectArray[500]을 고려하면 다음과 같은 방법이 명확하고 분명합니다.요소 123을 요소 456에 복사한 다음 얼마 후 요소 456을 방해하지 않고 요소 123의 너비를 555로 설정합니다."RectArray[432] = RectArray[321];...;RectArray[123].Width = 555;".Rectangle이 Width라는 정수 필드가 있는 구조체라는 것을 알면 위의 설명에 대해 알아야 할 모든 것을 알 수 있습니다.

이제 RectClass가 Rectangle과 동일한 필드를 가진 클래스이고 RectClass 유형의 RectClassArray[500]에 대해 동일한 작업을 수행하려고 한다고 가정합니다.아마도 배열은 변경 가능한 RectClass 객체에 대해 사전 초기화된 변경 불가능한 참조 500개를 보유해야 할 것입니다.이 경우 적절한 코드는 "RectClassArray[321].SetBounds(RectClassArray[456]);...;RectClassArray[321].X = 555;".아마도 배열은 변경되지 않을 인스턴스를 보유한다고 가정하므로 적절한 코드는 "RectClassArray[321] = RectClassArray[456];...;RectClassArray[321] = New RectClass(RectClassArray[321]);RectClassArray[321].X = 555;" 무엇을 해야 하는지 알려면 RectClass(예:복사 생성자, 복사 방법 등) 및 배열의 ​​의도된 사용법을 지원합니까?구조체를 사용하는 것만큼 깨끗한 곳은 없습니다.

불행하게도 배열 이외의 컨테이너 클래스가 구조체 배열의 깔끔한 의미를 제공할 수 있는 좋은 방법은 없습니다.예를 들어 컬렉션을 색인화하려는 경우 가장 좋은 방법은 다음과 같습니다.문자열은 인덱스용 문자열, 일반 매개변수, 일반 매개변수와 컬렉션 항목 모두를 참조로 전달하는 대리자를 허용하는 일반 "ActOnItem" 메서드를 제공하는 것일 수 있습니다.이는 구조체 배열과 거의 동일한 의미를 허용하지만, vb.net 및 C# 사용자가 멋진 구문을 제공하도록 유도할 수 없다면 코드는 합리적으로 성능이 뛰어나더라도 투박해 보일 것입니다(일반 매개변수를 전달하면 정적 대리자 사용을 허용하고 임시 클래스 인스턴스를 만들 필요가 없습니다.

개인적으로 Eric Lippert 등의 증오에 화가 납니다.변경 가능한 값 유형에 관해 설명합니다.여기저기서 사용되는 난잡한 참조 유형보다 훨씬 깔끔한 의미 체계를 제공합니다..net의 값 유형 지원에 대한 일부 제한에도 불구하고 변경 가능한 값 유형이 다른 유형의 엔터티보다 더 적합한 경우가 많습니다.

가치 유형은 기본적으로 불변의 개념을 나타냅니다. FX, 정수, 벡터 등과 같은 수학적 값을 갖고 수정할 수있는 것은 의미가 없습니다. 그것은 값의 의미를 재정의하는 것과 같습니다. 값 유형을 변경하는 대신 다른 고유 한 값을 할당하는 것이 더 합리적입니다. 속성의 모든 값을 비교하여 값 유형이 비교된다는 사실을 생각해보십시오. 요점은 속성이 동일하다면 해당 값의 보편적 인 표현이라는 것입니다.

Konrad가 언급 한 바와 같이, 값은 해당 고유 한 시점을 나타내고 상태 또는 컨텍스트 의존성이있는 시간 개체의 인스턴스가 아니라 날짜를 변경하는 것이 합리적이지 않습니다.

이것이 당신에게 의미가 있기를 바랍니다. 그것은 당신이 실제 세부 사항보다 값 유형으로 캡처하려는 개념에 관한 것입니다.

프로그래머 관점에서 예측할 수없는 행동으로 이어질 수있는 또 다른 커플 코너 케이스가 있습니다. 여기 몇 가지.

  1. 불변의 가치 유형과 준비된 필드

// Simple mutable structure. 
// Method IncrementI mutates current state.
struct Mutable
{
    public Mutable(int i) : this() 
    {
        I = i;
    }

    public void IncrementI() { I++; }

    public int I {get; private set;}
}

// Simple class that contains Mutable structure
// as readonly field
class SomeClass 
{
    public readonly Mutable mutable = new Mutable(5);
}

// Simple class that contains Mutable structure
// as ordinary (non-readonly) field
class AnotherClass 
{
    public Mutable mutable = new Mutable(5);
}

class Program
{
    void Main()
    {
        // Case 1. Mutable readonly field
        var someClass = new SomeClass();
        someClass.mutable.IncrementI();
        // still 5, not 6, because SomeClass.mutable field is readonly
        // and compiler creates temporary copy every time when you trying to
        // access this field
        Console.WriteLine(someClass.mutable.I);

        // Case 2. Mutable ordinary field
        var anotherClass = new AnotherClass();
        anotherClass.mutable.IncrementI();

        //Prints 6, because AnotherClass.mutable field is not readonly
        Console.WriteLine(anotherClass.mutable.I);
    }
}

  1. 변이 가능한 값 유형 및 배열

돌연변이 가능한 구조물의 배열이 있다고 가정하고 해당 배열의 첫 번째 요소에 대한 ycrementi 메소드를 호출한다고 가정 해 봅시다. 이 전화에서 어떤 행동을 기대하고 있습니까? 배열의 값을 변경해야합니까, 아니면 사본 만 변경해야합니까?

Mutable[] arrayOfMutables = new Mutable[1];
arrayOfMutables[0] = new Mutable(5);

// Now we actually accessing reference to the first element
// without making any additional copy
arrayOfMutables[0].IncrementI();

//Prints 6!!
Console.WriteLine(arrayOfMutables[0].I);

// Every array implements IList<T> interface
IList<Mutable> listOfMutables = arrayOfMutables;

// But accessing values through this interface lead
// to different behavior: IList indexer returns a copy
// instead of an managed reference
listOfMutables[0].IncrementI(); // Should change I to 7

// Nope! we still have 6, because previous line of code
// mutate a copy instead of a list value
Console.WriteLine(listOfMutables[0].I);

따라서, 당신과 나머지 팀이 당신이하고있는 일을 명확하게 이해하는 한, 돌연변이 가능한 구조는 사악하지 않습니다. 그러나 프로그램 동작이 예상되는 것과 다를 때 코너 사례가 너무 많아서 미묘한 생산하기 어렵고 오류를 이해하기 어려울 수 있습니다.

C/C ++와 같은 언어로 프로그래밍 된 경우 스트러크는 변이 가능하게 사용하는 것이 좋습니다. 그냥 심판으로 전달하면 잘못 될 수있는 것이 없습니다. 내가 찾은 유일한 문제는 C# 컴파일러의 제한 사항이며, 어떤 경우에는 구조물이 C# 클래스의 일부일 때와 같이 구조물에 대한 참조를 사용하도록 멍청한 것을 강요 할 수 없다는 것입니다. ).

따라서 돌연변이가있는 구조는 사악하지 않습니다. C#은 만들어진 그들 악. 나는 항상 C ++에서 돌연변이 성을 사용하며 매우 편리하고 직관적입니다. 대조적으로, C#은 객체를 처리하는 방식으로 인해 수업 구성원으로서 구조를 완전히 포기하게 만들었습니다. 그들의 편의는 우리에게 비용이 들었습니다.

1,000,000 구조 배열이 있다고 상상해보십시오. 각 구조물은 Bid_price, Offer_Price (아마도 Decimals) 등과 같은 것들로 자본을 나타내는 C#/VB에 의해 생성됩니다.

다른 기본 코드 스레드가 어레이에 동시에 액세스 할 수 있도록 관리되지 않은 힙에 할당 된 메모리 블록에 배열이 생성되었다고 상상해보십시오 (아마도 일부 고지 코드를 수학).

C#/VB 코드가 가격 변동의 시장 피드를 듣고 있다고 상상해보십시오. 그 코드는 배열의 일부 요소에 액세스 한 다음 일부 가격 필드를 수정해야 할 수도 있습니다.

이것이 초당 수십만 또는 수십만 번 이루어지고 있다고 상상해보십시오.

사실에 직면하게합니다.이 경우 우리는 이러한 구조를 돌연변이하기를 원합니다. 다른 기본 코드에 의해 공유되기 때문에 사본을 만드는 것이 도움이되지 않기 때문입니다. 이 속도에서 약 120 바이트 구조물의 사본을 만드는 것은 미치광이이기 때문에 특히 업데이트가 실제로 바이트에만 영향을 줄 수있는 경우 미치광이이기 때문입니다.

휴고

스트러크가 의도 한 내용 (C#, Visual Basic 6, Pascal/Delphi, C ++ struct 유형 (또는 클래스)이 포인터로 사용되지 않으면 구조가 화합물 변수. 즉,이를 의미합니다. 공통 이름 (멤버를 참조하는 레코드 변수)으로 포장 된 변수 세트로 취급합니다.

나는 많은 사람들이 OOP에 깊이 사용 된 많은 사람들을 혼란스럽게한다는 것을 알고 있지만, 그러한 것들이 본질적으로 사악하다고 말할 충분한 이유는 아닙니다. 일부 구조물은 의도 한대로 작동 할 수 없습니다 (이것은 Python의 경우입니다. namedtuple), 그러나 그것은 고려해야 할 또 다른 패러다임입니다.

예 : structs는 많은 기억을 포함하지만, 수행함으로써 정확히 더 많은 기억은 아닙니다.

point.x = point.x + 1

비교 :

point = Point(point.x + 1, point.y)

메모리 소비량은 적어도 동일하거나 더 많은 경우에도 동일하거나 더 많은 경우입니다 (이 경우는 언어에 따라 현재 스택의 경우 일시적이지만).

그러나 마지막으로 구조가 있습니다 구조, 개체가 아닙니다. 똥에서, 대상의 주요 특성은 그들의 신원, 대부분의 시간은 메모리 주소 이상이 아닙니다. Struct는 데이터 구조를 나타냅니다 (적절한 객체가 아니므로 신원이 없음). 데이터를 수정할 수 있습니다. 다른 언어로 기록 (대신에 구조, Pascal의 경우와 마찬가지로)는 단어이며 동일한 목적을 보유하고 있습니다. 데이터 레코드 변수는 파일에서 읽히고 수정되고 파일에 덤프됩니다 (주된 용도 및 많은 언어에서는 가능합니다. 레코드에서 데이터 정렬을 정의하는 반면 반드시 적절하게 객체라고하는 경우는 아닙니다).

좋은 예를 원하십니까? 스트러크는 파일을 쉽게 읽는 데 사용됩니다. 파이썬이 있습니다 이 도서관 객체 지향적이고 스트러크에 대한 지원이 없기 때문에 다른 방식으로 구현해야했는데, 이는 다소 추악한 것입니다. 구현 구현 스트러크에는 그 기능이 내장되어 있습니다. Pascal 또는 C와 같은 언어로 적절한 구조물이있는 비트 맵 헤더를 읽으십시오 (구조물이 올바르게 구축되고 정렬 된 경우, Pascal에서는 레코드 기반 액세스를 사용하지 않고 임의의 이진 데이터를 읽는 기능을 사용합니다). 따라서 파일과 직접 (로컬) 메모리 액세스의 경우 스트러크가 객체보다 낫습니다. 오늘날 우리는 JSON과 XML에 익숙해 져서 이진 파일의 사용 (그리고 부작용으로 스트러크 사용)의 사용을 잊어 버립니다. 그러나 그렇습니다 : 그것들은 존재하며 목적이 있습니다.

그들은 악하지 않습니다. 올바른 목적으로 그것들을 사용하십시오.

망치의 관점에서 생각한다면, 나사를 손톱으로 취급하고 나사를 찾기 위해 벽에 뛰어 들기가 더 어렵고 나사의 결함이 될 것이며 악의가 될 것입니다.

무언가가 변이될 수 있으면 정체성을 얻게 됩니다.

struct Person {
    public string name; // mutable
    public Point position = new Point(0, 0); // mutable

    public Person(string name, Point position) { ... }
}

Person eric = new Person("Eric Lippert", new Point(4, 2));

왜냐하면 Person 변경 가능하므로 생각하는 것이 더 자연스럽습니다. 에릭의 입장을 바꾸다 ~보다 Eric 복제, 복제 이동, 원본 파괴.두 작업 모두의 내용을 변경하는 데 성공합니다. eric.position, 그러나 하나는 다른 것보다 더 직관적입니다.마찬가지로 Eric을 수정하는 방법을 찾기 위해 Eric을 참조로 전달하는 것이 더 직관적입니다.메소드에 Eric의 복제본을 제공하는 것은 거의 항상 놀라운 일이 될 것입니다.돌연변이를 원하는 사람 Person 참조를 요청하는 것을 기억해야합니다 Person 아니면 그들은 잘못된 일을 할 것입니다.

유형을 변경할 수 없게 만들면 문제가 사라집니다.내가 수정할 수 없다면 eric, 내가 받든 말든 나에게는 아무런 차이가 없습니다. eric 또는 다음의 클론 eric.보다 일반적으로 관찰 가능한 모든 상태가 다음 중 하나의 멤버에 포함된 경우 유형을 값으로 전달하는 것이 안전합니다.

  • 불변
  • 참조 유형
  • 값으로 전달해도 안전함

이러한 조건이 충족되면 변경 가능한 값 유형은 참조 유형처럼 동작합니다. 얕은 복사본을 사용하면 수신자가 원본 데이터를 수정할 수 있기 때문입니다.

불변의 직관성 Person 그래도 당신이하려는 일에 달려 있습니다.만약에 Person 단지 데이터 세트 사람에 관해서는 직관적이지 않은 것이 없습니다. Person 변수는 실제로 추상을 나타냅니다. 가치, 객체가 아닙니다.(이 경우 이름을 다음으로 바꾸는 것이 더 적절할 것입니다. PersonData.) 만약에 Person 실제로 사람 그 자체를 모델링하는 것이라면, 원본을 수정한다고 생각하는 함정을 피했더라도 계속해서 복제본을 만들고 이동한다는 아이디어는 어리석은 것입니다.그런 경우에는 단순히 만드는 것이 더 자연스러울 것입니다. Person 참조 유형(즉, 클래스)

물론, 함수형 프로그래밍을 통해 다음과 같은 이점을 얻을 수 있다고 배웠습니다. 모든 것 불변(아무도 비밀리에 참조를 보유할 수 없음) eric 그리고 그를 변형시키십시오). 그러나 이는 OOP에서 관용적이지 않기 때문에 귀하의 코드를 작업하는 다른 사람에게는 여전히 직관적이지 않을 것입니다.

그것은 structs와 관련이 없지만 (C#은 아님) Java에서는 해시 맵의 키 일 때 변한 물체에 문제가 생길 수 있습니다. 지도에 추가 한 후 변경하면 변경하면 해시 코드, 사악한 일이 일어날 수 있습니다.

개인적으로 코드를 볼 때 다음은 나에게 꽤 끔찍해 보입니다.

data.value.set (data.value.get () + 1);

단순히보다는

data.value ++; 또는 data.value = data.value + 1;

데이터 캡슐화는 클래스를 통과 할 때 유용하며 값을 제어 된 방식으로 수정하려고합니다. 그러나 공개 세트가 있고 값을 전달하는 것 이상을 설정하는 것 이상의 기능을 얻을 때 단순히 공개 데이터 구조를 전달하는 것보다 어떻게 개선 되었습니까?

클래스 내부에서 개인 구조를 만들 때 변수 세트를 하나의 그룹으로 구성하기 위해 해당 구조를 만들었습니다. 클래스 범위 내에서 해당 구조를 수정하고 해당 구조의 사본을 얻지 않고 새로운 인스턴스를 만들 수 있기를 원합니다.

나에게 이것은 공개 변수를 구성하는 데 사용되는 구조의 유효한 사용을 방지합니다. 액세스 컨트롤을 원한다면 클래스를 사용합니다.

Eric Lippert 씨의 예에는 몇 가지 문제가 있습니다. 그것은 스트러크가 복사된다는 점을 설명하는 데 도움이됩니다. 예를 살펴보면 나는 나쁜 프로그래밍 습관의 결과로, 실제로 구조물이나 클래스에 문제가되지 않습니다.

  1. 구조물에는 공개 회원 만 있어야하며 캡슐화가 필요하지 않아야합니다. 그렇다면 실제로 유형/클래스 여야합니다. 당신은 정말로 같은 말을하기 위해 두 가지 구조가 필요하지 않습니다.

  2. 구조물을 둘러싸고있는 클래스가있는 경우, 클래스의 메소드를 호출하여 멤버 구조물을 돌연변이합니다. 이것이 내가 좋은 프로그래밍 습관으로 할 일입니다.

적절한 구현은 다음과 같습니다.

struct Mutable {
public int x;
}

class Test {
    private Mutable m = new Mutable();
    public int mutate()
    { 
        m.x = m.x + 1;
        return m.x;
    }
  }
  static void Main(string[] args) {
        Test t = new Test();
        System.Console.WriteLine(t.mutate());
        System.Console.WriteLine(t.mutate());
        System.Console.WriteLine(t.mutate());
    }

구조물 자체와의 문제가 아닌 프로그래밍 습관의 문제인 것 같습니다. 스트러크는 변이되어야합니다. 즉, 아이디어와 의도입니다.

변화의 결과가 예상대로 동작합니다.

1 2 3 키를 눌러 계속하십시오. . .

변이 가능한 데이터에는 많은 장점과 단점이 있습니다. 백만 달러 규모의 단점은 별명입니다. 동일한 값이 여러 곳에서 사용되고 그 중 하나가 변경되면 사용중인 다른 장소로 마술처럼 변경된 것으로 보입니다. 이것은 인종 조건과 관련이 있지만 동일하지는 않습니다.

백만 달러의 장점은 때로는 모듈성입니다. Mutable State를 사용하면 알 필요가없는 코드에서 변경 정보를 숨길 수 있습니다.

통역사의 예술 이러한 트레이드 오프에 들어가서 몇 가지 예를 들어 몇 가지 예를 제공합니다.

나는 그들이 올바르게 사용하면 그들이 악한 믿지 않습니다. 나는 그것을 제작 코드에 넣지 않았지만 구조물의 수명이 비교적 작는 구조화 된 장치 테스트 모의와 같은 것에 대해서는 할 것입니다.

Eric 예제를 사용하면 아마도 그 Eric의 두 번째 인스턴스를 만들고 싶지만 테스트의 특성 (즉, 복제, 수정)이므로 조정을 수행합니다. 테스트 비교로 그를 사용할 계획이 아니라면 테스트 스크립트의 나머지 부분에 ERIC2를 사용하는 경우 Eric의 첫 인스턴스에서 어떤 일이 발생하는지는 중요하지 않습니다.

이것은 주로 특정 물체 (스트러크의 지점)를 얕게 정의하는 레거시 코드를 테스트하거나 수정하는 데 유용하지만, 불변의 구조물을 가짐으로써 이는 사용이 성가신 것을 방지합니다.

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