전역은 데이터베이스와 어떻게 다릅니 까?


250

방금 전 세계 국가에 대한 악의를 묻는 이 오래된 질문을 가로 질러 뛰어 들었습니다 . 최고의 찬사로 받아 들여진 대답은 다른 변수가 다른 곳에서 와서 수정 할 수 있기 때문에 전역 변수와 호환되는 코드를 신뢰할 수 없다고 주장합니다. 값과 다음 데이터가 다르기 때문에 당신은 당신의 코드의 동작이 무엇인지 모른다! 그러나 그것을 볼 때 도움이 될 수는 없지만 그것이 실제로 약한 설명이라고 생각합니다. 왜냐하면 그것이 데이터베이스에 저장된 데이터를 사용하는 것과 다른 점이 있기 때문입니다.

프로그램이 데이터베이스의 데이터로 작업하는 경우 시스템의 다른 코드가 변경하는지 또는 완전히 다른 프로그램이 변경하더라도 상관 없습니다. 데이터가 무엇인지 상관하지 않습니다. 그게 요점입니다. 중요한 것은 코드에서 발생하는 데이터를 올바르게 처리한다는 것입니다. (분명히 여기서 캐싱 문제가 자주 발생하는 것에 대해 영광스러워하고 있지만 지금은 무시하겠습니다.)

그러나 작업중 인 데이터가 데이터베이스 (또는 사용자 입력 또는 네트워크 소켓 또는 파일 등)와 같이 코드가 제어 할 수없는 외부 소스에서 온 것이고 잘못된 것은 없습니다. 그렇다면 코드 자체 내의 글로벌 데이터 (프로그램이 훨씬 더 많은 수준의 제어권을 가짐)가 어떻게 문제로 보지 않는 완벽하게 정상적인 것보다 훨씬 덜 나쁜지 어떻게 알 수 있습니까?


117
베테랑 회원들이 교리에 약간 도전하는 것을 보게되어 기쁩니다.
svidgen

10
응용 프로그램에서 일반적으로 데이터베이스에 액세스하는 수단을 제공합니다.이 평균은 데이터베이스에 액세스하려는 함수로 전달됩니다. 전역 변수로는 그렇게하지 않고 단순히 변수가 있다는 것을 알고 있습니다. 그것은 바로 중요한 차이입니다.
Andy

45
전역 상태는 임의의 수의 응용 프로그램에서 동시에 많은 열을 액세스하는 단일 행이있는 단일 테이블이있는 단일 데이터베이스를 갖는 것과 같습니다.
BevynQ

42
데이터베이스도 악하다.
Stig Hemmer

27
여기서 당신이 한 주장을 "반전시키고"다른 방향으로 나아가는 것이 재미 있습니다. 다른 구조체에 대한 포인터가있는 구조체는 논리적으로 한 테이블의 한 행에있는 외래 키이며 다른 테이블의 다른 행에 키입니다. 어떻게와 협력하고 있는 도보를 포함하여, 코드 연결리스트 데이터베이스에 데이터를 조작에서 어떤 다른? 답 : 그렇지 않습니다. 질문 : 왜 그런 다른 도구를 사용하여 메모리 내 데이터 구조와 데이터베이스 내 데이터 구조를 조작해야합니까? 답 : 정말 모르겠습니다! 좋은 디자인보다는 역사의 사고처럼 보입니다.
Eric Lippert

답변:


118

먼저, 당신이 그 특정 문제를 과장하여 연결하고 전 세계 국가의 주요 악의에 대한 대답은 예측할 수없는 방식으로 커플 링을 도입하여 나중에 시스템의 동작을 변경하는 것을 어렵게 할 수 있다는 것입니다.

그러나이 문제를 더 자세히 살펴보면 일반적인 객체 지향 응용 프로그램의 전역 상태와 데이터베이스에있는 상태 사이에는 차이가 있습니다. 간단히 말해서, 이들 중 가장 중요한 것은 :

  • 객체 지향 시스템은 객체가 원래 유형의 하위 유형 인 한 다른 객체 클래스로 교체 할 수 있습니다. 이를 통해 data 뿐만 아니라 동작 을 변경할 수 있습니다 .

  • 응용 프로그램의 전역 상태는 일반적으로 데이터베이스에 대한 강력한 일관성을 보장하지 않습니다. 데이터베이스에 대해 일관된 상태를 보거나 원자 업데이트가없는 트랜잭션이 없습니다.

또한 데이터베이스 상태를 필요한 악으로 볼 수 있습니다. 시스템에서 제거 할 수 없습니다. 그러나 글로벌 상태는 불필요합니다. 우리는 그것을 완전히 제거 할 수 있습니다. 따라서 데이터베이스의 문제도 마찬가지로 문제가 많았지 만 잠재적 인 문제 중 일부 를 제거 할 수 있으며 부분 솔루션은 솔루션이없는 것보다 낫습니다.


44
일관성의 요점은 실제로 주된 이유라고 생각합니다. 전역 변수가 코드에 사용되는 경우 실제로 실제로 초기화되는 시점을 알 수 없습니다. 모듈 간의 종속성은 일련의 호출 내부에 깊이 숨겨져 있으며 두 개의 호출을 바꾸는 것과 같은 간단한 것들이 처음 사용되었을 때 갑자기 일부 전역 변수가 더 이상 올바르게 초기화되지 않기 때문에 정말 불쾌한 버그를 생성 할 수 있습니다. 적어도 이것이 내가 작업 해야하는 레거시 코드와 관련된 문제이며 리팩토링을 악몽으로 만듭니다.
cmaster

24
@DavidHammen 저는 실제로 온라인 게임의 세계 상태 시뮬레이션을 작업했습니다.이 게임은 분명히 당신이 이야기하는 응용 프로그램 범주에 있으며 심지어는 글로벌 상태를 사용하지 않을 것입니다. 전역 상태를 사용하여 일부 효율성을 얻을 수 있지만 문제는 전역 상태를 확장 할 수 없다는 것 입니다. 단일 스레드에서 다중 스레드 아키텍처로 이동하면 사용 하기어려워 집니다 . 그것은되고 비효율적 인 당신이 NUMA 아키텍처로 이동합니다. 분산 아키텍처로 이동 하면 불가능 해집니다 . 인용 한 논문은 다음과 같습니다.
Jules

24
1993.이 문제는 그다지 문제가되지 않았습니다. 저자는 단일 프로세서 시스템에서 작업하여 1,000 개의 객체의 상호 작용을 시뮬레이션했습니다. 현대 시스템에서는 최소한 듀얼 코어 시스템에서 이러한 종류의 시뮬레이션을 실행할 수 있지만 단일 시스템에서는 6 코어 이상일 수 있습니다. 더 큰 문제가 계속 발생하면 클러스터에서 실행해야합니다. 이런 종류의 변경을 위해서는 전역 상태를 효과적으로 공유 할 수 없으므로 전역 상태를 피해야합니다 .
Jules

