다이나믹 스코프를 가진 언어로 일하지 않는 행운을 가진 사람들을 위해, 그것이 어떻게 작동하는지 조금 알려 드리겠습니다. "RUBELLA"라는 의사 언어가 다음과 같이 작동한다고 가정 해보십시오.
function foo() {
print(x); // not defined locally => uses whatever value `x` has in the calling context
y = "tetanus";
}
function bar() {
x = "measles";
foo();
print(y); // not defined locally, but set by the call to `foo()`
}
bar(); // prints "measles" followed by "tetanus"
즉, 변수는 호출 스택을 자유롭게 위 아래로 전파합니다. 정의 된 모든 변수 foo는 해당 호출자에게 표시되며 변경 가능 bar합니다. 그 반대도 마찬가지입니다. 이는 코드 리팩토링에 심각한 영향을 미칩니다. 다음 코드가 있다고 상상해보십시오.
function a() { // defined in file A
x = "qux";
b();
}
function b() { // defined in file B
c();
}
function c() { // defined in file C
print(x);
}
이제에 대한 호출 a()이 인쇄 qux됩니다. 그러나 언젠가 b는 약간 변경해야한다고 결정합니다 . 모든 호출 컨텍스트를 알지 못하지만 (일부는 실제로 코드베이스 외부에있을 수 있음), 그래도 괜찮습니다-변경 사항이 완전히 내부에있을 것 b입니까? 따라서 다음과 같이 다시 작성하십시오.
function b() {
x = "oops";
c();
}
그리고 로컬 변수를 방금 정의했기 때문에 아무것도 변경하지 않았다고 생각할 수도 있습니다. 그러나 실제로, 당신은 고장났습니다 a! 이제 보다는 a인쇄합니다 .oopsqux
이것을 의사 언어 영역에서 다시 가져 오면 이것은 다른 구문으로도 MUMPS의 동작 방식과 정확히 동일합니다.
MUMPS의 최신 ( "현대") 버전에는 소위 NEW문이 포함되어 있는데,이를 통해 변수가 수신자로부터 발신자에게 누출되는 것을 방지 할 수 있습니다. 우리가했던 경우에 따라서 위의 첫 번째 예에서, NEW y = "tetanus"에 foo(), 다음 print(y)에 bar()(명시 적으로 다른 것으로 설정하지 않으면 MUMPS에, 모든 이름은 빈 문자열을 가리) 아무것도 출력하지 않을 것이다. 우리가있는 경우 :하지만 수신자에게 발신자로부터 누출 변수를 방지 할 수있는 건 아무것도 없다 function p() { NEW x = 3; q(); print(x); }, 우리가 알고있는 모두를 위해, q()돌연변이 수 x를 명시 적으로 수신되지에도 불구하고, x매개 변수로는. 이것은 여전히 나쁜 상황이지만, 예전 처럼 나쁘지는 않습니다 .
이러한 위험을 염두에두고 어떻게 MUMPS 또는 다른 언어로 동적 범위를 지정하여 코드를 안전하게 리팩터링 할 수 있습니까?
리팩토링을보다 쉽게하기위한 명백한 모범 사례가 있습니다. 예를 들어, NEW직접 초기화 하거나 명시적인 매개 변수로 전달 된 것 이외의 함수에서 변수를 사용하지 않고 함수의 호출자로부터 내재적으로 전달 된 매개 변수를 명시 적으로 문서화하는 것과 같습니다 . 그러나 수십 년 전 ~ 10 8 -LOC 코드베이스에서 이들은 종종 가지고 있지 않은 사치입니다.
물론, 어휘 범위를 가진 언어에서 리팩토링에 대한 모든 모범 사례는 동적 범위-쓰기 테스트 등의 언어에도 적용 할 수 있습니다. 그렇다면 리팩토링시 동적 범위 코드의 취약성 증가와 관련된 위험을 어떻게 완화 할 수 있을까요?
동적 언어로 작성된 코드를 탐색하고 리팩터링 하는 방법은 이 질문과 비슷한 제목을 갖지만 전적으로 관련이 없습니다.