변하지 않는 것이 무엇이고 어떻게 사용되며 프로그램에서 사용한 적이 있습니까?


48

나는 직장 에서 코더를 읽고 있는데 , 거기에는 불변에 대해 많은 이야기가 있습니다. 내가 이해하는 한, 불변은 표현 전후에 유지되는 조건입니다. 논리 코스를 올바르게 기억하면 루프가 올바른지 증명하는 데 유용합니다.

내 설명이 정확합니까, 아니면 무언가를 놓쳤습니까? 당신의 프로그램에서 그것들을 사용한 적이 있습니까? 그렇다면 어떻게 혜택을 얻었습니까?



@Robert Harvey : 예, 실제로 읽었습니다. 그러나 변하지 않는 것은 무언가를 증명하려고 할 때만 유용합니다. 이 말이 맞습니까?
gablin

그건 내 이해입니다. 프로그램에 대해 추론하려고 할 때 그 정확성을 증명하기 위해.
Robert Harvey

3
@ user9094 : 어설 션은 런타임의 특정 시점에서 어떤 것이 사실이며 코드로 표현된다는 선언입니다. 불변은 적용 할 때마다 항상 적용되며 코드 자체로 표현되지 않는 진술입니다.
David Thornley

1
불변은 정확성을 입증하는 데 실제로 유용하지만 그 경우에만 제한되지는 않습니다. 또한 방어 프로그래밍 및 디버깅 중에도 유용합니다. 그들은 코드가 정확하다는 것을 증명하는 데 도움을 줄뿐만 아니라 코드에 대한 추론을 도와주고 기원에 가까운 버그의 위치를 ​​찾습니다.
Oddthinking

답변:


41

OOP에서, 불변은 프로그램이 유효하기 위해 객체 수명 동안 항상 참이어야하는 일련의 주장입니다. 객체가 현재 상태를 변경하는 메소드를 실행하지 않을 때마다 생성자 끝에서 소멸자 시작까지 true를 유지해야합니다.

불변의 예는 정확히 두 멤버 변수 중 하나가 null이어야한다는 것입니다. 또는 하나의 값이 주어진 경우 다른 하나에 허용되는 값 세트는 이것 또는 저것입니다

언젠가는 객체의 멤버 함수를 사용하여 고정이 유지되는지 확인합니다. 그렇지 않은 경우 어설 션이 발생합니다. 그리고 메소드는 객체를 변경하는 각 메소드의 시작과 종료에서 호출됩니다 (C ++에서는 한 줄입니다 ...)


11
실행 메소드 중간에 불변을 언급하기위한 +1이 사실 일 필요는 없습니다.
Oddthinking

1
@Oddthinking 가능하면 가능하면 피하는 것이 가장 좋습니다. 변하지 않는 상태로 들어가고 돌아 오기 전에 모든 것을 올바르게 복원하는 것을 잊어 버릴 수 있습니다. 예외도 문제를 일으킬 수 있습니다.
Alexander

3
@Alexander : 사소한 불변의 경우 피하는 것이 거의 불가능합니다. 답변에 설명 된 것처럼 메소드에서 둘 이상의 변수를 업데이트 해야하는 경우 하나만 업데이트되고 불변은 거짓입니다. 새로운 코드를 추가하지 않고 좋은 코드를 작성하는 데 충분한 제약이 있습니다.
Oddthinking

@Oddthinking 예, 종종 피할 수없는 일입니다. 그러나 예를 들어 논리적으로 함께 속하는 변수 그룹 (예 : 배열 및 배열에서 "선택된"항목의 인덱스)이있는 경우 변수를 유형으로 추출하는 것이 좋습니다. 거기에서 배열 또는 유형의 돌연변이는 해당 유형의 새로운 인스턴스의 단일 할당으로 표현 될 수 있습니다
Alexander

13

글쎄, 내가이 글에서보고있는 것들은 모두 훌륭하지만, 나는 직장에서 나에게 큰 도움을 준 '불변'에 대한 정의를 가지고있다.

변하지 않는 것은 인간에게 전달 될 수 있지만 컴파일러와 통신 할 수없는 프로그램 실행 전체에 따라야하는 논리적 규칙입니다.

이 정의는 두 가지 그룹으로 조건을 분리하기 때문에 유용합니다. 컴파일러는 강제로 신뢰할 수있는 것과 버그를 도입하지 않고 코드베이스와 상호 작용하기 위해 문서화, 토론, 주석 처리 또는 기고자와 통신해야합니다. .