19
데이터베이스 상태를 "필요한 악"이라고 부르는 것은 약간의 확장이라고 생각합니다. 국가가 언제부터 악이 되었습니까? 상태는 데이터베이스의 전체 목적입니다. 상태는 정보입니다. 상태가 없으면 운영자 만 있으면됩니다. 조작 할 것이없는 오퍼레이터는 무엇입니까? 그 상태는 어딘가로 가야합니다. 하루가 끝나면 함수형 프로그래밍은 끝의 수단 일 뿐이며 상태를 변경하지 않으면 아무런 작업도 수행 할 필요가 없습니다. 그것은 케이크를 필요한 악이라고 부르는 빵 굽는 사람과 비슷합니다. 그것은 악한 것이 아닙니다. 그것은 모든 것의 요점입니다.
J ...

5
@DavidHammen "아직도 게임의 모든 객체에 대해 조금 알고있는 객체가 여전히 있습니다"반드시 그런 것은 아닙니다. 현대의 분산 시뮬레이션의 주요 기술은 지역성을 활용하고 먼 물체가 멀리있는 모든 것을 알 필요 가 없고 , 먼 물체의 소유자가 어떤 데이터를 제공하는지 근사치를 만드는 것입니다.
JAB

75

첫째, 당신이 연결 한 질문에 대한 답을 바탕으로 전역 변수의 문제점은 무엇입니까?

간단히 말해 프로그램 상태를 예측할 수 없게 만듭니다.

데이터베이스는 대부분 ACID를 준수합니다. ACID는 특히 데이터 저장소를 예측할 수 없거나 신뢰할 수 없게 만드는 근본적인 문제를 해결합니다.

또한 전역 상태는 코드의 가독성을 손상시킵니다.

전역 변수는 사용법과는 거리가 멀고 다른 파일에도 존재할 수 있기 때문입니다. 데이터베이스를 사용할 때 읽고있는 코드에 로컬 인 레코드 세트 또는 ORM 오브젝트를 사용 중입니다.

데이터베이스 드라이버는 일반적으로 문제 도메인에 관계없이 동일한 데이터에 액세스 할 수있는 일관되고 이해하기 쉬운 인터페이스를 제공합니다. 데이터베이스에서 데이터를 가져 오면 프로그램 에 데이터 사본 이 있습니다. 업데이트는 원 자성입니다. 동기화를 직접 추가하지 않으면 여러 스레드 또는 메소드가 원 자성없이 동일한 데이터에서 작동 할 수있는 전역 변수와 대조됩니다. 데이터 업데이트는 예측할 수 없으며 추적하기가 어렵습니다. 업데이트는 인터리브 될 수 있으며 멀티 스레드 데이터 손상의 bog 표준 교과서 예제 (예 : 인터리브 증가)를 유발할 수 있습니다.

데이터베이스는 일반적으로 전역 변수와 다른 데이터를 모델링하여 시작하지만, 잠시 후에 데이터베이스는 전역 변수에 대한 많은 우려를 완화하는 ACID 호환 데이터 저장소가되도록 설계되었습니다.


4
+1 당신이 말하는 것은 데이터베이스에 트랜잭션이 있어서 여러 개의 전역 상태를 원자 적으로 읽고 쓸 수 있다는 것 입니다. 좋은 점은 완전히 독립적 인 정보 에 대해 전역 변수를 사용해야 만 회피 할 수 있습니다 .
l0b0

1
@ l0b0 트랜잭션은 대부분의 ACID 목표를 달성하는 메커니즘입니다. 그러나 DB 인터페이스 자체는 데이터를보다 로컬 범위로 가져와 코드를 더 명확하게 만듭니다. try-with-resources 블록과 함께 JDBC RecordSet을 사용하거나 단일 함수 호출을 사용하여 데이터를 가져 오는 ORM 함수를 사용하십시오. 이것을 전 세계 어디에서나 읽고있는 코드에서 멀리 떨어진 데이터를 관리하는 것과 비교하십시오.

1
따라서 함수 시작 부분에 값을 로컬 변수 (뮤텍스 포함)에 복사하고 로컬 변수를 수정 한 다음 값을 전역 변수에 다시 복사하면 전역 변수를 사용하는 것이 좋습니다. 함수? (... 그는 수사적으로 물었다.)
RM

1
@RM 그는 두 가지 점을 언급했다. 당신이 버린 것은 첫 번째 (프로그램 상태는 예측 불가능)를 해결할 수 있지만 두 번째는 (코드의 가독성)을 다루지 않습니다. 사실, 프로그램의 가독성이 더 나빠질 수 있습니다. : P.
riwalk

1
@RM 함수가 일관되게 실행됩니다. 그러나 그 동안 다른 변수가 전역 변수를 수정했는지 여부에 대한 의문이 생겼으며 그 수정은 사용자가 작성하는 것보다 중요합니다. 물론 데이터베이스에도 같은 문제가있을 수 있습니다.
Graham

45

몇 가지 관찰을 제공합니다.

예, 데이터베이스는 전역 상태입니다.

사실, 당신이 지적했듯이, 그것은 초 세계적 상태입니다. 그것은의 보편적! 그 범위는 수반 아무것도 또는 누군가 데이터베이스에 연결합니다. 그리고 수년간의 경험을 가진 많은 사람들이 데이터의 "이상한 일"이 하나 이상의 관련 응용 프로그램에서 "예기치 않은 행동"을 초래 한 것에 대한 공포 이야기를 들려 줄 수 있다고 생각합니다 ...

전역 변수를 사용할 경우 발생할 수있는 결과 중 하나는 두 개의 개별 "모듈"이 고유 한 목적으로 해당 변수를 사용한다는 것입니다. 그리고 그 정도로 데이터베이스 테이블도 다르지 않습니다. 같은 문제에 희생 될 수 있습니다.

흠 ... 여기 일이 있습니다 :

어떤 방식 으로든 모듈이 외적으로 작동하지 않으면 아무 것도하지 않습니다.

유용한 모듈이 될 수 주어진 데이터를하거나 수행 할 수 있습니다 찾을 수 를. 또한 데이터 를 반환 하거나 상태 를 수정할 수 있습니다 . 그러나 외부 세계와 어떤 식 으로든 상호 작용하지 않으면 아무것도 할 수 없습니다.

이제 데이터 를 수신하고 데이터를 반환 하는 것이 좋습니다. 대부분의 모듈은 외부 세계가하는 일을 전혀 무시하고 작성할 수있는 경우 쓰기가 더 쉽습니다. 그러나 궁극적으로 무엇인가 할 필요가 찾아 데이터 및 수정 이 외부 세계 상태.

또한 실제 응용 프로그램에는 다양한 작업을 통해 데이터를 읽고 업데이트 할 수 있도록 데이터가 존재 합니다. 일부 문제는 잠금 및 트랜잭션으로 방지됩니다. 그러나 원칙적 으로 이러한 작업이 원칙적 으로 서로 충돌하는 것을 막기 위해서는 신중한 사고가 필요 합니다. (그리고 실수하는 중 ...)

또한 우리는 일반적으로 세계 국가와 직접 협력하지 않습니다 .

응용 프로그램이 데이터 계층 (SQL 등)에 상주하지 않는 한, 모듈이 작업하는 객체는 실제로 공유 전역 상태 의 복사본 입니다. 우리는 실제 공유 상태에 영향을 미치지 않고 원하는 것을 할 수 있습니다 .

그리고, 우리가 그 글로벌 상태를 변경해야 할 경우, 우리가 제공 한 데이터가 변경되지 않았다는 가정하에, 일반적으로 로컬 글로벌에서하는 것과 같은 종류의 잠금을 수행 할 수 있습니다.

우리가보다 그리고 마지막으로, 우리는 일반적으로 데이터베이스와 다른 일을 할 수도 나쁜 전역 때와.

장난스럽고 부서진 세계는 다음과 같습니다.

Int32 counter = 0;

public someMethod() {
  for (counter = 0; counter < whatever; counter++) {
    // do other stuff.
  }
}

public otherMethod() {
  for (counter = 100; counter < whatever; counter--) {
    // do other stuff.
  }
}

우리는 단순히 그와 같은 프로세스 / 운영에 데이터베이스를 사용하지 않습니다. 그리고 데이터베이스의 느린 특성과 우리를 방해하는 간단한 변수의 상대적 편리함이있을 수 있습니다. 데이터베이스와의 느리고 어색한 상호 작용은 단순히 변수 로 인해 우리가 역사적으로했던 많은 실수에 대한 나쁜 후보됩니다.


3
데이터베이스에서 "주어진 데이터가 변경되지 않았다"는 것을 보장 하는 방법 은 트랜잭션 일 것입니다.
l0b0

그렇습니다. "같은 종류의 잠금 장치"로 암시되어야합니다.
svidgen

그러나 하루가 끝나면 신중하게 생각하기가 어려울 수 있습니다.

예, 데이터베이스는 실제로 전역 상태이므로 git 또는 ipfs와 같은 것을 사용하여 데이터를 공유하고 싶어합니다.
윌리엄 페인 12

21

나는 다음과 같은 기본적인 주장에 동의하지 않습니다.

프로그램이 데이터베이스의 데이터로 작업하는 경우 시스템의 다른 코드가 변경하는지 또는 완전히 다른 프로그램이 변경하더라도 상관 없습니다.

나의 초기 생각은 "와우. 저스트 와우"였다. 이를 피하기 위해 많은 시간과 노력을 들이고 각 응용 프로그램에서 어떤 장단점과 타협점을 해결해야합니다. 그것을 무시하는 것은 재난의 요리법입니다.

그러나 나는 또한 건축 수준에서 이견을 보인다. 전역 변수는 단순한 전역 상태가 아닙니다. 어디에서나 투명하게 액세스 할 수있는 글로벌 상태입니다. 데이터베이스를 사용하는 것과 달리 핸들을 가져야합니다 (글로벌 변수에 핸들보다 저장하지 않는 한.)

예를 들어 전역 변수를 사용하면 다음과 같이 보일 수 있습니다

int looks_ok_but_isnt() {
  return global_int++;
}

int somewhere_else() {
  ...
  int v = looks_ok_but_isnt();
  ...
}

그러나 데이터베이스를 사용하여 동일한 작업을 수행하면 해당 작업에 대해 더 명확해야

int looks_like_its_using_a_database( MyDB * db ) {
   return db->get_and_increment("v");
}

int somewhere_else( MyBD * db ) { 
   ...
   v = looks_like_its_using_a_database(db);
   ...
}

데이터베이스 하나가 데이터베이스와 분명히 맞물려 있습니다. 데이터베이스를 사용하지 않으려면 명시 적 상태를 사용할 수 있으며 데이터베이스의 경우와 거의 같습니다.

int looks_like_it_uses_explicit_state( MyState * state ) {
   return state->v++;
}


int somewhere_else( MyState * state ) { 
   ...
   v = looks_like_it_uses_explicit_state(state);
   ...
}

따라서 데이터베이스를 사용하는 것이 전역 변수를 사용하는 것보다 명시 적 상태를 사용하는 것과 훨씬 비슷하다고 주장합니다.


2
네, OP가 다음과 같이 말했을 때 흥미 로웠다고 생각했습니다. " 데이터가 무엇이든 상관하지 않습니다. 그것이 요점입니다. "-우리가 신경 쓰지 않는다면 왜 저장해야합니까? 생각은 다음과 같습니다 . 변수와 데이터 사용을 중단 하십시오 . 그렇게하면 훨씬 간단 해집니다. "세상을 멈추고 내리고 싶다!"

1
+1 동일한 데이터베이스에서 읽고 쓰는 다른 스레드 또는 앱은 수많은 잘 알려진 문제의 잠재적 원인이므로 데이터베이스 또는 앱 수준에서이를 처리하기위한 전략이 항상 있어야합니다. 양자 모두. 따라서 귀하 (앱 개발자)가 다른 사람이 데이터베이스에서 읽고 쓰는 것에 신경 쓰지 않는다는 것은 사실이 아닙니다.
Andres F.

1
+1 참고로,이 답변은 의존성 주입에 대해 내가 가장 싫어하는 것을 설명합니다. 이러한 종류의 종속성을 숨 깁니다.
jpmc26

@ jpmc26 단어를 표시 할 수도 있지만 위의 종속성 주입 (전역 조회와 달리)이 종속성을 명시 적으로 만드는 데 도움이되는 좋은 예는 아닙니까? JAX-RS 및 Spring에서 사용하는 주석 마술과 같은 특정 API에서 문제를 겪고있는 것처럼 보입니다.
Emil Lundberg

2
@EmilLundberg 아니요, 문제는 계층 구조가있을 때입니다. 의존성 주입은 상위 계층의 코드에서 하위 계층의 종속성을 숨기므로 상호 작용하는 항목을 추적하기가 어렵습니다. 예를 들어, MakeNewThing의존 MakeNewThingInDb하고 컨트롤러 클래스가를 사용하는 MakeNewThing경우 컨트롤러 의 코드에서 데이터베이스를 수정하고 있는지 명확하지 않습니다. 그렇다면 실제로 현재 트랜잭션을 DB에 커밋 하는 다른 클래스를 사용하면 어떻게 됩니까? DI는 개체의 범위를 제어하기가 매우 어렵습니다.
jpmc26

18

상태가 다른 곳에서 변경 될 수 있기 때문에 전역 변수를 신뢰할 수없는 유일한 이유는 그 자체로 사용하지 않을 정도로 합리적이지 않다는 것입니다 (그러나 꽤 좋은 이유입니다!). 대답은 주로 코드 영역에만 변수의 액세스를 제한하는 것이 더 의미가있는 사용법을 설명하는 것입니다.