또한이 정의는 "불변 값이 나쁘다"라는 일반화를 사용할 수 있으므로 유용합니다.

예를 들어, 수동 변속기 자동차의 시프터는 변하지 않도록 설계되었습니다. 원한다면 각 기어마다 하나의 레버로 변속기를 만들 수있었습니다. 이 레버는 앞으로 ( "결합 된") 또는 뒤로 ( "분리 된") 수 있습니다. 이러한 시스템에서 "불변"을 만들었습니다.

"다른 기어가 결합되기 전에 현재 결합 된 기어를 분리하는 것이 중요합니다. 두 기어를 동시에 결합하면 기계적 응력이 발생하여 변속기가 분리됩니다. 다른 기어를 결합하기 전에 항상 현재 결합 된 기어를 분리하십시오."

따라서 조잡한 운전에서 고장난 변속기를 비난 할 수 있습니다. 그러나 현대 자동차는 기어 사이에서 회전하는 단일 스틱을 사용합니다. 그것은 현대의 스틱 시프트 카에서 동시에 두 개의 기어를 작동시킬 수 없도록 설계되었습니다.

이런 방식으로 변속기는 '불변량을 제거'하도록 설계되었다고 말할 수 있는데, 이는 논리적 규칙을 위반하는 방식으로 기계적으로 구성 될 수 없기 때문입니다.

코드에서 제거하는 이러한 종류의 불변은 코드 작업의인지 부하를 낮추기 때문에 개선 된 것입니다.


1
불변이 프로그램 실행 전체에 따라야하는 논리적 규칙이고 논리적 규칙이 동시에 두 개의 기어를 사용할 수없는 경우 두 기어가 동시에 관여 할 수있는 불변이 아닙니다 시각? 이 불변이 없으면 변속기가 동시에 두 개의 기어에있을 수 있으므로 분리됩니다. 첫째, 단일 스틱 시프터가 실제로 그 불변성을 적용하지 않습니까? 둘째, 왜 불변이 본질적으로 좋거나 나쁠까요?
더스틴 클리블랜드

1
자동차 기어와의 비교는 매우 분명합니다. 감사!
Marecky

"불변 값은 프로그램이 실행되는 동안 인간과 통신 할 수 있지만 컴파일러와 통신 할 수없는 논리적 규칙입니다." -나는 이것을 간결하고 기억하기 쉽다.
ZeroKnight

@DustinCleveland이 예제에서 스틱 시프트의 메커니즘은 규칙을 '강화'하는 '컴파일러'인 반면 사고를 유발할 수있는 드라이버는 정보를 소비하고 기억 해야하는 많은 클라이언트 중 하나라고 생각합니다. "문서화, 토론, 논평 또는 다른 방법으로 전달되었습니다."
에버 나드

훌륭한 설명! 나는 코드에 불변이있는 이유가 왜 나쁜지를 이해하고 있습니다.
벤 C 왕 4

3

변하지 않는 (상식적으로) 특정 시점이나 심지어는 프로그램이 실행되는 동안 반드시 참이어야하는 조건을 의미합니다. 예를 들어 사전 조건 및 사후 조건을 사용하여 함수가 호출 될 때와 반환 될 때 참이어야하는 일부 조건을 주장 할 수 있습니다. 객체 불변량은 객체가 존재하는 동안 유효한 상태를 가져야한다고 주장하는 데 사용될 수 있습니다. 계약 원칙에 따른 설계입니다.
코드의 검사를 사용하여 비공식적으로 변형을 사용했습니다. 그러나 더 최근에는 variant 를 직접 지원 하는 .Net 의 코드 계약 라이브러리를 사용 하고 있습니다.


3

Coders At Work의 다음 인용문을 기반으로 ...

그러나 불변량을 유지하고 있다는 것을 알면, 불변량을 유지하면 로그 조회 시간을 얻을 수 있습니다.

... "불변"= "원하는 효과를 유지하기 위해 유지하려는 조건"이라고 생각합니다.

불변에는 미묘한 방식으로 다른 두 가지 감각이있는 것 같습니다.

  1. 동일하게 유지되는 것.
  2. 목표 X를 달성하기 위해 동일하게 유지하려는 것 (예 : 위의 "로그 조회 시간")