그러나 데이터베이스는 "전 세계적으로"액세스 할 수 있도록 설계 되었기 때문에 다른 문제입니다.

예를 들면 다음과 같습니다.

  • 데이터베이스는 일반적으로 데이터베이스에 액세스하는 언어보다 더 우수한 유형 및 구조 유효성 검사를 제공합니다.
  • 데이터베이스는 트랜잭션을 기반으로 거의 만장일치로 업데이트하므로 일관성이없는 상태를 방지합니다 (단일 상태로 숨겨져 있지 않은 경우).
  • 데이터베이스 구조는 테이블 또는 객체 구조를 기반으로 최소한 암시 적으로 문서화됩니다.

그러나 가장 중요한 것은 데이터베이스가 전역 변수와 다른 목적으로 사용됩니다. 데이터베이스는 대량의 체계화 된 데이터를 저장하고 검색하기위한 것으로, 글로벌 변수는 특정 틈새를 제공합니다 (정당한 경우).


1
허. 나는 거의 같은 대답을 쓰는 도중에 나를 이겼다. :)
Jules

@Jules 답변은 응용 프로그램 측면에서 더 자세한 정보를 제공합니다. 보관해라.
Jeffrey Sweeney

그러나 데이터 액세스를위한 저장 프로 시저에 전적으로 의존하지 않는 한 해당 구조는 모두 테이블이 의도 한대로 사용되도록 강제하지 않습니다. 또는 해당 작업이 적절한 순서로 수행됩니다. 또는 필요에 따라 잠금 (트랜잭션)이 작성됩니다.
svidgen

안녕하세요, Java와 같은 정적 유형의 언어를 사용하는 경우 포인트 1과 3이 계속 적용됩니까?
Jesvin Jose

@aitchnyu 반드시 그런 것은 아닙니다. 요점은 데이터베이스가 일반적으로 전역 변수가 아닌 데이터를 안정적으로 공유하기 위해 구축되었다는 것입니다. 엄격한 언어로 자체 문서화 인터페이스를 구현하는 객체는 느슨한 유형의 NoSQL 데이터베이스와는 다른 목적으로 사용됩니다.
Jeffrey Sweeney

10

그러나 그것을 볼 때 도움이 될 수는 없지만 그것이 실제로 약한 설명이라고 생각합니다. 왜냐하면 그것이 데이터베이스에 저장된 데이터를 사용하는 것과 다른 점이 있기 때문입니다.

또는 대화식 장치, 파일, 공유 메모리 등을 사용한 작업과는 다릅니다. 실행될 때마다 똑같은 작업을 수행하는 프로그램은 매우 지루하고 다소 쓸모없는 프로그램입니다. 예, 그것은 약한 논쟁입니다.

나에게 전역 변수와 관련하여 차이점을 만드는 차이점은 숨겨져 있고 보호되지 않은 통신 회선을 형성한다는 것입니다. 키보드에서 읽는 것은 매우 분명하고 보호됩니다. 특정 기능을 호출해야하는데 키보드 드라이버에 액세스 할 수 없습니다. 파일 액세스, 공유 메모리 및 예제 데이터베이스에도 동일하게 적용됩니다. 이 함수는 키보드에서 읽고, 함수는 파일에 액세스하고, 일부 다른 함수는 공유 메모리에 액세스하고 (그 주위에 더 나은 보호 기능이 있음), 일부 다른 함수는 데이터베이스에 액세스한다는 것은 코드 독자에게 명백합니다.

반면에 전역 변수를 사용하면 전혀 분명하지 않습니다. API가을 호출한다고합니다 foo(this_argument, that_argument). 호출 순서에는 전역 변수 g_DangerWillRobinson가 어떤 값으로 설정되어야하지만 호출하기 전에 foo(또는 호출 후에 검사 되어야 함) 말하는 것은 없습니다 foo.


Google은 C ++에서 상수가 아닌 참조 인수의 사용을 금지했습니다. 왜냐하면 상수가 아닌 참조를 인수로 foo(x)사용 x하기 때문에 변경 될 코드의 독자에게는 분명하지 않기 때문입니다 foo. (함수 정의와 호출 사이트 둘 다 ref키워드 로 참조 매개 변수를 규정해야한다는 C #과 비교하십시오 .) 이에 대한 Google 표준에 동의하지 않지만 그 요점을 이해합니다.

코드는 한 번 작성되고 몇 번 수정되었지만, 코드가 양호하면 여러 번 읽 힙니다. 숨겨진 커뮤니케이션 라인은 매우 업장입니다. C ++의 비 const 참조는 사소한 숨겨진 통신 회선을 나타냅니다. 좋은 API 나 좋은 IDE는 "Oh! 이것은 참조에 의한 호출"이라는 것을 보여줍니다. 전역 변수는 숨겨진 숨겨진 커뮤니케이션 라인입니다.


대답이 더 합리적입니다.
Billal Begueradj

8

나는 인용 된 설명이 논증이 터무니없는 지점까지 문제를 단순화한다고 생각합니다. 물론 외부 데이터베이스의 상태는 전역 상태에 영향을줍니다. 중요한 질문은 어떻게프로그램은 (변경 가능) 전역 상태에 따라 다릅니다. 공백으로 문자열을 분할하는 라이브러리 함수가 데이터베이스에 저장된 중간 결과에 의존하는 경우 적어도 동일한 목적으로 사용되는 전역 문자 배열에 대해 이의를 제기하는 것만 큼이 디자인에 반대합니다. 반면, 애플리케이션이이 시점에서 비즈니스 데이터를 저장하기 위해 완전한 DBMS가 필요하지 않다고 결정하고 글로벌 메모리 내 키-값 구조가 그렇게한다고해서 반드시 디자인이 나쁜 것은 아닙니다. 중요한 것은 – 데이터를 저장하기 위해 어떤 솔루션을 선택하든이 선택은 시스템의 아주 작은 부분에 격리되어 있기 때문에 대부분의 구성 요소는 배포를 위해 선택한 솔루션과 독립적으로 테스트되고 배포 된 솔루션에 대해 무시할 수 있다는 것입니다. 적은 노력으로 나중에 솔루션을 변경할 수 있습니다.


8

임베디드 펌웨어를 주로 사용하는 소프트웨어 엔지니어 인 저는 거의 항상 모듈 간 모든 것을 위해 전역 변수를 사용하고 있습니다. 실제로 임베디드에 대한 모범 사례입니다. 정적으로 할당되므로 힙 / 스택을 날릴 위험이 없으며 함수 입력 / 종료시 스택 할당 / 정리에 걸리는 시간이 없습니다.

이것의 단점은 우리가 있다는 것입니다 않는 그 변수를 사용하는 방법을 생각해야하고, 그 많은 데이터베이스 논쟁에가는 생각의 같은 종류로 내려 온다. 모든 비동기 읽기 / 변수의 쓰기는 반드시 원자합니다. 둘 이상의 장소가 변수를 쓸 수 있다면 어떤 사람들은 항상 유효한 데이터를 쓰도록해야하므로 이전의 쓰기는 임의로 대체되지 않습니다 (또는 임의의 대체는 안전한 일입니다). 동일한 변수를 두 번 이상 읽는 경우 변수가 읽기 사이에서 값을 변경하거나 시작시 변수 사본을 가져 와서 처리가 일관된 값을 사용하여 수행되도록하는 경우 발생하는 상황을 고려해야합니다. 처리하는 동안 해당 값이 오래됩니다.

(마지막 날, 항공기 대책 시스템에서 작업하는 계약의 첫날에 매우 안전하므로 소프트웨어 팀은 일주일 정도 알아 내려고 시도한 버그 보고서를보고있었습니다. 개발 도구와 코드 사본을 다운로드 할 시간이 충분했지만 "변수 사이에 변수를 업데이트하여 읽을 수 없습니까?"라고 물었지만 실제로 답변을 얻지 못했습니다. 그래서 그들은 여전히 ​​그것을 논의하고있는 동안, 변수를 원자 적으로 읽을 수있는 보호 코드를 추가하고, 지역 빌드를했고, 기본적으로 "이봐, 이걸 시도 해봐."라고 말했다. :)

따라서 전역 변수는 분명 나쁜 것은 아니지만 신중하게 생각하지 않으면 광범위한 문제에 노출됩니다.


7

판단하는 측면에 따라 전역 변수와 데이터베이스 액세스는 세계와 다를 수 있지만 종속성으로 판단하는 한 동일합니다.

순수 함수에 대한 함수형 프로그래밍의 정의가 입력으로 취하는 매개 변수에만 의존하여 결정 론적 출력을 생성해야한다는 상태를 고려해 봅시다. 즉, 동일한 인수 세트가 두 번 주어지면 동일한 결과를 생성해야합니다.

함수가 전역 변수에 의존하는 경우, 동일한 세트 또는 인수에 대해 전역 변수의 값이 호출간에 변경되었을 수 있으므로 다른 출력을 생성 할 수 있으므로 더 이상 순수한 것으로 간주 될 수 없습니다.

그러나 전역 변수를 다른 인수만큼 함수 인터페이스의 일부로 간주하면 함수가 결정 론적 인 것으로 보일 수 있으므로 문제가되지 않습니다. 문제는 명백하게 보이는 함수에서 예기치 않은 동작에 놀라게 될 때까지 숨겨진다는 것입니다 . 그런 다음 구현을 읽고 숨겨진 종속성을 찾으십시오 .

이 부분에서 전역 변수가 숨겨진 의존성이되는 순간은 우리 프로그래머가 악한 것으로 간주합니다. 코드를 추론하기 어렵고, 동작 방식을 예측하기 어렵고, 재사용하기 어렵고, 테스트하기가 어렵고, 특히 문제 발생시 디버그 및 수정 시간이 늘어납니다.

데이터베이스에 대한 종속성을 숨길 때도 마찬가지입니다. 데이터베이스 쿼리와 명령을 직접 호출하는 함수 또는 객체를 가질 수 있으며, 이러한 종속성을 숨기고 전역 변수로 인해 발생하는 것과 동일한 문제를 일으 킵니다. 또는 우리는 그것들을 명시 적으로 만들 수 있습니다. 이것은 결과적으로 저장소 패턴, 데이터 저장소, 게이트웨이 등과 같은 많은 이름을 사용하는 모범 사례로 간주됩니다.

추신 : 동시성이 포함되는지 여부와 같이이 비교에 중요한 다른 측면이 있지만 그 점은 다른 답변으로 덮여 있습니다.


나는 당신이 의존성 각도에서 이것을 취한 것을 좋아합니다.
cbojar

6

좋아, 역사적 지점에서 시작하자.

우리는 전형적인 어셈블리와 C의 조합으로 작성된 오래된 응용 프로그램에 있습니다 . 함수는 없으며 절차있습니다 . 프로 시저에서 인수 또는 리턴 값을 전달하려는 경우 전역 변수를 사용합니다. 말할 것도없이, 이것은 추적하기가 매우 어렵고, 일반적으로 모든 프로시 저는 모든 전역 변수로 원하는 것을 수행 할 수 있습니다. 당연히 사람들은 가능한 한 빨리 인수를 전달하고 다른 방식으로 값을 반환했습니다 (예 : 빌드 엔진 (Duke 3D) 소스 코드 확인). 전역 변수에 대한 증오가 여기에서 태어났습니다. 각 프로 시저가 읽고 변경할 전역 상태 조각이 무엇인지 거의 알지 못했고 실제로 프로 시저 호출을 안전하게 중첩 할 수 없었습니다.

이것이 전역 변수 증오가 과거의 일이라는 것을 의미합니까? 좀 빠지는.

먼저, 현재 작업중 인 프로젝트에서 인수를 전달 하는 것과 똑같은 접근법 을 보았습니다 . 약 10 년 된 프로젝트에서 C #으로 두 개의 참조 유형 인스턴스를 전달합니다. 말 그대로 이와 같은 좋은 이유는 없으며,화물 배양이나 C # 작동 방식에 대한 완전한 오해에서 비롯된 것 같습니다.

더 큰 요점은 전역 변수를 추가함으로써 해당 전역 변수에 액세스 할 수있는 모든 단일 코드의 범위를 확장한다는 것입니다. "방법을 짧게 유지"와 같은 모든 권장 사항을 기억하십니까? 600 개의 전역 변수가있는 경우 (다시 실제 예제 : /) 모든 메서드 범위는 600 개의 전역 변수에 의해 암시 적으로 확장되며 누가 무엇에 액세스 할 수 있는지 추적 할 수있는 간단한 방법이 없습니다.

잘못 된 경우 (일반적인 방법 :)) 전역 변수는 서로 연결되어있을 수 있습니다. 그러나 그것들이 어떻게 연결되어 있는지 모릅니다. 그리고 글로벌 상태가 항상 일관성을 유지할 수있는 메커니즘은 없습니다. 일관된 내용을 유지하고 유지하기 위해 중요한 섹션을 소개하더라도 적절한 ACID 데이터베이스와 비교할 수 없을 것입니다.

  • "트랜잭션"전에 이전 값을 유지하지 않으면 부분 업데이트를 롤백 할 방법이 없습니다. 말할 필요도없이,이 시점에서 인수로 값을 전달하는 것은 이미 승리입니다 :)
  • 동일한 상태에 액세스하는 모든 사람 은 동일한 동기화 프로세스를 준수 해야 합니다. 그러나이를 시행 할 방법은 없습니다. 중요 섹션 설정을 잊어 버린 경우 문제가 생길 수 있습니다.
  • 모든 액세스를 올바르게 동기화하더라도 부분적으로 수정 된 상태에 액세스하는 중첩 된 호출이있을 수 있습니다. 즉, 교착 상태 (중요한 섹션이 미숙 한 경우)이거나 일관되지 않은 데이터 (아직없는 경우)를 처리해야합니다.