따라서 1은 단언과 같습니다. 2는 정확성, 성능 또는 기타 속성을 입증하는 도구와 같습니다. 2의 예 는 Wikipedia 기사 를 참조하십시오 (MU 퍼즐에 대한 솔루션의 정확성 증명).

실제로 불변의 세 번째 의미는 다음과 같습니다.

.삼. 프로그램 (또는 모듈 또는 기능)이해야 할 일; 다시 말해, 그 목적입니다.

동일한 Coders At Work 인터뷰에서 :

그러나 큰 소프트웨어를 관리 할 수있게 만드는 것은 수행해야 할 작업과 수행 할 작업에 대한 글로벌 불변 또는 큰 설명을 갖는 것입니다.


1

불변은 프로그램의 논리를 지시하는 데 사용할 수있는 규칙이나 가정과 같습니다.

예를 들어 사용자 계정을 추적하는 소프트웨어 응용 프로그램이 있다고 가정합니다. 사용자가 여러 계정을 가질 수 있지만 어떤 이유로 든 사용자의 기본 계정과 "별칭"계정을 구별해야한다고 가정 해 봅시다.

이것은 DB 레코드 또는 다른 것 일 수 있지만 지금은 각 사용자 계정이 클래스 객체로 표시된다고 가정합니다.

class userAccount {private char * pUserName; 개인 char * pParentAccountUserName;

...}

변하지 않는 것은 pParentAccountUserName이 NULL이거나 비어 있으면이 개체가 부모 계정이라는 가정입니다. 이 변형을 사용하여 다른 유형의 계정을 구별 할 수 있습니다. 다른 유형의 사용자 계정을 구별하는 더 좋은 방법이있을 수 있으므로이 방법은 변형이 사용되는 방법을 보여주는 예일뿐입니다.


변수는 프로그램의 상태를 확인합니다. 그들은 디자인 결정이 아닙니다.
Xavier Nodet

3
불변은 아무것도 확인하지 않습니다. 프로그램 상태를 확인하여 불변이 참 또는 거짓인지 확인할 수 있지만, 변하지 않는 것 자체는 아무것도하지 않습니다.
Pemdas

2
일반적으로 C ++에서는 멤버 x와 같은 일종의 클래스 불변성이 25보다 작고 0보다 커야합니다. 이는 불변입니다. 그 불변에 대한 모든 검사는 주장입니다. 위의 예제에서 내 불변은 pParentAccountUserName이 NULL이거나 비어 있으면 부모 계정입니다. 불변은 의사 결정으로 설계되었습니다.
Pemdas

pParentAccountUserName이 NULL이거나 비어있는 경우이 개체가 부모 계정인지 어떻게 확인합니까? 귀하의 진술은 null / empty 값이 나타내는 것으로 만 정의합니다. 변하지 않는 것은 시스템이이를 준수한다는 것입니다. 즉, pParentAccountUserName이 부모 계정 인 경우에만 null 또는 비어있을 수 있습니다. 미묘한 차이입니다.
Cameron

1

물리학 배경에서, 물리학에서 우리는 불변량을 가지는데, 이는 본질적으로 전체 계산 / 시뮬레이션에서 변하지 않는 양입니다. 예를 들어, 물리학에서는 닫힌 시스템의 경우 총 에너지가 보존됩니다. 또는 물리학에서 두 입자가 충돌하는 경우 결과 조각에는 정확히 시작된 에너지와 정확히 같은 운동량 (벡터 양)이 포함되어야합니다. 일반적으로 결과를 완전히 지정하기위한 불변 값이 충분하지 않습니다. 예를 들어, 2 입자 충돌에서 우리는 4 개의 불변량, 3 개의 운동량 성분 및 에너지 성분을 갖지만 시스템은 6 개의 자유도 (상태를 나타내는 6 개의 숫자)를 갖습니다. 불변은 반올림 오차 내에서 보존되어야하지만 보존은 해가 옳다는 것을 증명하지는 않습니다.

따라서 일반적으로 이러한 사항은 온 전성 검사로 중요하지만 그 자체로는 정확성을 입증 할 수 없습니다.


1
-1 물리의 불변은 다릅니다. 해를 계산하는 것은 알고리즘이 올바른지 증명하는 것과 다릅니다. 후자의 경우, 불변 정확성 증명할 수 있습니다 .
aaronasterling
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.