이러한 문제를 해결할 수 있습니까? 실제로는 아닙니다. 이를 처리하려면 캡슐화가 필요하거나 실제로는 엄격한 규율이 ​​필요합니다. 올바른 일을하기는 어렵고 소프트웨어 개발에서 성공하기위한 좋은 방법은 아닙니다. :)

범위가 작을수록 코드를 쉽게 추론 할 수 있습니다. 전역 변수를 사용하면 가장 간단한 코드조차도 거대한 범위의 범위를 포함합니다.

물론 이것이 글로벌 범위가 악하다는 것을 의미하지는 않습니다. 단지 첫 번째 솔루션이되어서는 안됩니다. "구현하기가 간단하고 유지하기가 어려운"전형적인 예입니다.


실제 세계와 비슷하게 들립니다. 롤백하기가 매우 어렵습니다.

이것은 좋은 대답이지만, 처음에는 논문 발표 (TL; DR 섹션)가 될 수 있습니다.
jpmc26

6

전역 변수는 도구이며 선과 악에 사용될 수 있습니다.

데이터베이스는 도구이며 선과 악을 위해 사용될 수 있습니다.

원래 포스터가 지적했듯이 그 차이는 그리 크지 않습니다.

경험이없는 학생들은 종종 버그가 다른 사람들에게 발생한다고 생각합니다. 교사는 "글로벌 변수는 악하다"는 잘못된 디자인에 불이익을주는 간단한 이유로 사용합니다. 학생들은 일반적으로 100 줄 프로그램에 버그가 없다고해서 10000 줄 프로그램에 같은 방법을 사용할 수 있다는 것을 이해하지 못합니다.

데이터베이스를 다룰 때는 프로그램이 전부이기 때문에 전역 상태를 금지 할 수 없습니다. 대신 ACID 및 일반 양식 등과 같은 자세한 지침을 얻을 수 있습니다.

사람들이 전역 변수에 ACID 접근 방식을 사용했다면 그리 나쁘지 않을 것입니다.

반면에 데이터베이스를 잘못 디자인하면 악몽이 될 수 있습니다.


3
stackoverflow에 대한 일반적인 학생 주장 : 도와주세요! 내 코드는 완벽하지만 제대로 작동하지 않습니다!
David Hammen

"전역 변수에 대한 ACID 접근"-Clojure의 참조를 참조하십시오.
Charles Duffy

@DavidHammen과 전문가들은 학생들과 달리 두뇌가 있다고 생각하십니까?
Billal Begueradj

@BillalBEGUERADJ-전문가와 학생의 차이입니다. 우리는 수년간의 경험과 코드 검토, 테스트 등의 최선의 노력에도 불구하고 코드가 완벽하지 않다는 것을 알고 있습니다.
David Hammen


5

나에게 가장 큰 악은 Globals가 동시성 문제로부터 보호하지 못한다는 것입니다. Globals에서 이러한 문제를 처리하는 메커니즘을 추가 할 수 있지만, 동시성 문제를 많이 해결할수록 Global이 데이터베이스를 모방하기 시작합니다. 이차적 악은 사용 계약이 아닙니다.


3
예를 들어 errnoC.
David Hammen에서

1
이것은 왜 전역과 데이터베이스가 동일하지 않은지를 설명합니다. 다른 차이점이있을 수 있지만 특정 게시물은 개념을 완전히 파괴합니다. 빠른 코드 예제를 제공하면 많은 공감대를 얻게 될 것입니다. 예 : MyFunc () {x = globalVar * 5; // .... 다른 처리; y = globalVar * 34; // Ooops, 일부 다른 스레드는 다른 처리 중에 globalVar를 변경했을 수 있으며 x와 y는 계산에서 globalVar에 대해 다른 값을 사용하므로 바람직한 결과를 얻지 못할 것입니다.
Dunk

5

다른 답변 중 일부는 데이터베이스를 사용하는 것이 좋은 이유를 설명하려고합니다. 그들은 틀렸다! 데이터베이스는 전역 상태이므로 싱글 톤이나 전역 변수만큼 악합니다. 로컬 맵이나 배열을 쉽게 사용할 수있을 때 데이터베이스를 사용하는 것은 모든 종류의 잘못입니다!

전역 변수는 전역 액세스를 허용하여 악용 될 위험이 있습니다. 전역 변수에도 장점이 있습니다. 전역 변수는 일반적으로 절대 사용해서는 안되는 것이 아니라 피해야하는 것으로 알려져 있습니다. 쉽게 피할 수 있다면 피해야합니다. 그러나 이점이 단점보다 클 경우에는 반드시 사용해야합니다! *

전역 변수와 마찬가지로 전역 상태 인 데이터베이스에도 똑같은 사실 **이 적용됩니다. 데이터베이스에 액세스하지 않고 수행 할 수 있고 결과 논리가 필요한 모든 작업을 수행하고 복잡하게 수행하는 경우 데이터베이스를 사용하면 상응하는 이점없이 프로젝트에 위험이 증가합니다.

실제로 많은 응용 프로그램에는 디자인에 따라 전역 상태가 필요하며 때로는 영구적 인 전역 상태가 필요하기 때문에 파일, 데이터베이스 등이 있습니다.


* 여기서는 예외입니다. 학생들이 전역 변수를 사용하지 못하게하여 대안이 무엇인지 배워야합니다.

** 일부 답변은 데이터베이스가 다른 형태의 전역 상태보다 어떻게 더 잘 보호된다고 잘못 주장하고 있습니다 (질문은 전역 변수가 아니라 전역 상태 에 관한 것입니다 ). 그것은 자물쇠입니다. 데이터베이스 시나리오에서 제공되는 기본 보호는 규칙에 따라 다른 전역 상태와 동일합니다. 대부분의 언어는 또한 const생성자에서 설정된 후 상태를 변경하는 것을 허용하지 않는 클래스 또는 스레드 정보 또는 프로그램 상태를 고려할 수있는 getter 및 setter의 형태로 전역 상태에 대해 많은 추가 보호를 허용합니다.


2

어떤 의미에서, 전역 변수와 데이터베이스의 구별은 오브젝트의 개인 구성원과 공용 구성원의 구별과 유사합니다 (누구나 여전히 공용 필드를 사용한다고 가정). 전체 프로그램을 객체로 생각하면 전역 변수는 개인 변수이고 데이터베이스는 공용 필드입니다.

여기서 중요한 차이점은 가정 된 책임 중 하나입니다.

객체를 작성할 때 멤버 메소드를 유지 관리하는 사람은 개인 필드가 올바르게 작동하는지 확인한다고 가정합니다. 그러나 당신은 이미 공공 장소의 상태에 대한 모든 가정을 포기하고 추가주의를 기울여 취급합니다.

동일한 가정이 더 넓은 수준에서 globals v / s 데이터베이스에 적용됩니다. 또한, 프로그래밍 언어 / 생태계는 (비공유 메모리) 전역 v / s 데이터베이스에 적용하는 것과 동일한 방식으로 개인 v 공개에 대한 액세스 제한을 보장합니다.

멀티 스레딩이 작동하면 private v / s public v / s global v / s 데이터베이스의 개념은 스펙트럼에 따른 차이 일뿐입니다.

static int global; // within process memory space
static int dbvar; // mirrors/caches data outside process memory space

class Cls {
    public: static int class_public; // essentially the same as global
    private: static int class_private; // but public to all methods in class

    private: static void method() {
        static int method_private; // but public to all scopes in method
        // ...
        {
            static int scope1_private; // mutex guarded
            int the_only_truly_private_data;
        }
        // ...
        {
            static int scope2_private; // mutex guarded
        }
    }
}

1

데이터베이스 전역 상태 일 수 있지만 항상 그럴 필요는 없습니다. 나는 당신이 통제 할 수 없다는 가정에 동의하지 않습니다. 이를 관리하는 한 가지 방법은 잠금 및 보안입니다. 이것은 레코드, 테이블 또는 전체 데이터베이스에서 수행 할 수 있습니다. 또 다른 방법은 데이터가 오래된 경우 레코드 변경을 방지하는 일종의 버전 필드를 사용하는 것입니다.

전역 변수와 마찬가지로 데이터베이스의 값은 잠금이 해제되면 변경 될 수 있지만 액세스를 제어하는 ​​방법은 여러 가지가 있습니다 (모든 개발자에게 데이터를 변경할 수있는 계정에 암호를 제공하지 마십시오). 액세스가 제한된 변수가 있다면 그다지 전역 적이 지 않습니다.


0

몇 가지 차이점이 있습니다.

  • 데이터베이스 값 즉시 수정 될 있습니다. 반면에 코드에 설정된 전역 값은 응용 프로그램을 재배치하고 코드를 수정하지 않으면 변경할 수 없습니다 . 실제로 이것은 의도적 인 것입니다. 데이터베이스는 시간이 지남에 따라 변경 될 수있는 값을위한 것이지만, 전역 변수 는 절대 변하지 않는 것들 실제 데이터를 포함하지 않을 때만 사용해야 합니다.

  • 데이터베이스 값 (행, 열)에는 데이터베이스에 컨텍스트 및 관계형 매핑이 있습니다. 이 관계는 Jailer와 같은 도구를 사용하여 쉽게 추출하고 분석 할 수 있습니다. 반면에 전역 변수는 약간 다릅니다. 모든 사용법을 찾을 수 있지만 변수가 다른 세계와 상호 작용하는 모든 방법 을 말해 줄 수는 없습니다 .

  • 전역 변수가 더 빠릅니다 . 데이터베이스에서 무언가를 얻으려면 데이터베이스 연결이 필요하고 선택하여 실행 한 다음 데이터베이스 연결을 닫아야합니다. 필요한 모든 유형 변환이 그 위에 있습니다. 코드에서 액세스하는 전역과 비교하십시오.

이것들은 내가 지금 생각할 수있는 유일한 것이지만 더 많은 것이 있다고 확신합니다. 간단히 말해서, 그것들은 서로 다른 두 가지이며 다른 목표에 사용해야합니다 .


0

물론 전 세계가 항상 부적절한 것은 아닙니다. 그것들은 합법적으로 사용되기 때문에 존재합니다. 전역의 주요 문제점과이를 피하기위한 훈계의 주요 원인은 전역을 사용하는 코드가 하나의 전역에만 첨부된다는 것입니다.

예를 들어, 서버 이름을 저장하는 HTTP 서버를 고려하십시오.

서버 이름을 전역에 저장하면 프로세스가 서로 다른 두 서버 이름에 대한 논리를 동시에 실행할 수 없습니다. 원래 디자인은 한 번에 둘 이상의 서버 인스턴스를 실행하는 것을 고려하지 않았지만 나중에이를 결정하기로 결정한 경우 서버 이름이 전역인지 여부는 간단하지 않습니다.

반대로 서버 이름이 데이터베이스에 있으면 아무런 문제가 없습니다. HTTP 서버의 각 인스턴스마다 해당 데이터베이스의 인스턴스를 하나만 만들 수 있습니다. 서버의 각 인스턴스에는 자체 데이터베이스 인스턴스가 있으므로 자체 서버 이름을 가질 수 있습니다.

따라서 전역에 대한 주요 이의 제기는 해당 전역에 액세스하는 모든 코드에 대해 하나의 값만있을 수 있으며 데이터베이스 항목에는 적용되지 않습니다. 동일한 코드는 특정 항목에 대해 다른 값을 가진 별개의 데이터베이스 인스턴스에 쉽게 액세스 할 수 있습니다.


0

나는 이것이 흥미로운 질문이라고 생각하지만 '글로벌 스테이트'라는 용어에 따라 두 가지 주요 이슈가 있기 때문에 대답하기가 약간 어렵습니다. 첫 번째는 '글로벌 커플 링'의 개념입니다. 그 증거는 글로벌 상태에 대한 대안이 의존성 주입이라는 것입니다. 문제는 DI가 반드시 글로벌 상태를 제거 할 필요는 없다는 것입니다. 즉, 전 세계 국가에 의존성을 주입하는 것이 절대적으로 가능하고 일반적입니다. DI는 글로벌 변수와 일반적으로 사용되는 싱글 톤 패턴과 함께 제공되는 커플 링을 제거합니다. 약간 덜 명백한 디자인을 제외하고는 이러한 종류의 커플 링을 제거하는 데 거의 단점이 없으며 커플 링을 제거하면 이점이 전 세계에 대한 종속성 수에 따라 기하 급수적으로 증가합니다.

이것의 다른 측면은 공유 상태입니다. 전 세계적으로 공유 된 주와 일반적으로 공유 된 주가 실제로 명확하게 구분되어 있는지 확실하지 않지만 비용과 혜택은 훨씬 미묘합니다. 공유 상태가 유용해야하는 수많은 소프트웨어 시스템이 있습니다. 예를 들어 비트 코인은 분산 된 방식으로 전 세계적으로 (문학적으로) 상태를 공유하는 매우 영리한 방법입니다. 큰 병목 현상을 일으키지 않고 변경 가능한 상태를 올바르게 공유하는 것은 어렵지만 유용합니다. 따라서 실제로 필요하지 않은 경우 공유 가능한 변경 가능 상태를 최소화하여 응용 프로그램을 단순화 할 수 있습니다.

따라서 데이터베이스와 데이터베이스가 어떻게 다른지에 대한 질문도이 두 가지 측면에서 나뉘어 있습니다. 그들은 커플 링을 소개합니까? 그렇습니다.하지만 응용 프로그램의 설계 방식과 데이터베이스의 설계 방식에 따라 다릅니다. 디자인에 대한 세부 사항없이 데이터베이스가 전역 결합을 도입하는지 여부에 대한 단일 답변을하기에는 너무 많은 요소가 있습니다. 그들이 상태 공유를 도입하는지 여부에 관해서는 이것이 데이터베이스의 주요 요점입니다. 문제는 그들이 잘하는지 여부입니다. 다시 말하지만, 이것은 대안 및 다른 많은 트레이드 오프와 같은 다른 많은 정보가 없으면 대답하기에는 너무 복잡하다고 생각합니다.


0

행동과 같은 "전역 변수"는 데이터베이스 관리자 (DBA)가 지불하는 가격입니다. 업무를 수행하는 데 필요한 악이 있기 때문입니다.

다른 사람들이 지적했듯이 전역 변수의 문제는 임의의 문제가 아닙니다. 문제는 변수를 사용하는 사람과 방법을 결정하기가 더 어려워 지므로 프로그램을 사용하면 프로그램의 동작이 예측하기가 어렵고 짧아진다는 것입니다. 현대 소프트웨어는 일반적으로 많은 유연한 작업을 수행하도록 요청되기 때문에 이것은 현대 소프트웨어의 큰 문제입니다. 실행하는 동안 수십억 또는 수 조 건의 복잡한 상태 조작을 수행 할 수 있습니다. 수십억 또는 수십억 번의 운영에서 소프트웨어가 무엇을 할 것인지에 대한 진정한 진술을 입증 할 수있는 능력은 매우 중요합니다.

최신 소프트웨어의 경우 모든 언어는 캡슐화와 같이이를 지원하는 도구를 제공합니다. 그것을 사용하지 않는 선택은 불필요하며, "글로벌은 악하다"는 사고 방식으로 이어진다. 소프트웨어 개발 분야의 많은 지역에서 소프트웨어를 사용하는 사람은 코딩 방법을 잘 모르는 사람뿐입니다. 이것은 그들이 직접적으로 문제를 일으켰을뿐 아니라 개발자가 무엇을하고 있는지 몰랐다는 것을 간접적으로 암시합니다. 다른 지역에서는 전역이 완전히 정상임을 알 수 있습니다 (특히 내장 소프트웨어는 부분적으로 ISR과 잘 작동하기 때문에 전역을 좋아합니다). 그러나 많은 소프트웨어 개발자들 사이에는 소수의 목소리가 들리므로 "글로벌은 악하다"는 유일한 목소리입니다.

데이터베이스 개발은 소수의 음성 상황 중 하나입니다. DBA 작업을 수행하는 데 필요한 도구는 매우 강력하며 이론은 캡슐화에 뿌리를두고 있지 않습니다 . 데이터베이스에서 모든 단일 성능의 성능을 얻으려면 글로벌과 마찬가지로 모든 것에 대한 완벽한 액세스가 필요합니다. 1 억 개의 행 (또는 그 이상)의 데이터베이스 중 하나를 사용하면 DB 엔진이 펀치를 보유하지 않는 이유를 이해할 수 있습니다.

그들은 그 대가를 치러야합니다. DBA는 도구가 보호하지 않기 때문에 세부 사항에주의를 기울여 거의 병리학 적이어야합니다. 그들이 보호하는 데 가장 좋은 것은 ACID 또는 외래 키입니다. 병리학 적이 아닌 사람들 은 완전히 사용할 수 없거나 심지어 부패한 테이블을 완전히 엉망 으로 만듭니다.

100k 라인 소프트웨어 패키지는 드문 일이 아닙니다. 이론적으로 소프트웨어의 모든 라인은 어느 시점에서나 글로벌에 영향을 줄 수 있습니다. DBA에서는 데이터베이스를 수정할 수있는 100k 개의 다른 쿼리를 찾을 수 없습니다. 자신을 보호하기 위해 필요한 세부 사항에주의를 기울여 유지하는 것은 무리가 있습니다. DBA가 이와 같은 큰 것을 가지고 있다면, "글로벌 같은"문제를 회피하면서 접근자를 사용하여 데이터베이스를 의도적으로 캡슐화 한 다음 "safer"메커니즘을 통해 가능한 많은 작업을 수행합니다. 따라서 푸시가 촉발 될 때 데이터베이스 사용자조차도 글로벌을 피할 수 있습니다. 그들은 단순히 위험이 많이 함께하고 있습니다 대안이 있습니다 강한,하지만 같은 위험하지.

다른 모든 것들이 동일하다면 깨진 유리 위를 걸 으면서, 쓸쓸한 보도를 걸어가겠습니까? 예, 깨진 유리를 걸을 수 있습니다. 예, 어떤 사람들은 생계를 유지하기도합니다. 그러나 여전히 보도를 청소하고 계속 진행하십시오!


0

전제는 거짓이라고 생각합니다. 데이터베이스가 (매우 큰) 컨텍스트 객체가 아닌 "전역 상태"여야하는 이유는 없습니다. 코드가 전역 변수 또는 고정 전역 데이터베이스 연결 매개 변수를 통해 사용하는 특정 데이터베이스에 바인딩하는 경우 다른 전역 상태와 다르지 않으며 나쁘지 않습니다. 반면, 데이터베이스 연결을 위해 컨텍스트 객체를 올바르게 전달하면 전역 상태가 아니라 큰 (및 널리 사용되는) 컨텍스트 상태입니다.

차이점을 쉽게 측정 할 수 있습니다. 코드를 크게 변경하지 않고 단일 프로그램 / 프로세스에서 각각 자체 데이터베이스를 사용하는 프로그램 논리의 두 인스턴스를 실행할 수 있습니까? 그렇다면 데이터베이스가 실제로 "전역 상태"가 아닙니다.


-2

세계는 악이 아니다. 그들은 단순히 도구입니다. 전역 프로그래밍의 잘못된 사용은 다른 프로그래밍 기능의 잘못된 사용과 마찬가지로 문제가됩니다.

저의 일반적인 권장 사항은 글로벌 솔루션은 다른 솔루션이 최적이 아닌 잘 이해하고 고려 된 상황에서만 사용해야한다는 것입니다. 가장 중요한 것은 글로벌 값이 수정 될 수있는 위치를 잘 문서화하고 멀티 스레드를 실행중인 경우 글로벌 및 모든 종속 종속 글로벌이 트랜잭션 방식으로 액세스되는지 확인하는 것입니다.


downvoters 중 일부는 downvotes를 설명할까요? 설명없이 공감하는 것은 무례한 것 같습니다.
바이런 존스

-2

읽기 전용 패턴이며 인쇄 할 때 데이터가 최신 상태가 아니라고 가정합니다. 대기열은 다른 방법으로 충돌을 쓰거나 처리합니다. 지옥 악마에 오신 것을 환영합니다, 당신은 글로벌 DB를 사용하고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.