Làm thế nào là toàn cầu khác với cơ sở dữ liệu?


250

Tôi vừa chạy qua câu hỏi cũ này hỏi có gì xấu về trạng thái toàn cầu và câu trả lời được chấp nhận hàng đầu, được chấp nhận khẳng định rằng bạn không thể tin bất kỳ mã nào hoạt động với các biến toàn cục, bởi vì một số mã khác có thể xuất hiện và sửa đổi mã đó giá trị và sau đó bạn không biết hành vi của mã của bạn sẽ là gì vì dữ liệu là khác nhau! Nhưng khi tôi nhìn vào điều đó, tôi không thể không nghĩ rằng đó là một lời giải thích thực sự yếu kém, bởi vì làm thế nào khác với làm việc với dữ liệu được lưu trữ trong cơ sở dữ liệu?

Khi chương trình của bạn đang làm việc với dữ liệu từ cơ sở dữ liệu, bạn không quan tâm liệu mã khác trong hệ thống của bạn có thay đổi nó hay không, ngay cả khi một chương trình hoàn toàn khác đang thay đổi nó, đối với vấn đề đó. Bạn không quan tâm dữ liệu là gì; đó là toàn bộ vấn đề Tất cả vấn đề là mã của bạn xử lý chính xác dữ liệu mà nó gặp phải. (Rõ ràng là tôi đang đề cập đến vấn đề thường gặp của bộ nhớ đệm ở đây, nhưng chúng ta hãy bỏ qua điều đó vào lúc này.)

Nhưng nếu dữ liệu bạn đang làm việc đến từ nguồn bên ngoài mà mã của bạn không có quyền kiểm soát, chẳng hạn như cơ sở dữ liệu (hoặc đầu vào của người dùng, ổ cắm mạng hoặc tệp, v.v.) và không có gì sai với điều đó, làm thế nào dữ liệu toàn cầu trong chính mã - mà chương trình của bạn có mức độ kiểm soát lớn hơn nhiều - bằng cách nào đó là một điều tồi tệ khi nó rõ ràng là kém hơn nhiều so với những thứ hoàn toàn bình thường mà không ai coi là vấn đề?


117
Thật tuyệt khi thấy các thành viên kỳ cựu thách thức các giáo điều một chút ...
svidgen

10
Trong một ứng dụng, bạn thường cung cấp một phương tiện để truy cập cơ sở dữ liệu, điều này có nghĩa là được chuyển đến các chức năng muốn truy cập cơ sở dữ liệu. Bạn không làm điều đó với các biến toàn cục, bạn chỉ cần biết rằng chúng có trong tay. Đó là một sự khác biệt quan trọng ngay tại đó.
Andy

45
Trạng thái toàn cầu giống như có một cơ sở dữ liệu với một bảng duy nhất với một hàng với vô số cột được truy cập đồng thời bởi một số lượng ứng dụng tùy ý.
BevynQ

42
Cơ sở dữ liệu cũng xấu.
Stig Hemmer

27
Thật thú vị khi "đảo ngược" lập luận bạn đưa ra ở đây và đi theo hướng khác. Một cấu trúc có một con trỏ tới một cấu trúc khác về mặt logic chỉ là một khóa ngoại trong một hàng của một bảng mà khóa với một hàng khác của một bảng khác. Làm thế nào để làm việc với bất kỳnào , bao gồm cả danh sách liên kết đi bộ khác với thao tác dữ liệu trong cơ sở dữ liệu? Trả lời: không phải vậy. Câu hỏi: tại sao sau đó chúng ta thao tác các cấu trúc dữ liệu trong bộ nhớ và cấu trúc dữ liệu trong cơ sở dữ liệu bằng các công cụ khác nhau như vậy? Trả lời: Tôi thực sự không biết! Có vẻ như một tai nạn của lịch sử hơn là thiết kế tốt.
Eric Lippert

Câu trả lời:


118

Đầu tiên, tôi muốn nói rằng câu trả lời mà bạn liên kết để nói quá vấn đề cụ thể đó và rằng cái xấu chính của nhà nước toàn cầu là nó đưa ra sự ghép nối theo những cách không thể đoán trước có thể gây khó khăn trong việc thay đổi hành vi của hệ thống của bạn trong tương lai.

Nhưng đi sâu vào vấn đề này hơn nữa, có sự khác biệt giữa trạng thái toàn cầu trong một ứng dụng hướng đối tượng điển hình và trạng thái được giữ trong cơ sở dữ liệu. Tóm lại, quan trọng nhất trong số này là:

  • Các hệ thống hướng đối tượng cho phép thay thế một đối tượng bằng một lớp đối tượng khác, miễn là nó là một kiểu con của kiểu ban đầu. Điều này cho phép thay đổi hành vi , không chỉ dữ liệu .

  • Trạng thái toàn cầu trong một ứng dụng thường không cung cấp sự đảm bảo tính nhất quán mạnh mẽ mà cơ sở dữ liệu thực hiện - không có giao dịch nào trong đó bạn thấy trạng thái nhất quán cho nó, không có cập nhật nguyên tử, v.v.

Ngoài ra, chúng ta có thể thấy trạng thái cơ sở dữ liệu là một điều ác cần thiết; không thể loại bỏ nó khỏi hệ thống của chúng tôi. Nhà nước toàn cầu, tuy nhiên, là không cần thiết. Chúng tôi hoàn toàn có thể loại bỏ nó. Vì vậy, ngay cả những vấn đề với cơ sở dữ liệu cũng tệ như vậy, chúng ta vẫn có thể loại bỏ một số vấn đề tiềm ẩn và một giải pháp một phần vẫn tốt hơn là không có giải pháp.


44
Tôi nghĩ rằng điểm của tính nhất quán thực sự là lý do chính: Khi các biến toàn cục được sử dụng trong mã, thường không có thông báo khi chúng thực sự được khởi tạo. Sự phụ thuộc giữa các mô-đun được ẩn sâu bên trong chuỗi các cuộc gọi và những thứ đơn giản như hoán đổi hai cuộc gọi có thể tạo ra các lỗi thực sự khó chịu vì đột nhiên một số biến toàn cục không được khởi tạo chính xác nữa khi nó được sử dụng lần đầu tiên. Ít nhất đó là vấn đề tôi gặp phải với mã kế thừa mà tôi cần phải làm việc và điều này khiến cho việc tái cấu trúc trở thành một cơn ác mộng.
cmaster

24
@DavidHammen Tôi thực sự đã làm việc mô phỏng trạng thái thế giới cho một trò chơi trực tuyến, rõ ràng là trong danh mục ứng dụng mà bạn đang nói đến, và thậm chí ở đó tôi sẽ không (và không) sử dụng trạng thái toàn cầu cho nó. Ngay cả khi một số lợi ích hiệu quả có thể được thực hiện bằng cách sử dụng trạng thái toàn cầu, vấn đề là trạng thái toàn cầu không thể mở rộng được . Nó trở nên khó sử dụng một khi bạn chuyển từ kiến ​​trúc đơn luồng sang kiến ​​trúc đa luồng. Nó trở nên không hiệu quả khi bạn chuyển sang kiến ​​trúc NUMA. Nó trở nên không thể khi bạn di chuyển đến một kiến ​​trúc phân tán. Bài báo bạn trích dẫn từ ...
Jules

24
1993. Những vấn đề này ít hơn một vấn đề sau đó. Các tác giả đã làm việc trên một hệ thống xử lý duy nhất, mô phỏng các tương tác của 1.000 đối tượng. Trong một hệ thống hiện đại, bạn có thể chạy mô phỏng loại đó ít nhất là một hệ thống lõi kép, nhưng rất có thể nó có thể có ít nhất 6 lõi trong một hệ thống. Đối với các vấn đề lớn hơn, bạn vẫn chạy nó trên một cụm. Đối với loại thay đổi này, bạn phải tránh trạng thái toàn cầu vì trạng thái toàn cầu không thể được chia sẻ một cách hiệu quả.
Jules

19
Tôi nghĩ rằng việc gọi cơ sở dữ liệu là "điều ác cần thiết" là một chút khó khăn. Ý tôi là, từ khi nào nhà nước trở thành ác quỷ? Nhà nước là toàn bộ mục đích của một cơ sở dữ liệu. Nhà nước là thông tin. Không có nhà nước, tất cả những gì bạn có là các nhà khai thác. Những gì tốt là các nhà khai thác mà không có cái gì để hoạt động? Nhà nước đó phải đi đâu đó. Vào cuối ngày, lập trình chức năng chỉ là phương tiện để kết thúc và không có trạng thái đột biến, sẽ không có việc gì để làm bất cứ điều gì cả. Nó hơi giống một thợ làm bánh gọi bánh là một điều ác cần thiết - nó không phải là xấu xa. Đó là toàn bộ vấn đề.
J ...

5
@DavidHammen "vẫn còn một số đối tượng biết ít nhất một chút về mọi đối tượng trong trò chơi" Không nhất thiết phải đúng. Một kỹ thuật chính trong mô phỏng phân tán hiện đại là tận dụng lợi thế của địa phương và tạo ra các xấp xỉ sao cho các vật thể ở xa không cần biết về mọi thứ ở xa, chỉ những dữ liệu nào được cung cấp cho chúng bởi những chủ sở hữu của những vật thể ở xa đó.
JAB

75

Đầu tiên, các vấn đề với các biến toàn cầu là gì, dựa trên câu trả lời được chấp nhận cho câu hỏi bạn liên kết?

Rất ngắn gọn, nó làm cho nhà nước chương trình không thể đoán trước.

Cơ sở dữ liệu, phần lớn thời gian, tuân thủ ACID. ACID đặc biệt giải quyết các vấn đề tiềm ẩn sẽ khiến việc lưu trữ dữ liệu trở nên khó lường hoặc không đáng tin cậy.

Hơn nữa, nhà nước toàn cầu làm tổn thương khả năng đọc mã của bạn.

Điều này là do các biến toàn cục tồn tại trong một phạm vi cách xa việc sử dụng chúng, thậm chí có thể trong một tệp khác. Khi sử dụng cơ sở dữ liệu, bạn đang sử dụng một bộ bản ghi hoặc đối tượng ORM cục bộ với mã bạn đang đọc (hoặc nên là).

Trình điều khiển cơ sở dữ liệu thường cung cấp một giao diện nhất quán, dễ hiểu để truy cập dữ liệu giống nhau bất kể miền có vấn đề. Khi bạn lấy dữ liệu từ cơ sở dữ liệu, chương trình của bạn có một bản sao của dữ liệu. Cập nhật là nguyên tử. Tương phản với các biến toàn cục, trong đó nhiều luồng hoặc phương thức có thể hoạt động trên cùng một dữ liệu mà không có tính nguyên tử trừ khi bạn tự thêm đồng bộ hóa. Cập nhật dữ liệu là không thể đoán trước và khó theo dõi. Các cập nhật có thể được xen kẽ, gây ra các ví dụ trong sách giáo khoa tiêu chuẩn không có lỗi về dữ liệu đa luồng (ví dụ: gia tăng xen kẽ).

Cơ sở dữ liệu thường mô hình hóa dữ liệu khác với các biến toàn cục để bắt đầu, nhưng tạm thời để cơ sở dữ liệu được thiết kế để trở thành kho lưu trữ dữ liệu tuân thủ ACID giúp giảm thiểu nhiều mối lo ngại với các biến toàn cục.


4
+1 Điều bạn đang nói là cơ sở dữ liệu có các giao dịch, cho phép đọc và viết nhiều phần của trạng thái toàn cầu một cách nguyên tử. Điểm hay, chỉ có thể tránh được bằng cách sử dụng các biến toàn cục cho từng thông tin hoàn toàn độc lập.
l0b0

1
Các giao dịch @ l0b0 là cơ chế đạt được hầu hết các mục tiêu ACID, chính xác. Nhưng chính giao diện DB làm cho mã rõ ràng hơn bằng cách đưa dữ liệu vào phạm vi cục bộ hơn. Hãy nghĩ đến việc sử dụng Bản ghi JDBC với khối tài nguyên thử hoặc hàm ORM để lấy một phần dữ liệu bằng một lệnh gọi hàm duy nhất. So sánh điều này với việc quản lý dữ liệu cách xa mã bạn đang đọc trên toàn cầu ở đâu đó.

1
Vì vậy, sẽ ổn khi sử dụng biến toàn cục nếu tôi sao chép giá trị sang biến cục bộ (có mutex) ở đầu hàm, sửa đổi biến cục bộ và sau đó sao chép giá trị trở lại biến toàn cục ở cuối chức năng? (... anh ấy hỏi một cách khoa trương.)
RM

1
@RM Ông đề cập đến hai điểm. Những gì bạn đã ném ra có thể giải quyết vấn đề thứ nhất (trạng thái chương trình không thể đoán trước), nhưng nó không giải quyết vấn đề thứ hai (khả năng đọc mã của bạn). Trong thực tế, nó có thể làm cho khả năng đọc chương trình của bạn trở nên tồi tệ hơn: P.
riwalk

1
@RM Chức năng của bạn sẽ chạy ổn định, vâng. Nhưng sau đó bạn sẽ có câu hỏi liệu có điều gì khác đã sửa đổi biến toàn cầu trong thời gian đó hay không, và sửa đổi đó quan trọng hơn những gì bạn đang viết cho nó. Cơ sở dữ liệu có thể có cùng một vấn đề, tất nhiên.
Graham

45

Tôi muốn đưa ra một vài quan sát:

Vâng, một cơ sở dữ liệu là trạng thái toàn cầu.

Trên thực tế, đó là một trạng thái siêu toàn cầu, như bạn đã chỉ ra. Nó là phổ quát! Phạm vi của nó đòi hỏi bất cứ điều gì hoặc bất cứ ai kết nối với cơ sở dữ liệu. Và, tôi nghi ngờ rất nhiều người có nhiều năm kinh nghiệm có thể kể cho bạn nghe những câu chuyện kinh dị về việc "những điều kỳ lạ" trong dữ liệu dẫn đến "hành vi bất ngờ" trong một hoặc nhiều ứng dụng có liên quan ...

Một trong những hậu quả tiềm tàng của việc sử dụng biến toàn cục là hai "mô-đun" riêng biệt sẽ sử dụng biến đó cho các mục đích riêng biệt của chúng. Và đến mức đó, một bảng cơ sở dữ liệu không khác. Nó có thể trở thành nạn nhân của cùng một vấn đề.

Hmm ... Đây là điều:

Nếu một mô-đun không hoạt động bên ngoài theo một cách nào đó, nó không làm gì cả.

Một mô-đun hữu ích có thể được cung cấp dữ liệu hoặc nó có thể tìm thấy nó. Và, nó có thể trả về dữ liệu hoặc nó có thể sửa đổi trạng thái. Nhưng, nếu nó không tương tác với thế giới bên ngoài theo một cách nào đó, thì nó cũng có thể không làm gì cả.

Bây giờ, sở thích của chúng tôi là nhận dữ liệu và trả lại dữ liệu. Hầu hết các mô-đun chỉ đơn giản là dễ viết hơn nếu chúng có thể được viết với sự coi thường hoàn toàn cho những gì thế giới bên ngoài đang làm. Nhưng cuối cùng, một cái gì đó cần phải tìm dữ liệu và sửa đổi trạng thái bên ngoài, toàn cầu đó.

Hơn nữa, trong các ứng dụng trong thế giới thực, dữ liệu tồn tại để có thể đọc và cập nhật bằng nhiều hoạt động khác nhau . Một số vấn đề được ngăn chặn bởi các khóa và giao dịch. Nhưng, ngăn chặn các hoạt động này xung đột với nhau về nguyên tắc , vào cuối ngày, chỉ đơn giản liên quan đến suy nghĩ cẩn thận. (Và phạm sai lầm ...)

Nhưng ngoài ra, chúng ta thường không làm việc trực tiếp với nhà nước toàn cầu.

Trừ khi ứng dụng sống trong lớp dữ liệu (bằng SQL hoặc bất cứ thứ gì), các đối tượng mà các mô-đun của chúng tôi làm việc thực sự là một bản sao của trạng thái chung được chia sẻ. Chúng tôi có thể làm bất cứ điều gì chúng tôi muốn mà không có bất kỳ tác động nào đến trạng thái chia sẻ thực tế.

Và, trong trường hợp chúng ta cần phải thay đổi trạng thái toàn cầu đó, với giả định rằng dữ liệu chúng ta đã cung cấp không thay đổi, chúng ta thường có thể thực hiện cùng một kiểu khóa mà chúng ta sẽ làm trên toàn cầu địa phương.

Và cuối cùng, chúng ta thường làm những việc khác nhau với cơ sở dữ liệu hơn chúng ta sức mạnh với globals nghịch ngợm.

Một thế giới nghịch ngợm, bị phá vỡ trông như thế này:

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.
  }
}

Chúng tôi chỉ đơn giản là không sử dụng cơ sở dữ liệu cho các công cụ trong quá trình / hoạt động như thế. Và nó có thể là bản chất chậm của cơ sở dữ liệu và sự tiện lợi tương đối của một biến đơn giản ngăn cản chúng ta: Sự tương tác chậm chạp, lúng túng của chúng ta với cơ sở dữ liệu chỉ khiến chúng trở thành ứng cử viên tồi cho nhiều lỗi mà chúng ta đã mắc phải trong quá khứ .


3
Cách để đảm bảo (vì chúng tôi không thể giả định) "rằng dữ liệu chúng tôi đã cung cấp không thay đổi" trong cơ sở dữ liệu sẽ là một giao dịch.
l0b0

Phải ... điều đó được cho là ngụ ý với "kiểu khóa tương tự".
Svidgen

Nhưng, có thể khó để suy nghĩ cẩn thận vào cuối ngày.

Vâng, cơ sở dữ liệu thực sự là trạng thái toàn cầu - đó là lý do tại sao nó rất hấp dẫn để chia sẻ dữ liệu bằng cách sử dụng một cái gì đó như git hoặc ipfs.
William Payne

21

Tôi không đồng ý với tuyên bố cơ bản rằng:

Khi chương trình của bạn đang làm việc với dữ liệu từ cơ sở dữ liệu, bạn không quan tâm liệu mã khác trong hệ thống của bạn có thay đổi nó hay không, ngay cả khi một chương trình hoàn toàn khác đang thay đổi nó, đối với vấn đề đó.

Suy nghĩ ban đầu của tôi là "Wow. Chỉ cần Wow". Rất nhiều thời gian và nỗ lực được dành để cố gắng tránh chính xác điều này - và tìm ra những gì đánh đổi và thỏa hiệp hoạt động cho mỗi ứng dụng. Chỉ cần bỏ qua nó là một công thức cho thảm họa.

Nhưng tôi cũng diasgree ở cấp độ kiến ​​trúc. Một biến toàn cầu không chỉ là nhà nước toàn cầu. Đó là trạng thái toàn cầu có thể truy cập từ mọi nơi trong suốt. Ngược lại để sử dụng cơ sở dữ liệu, bạn cần phải xử lý nó - (trừ khi bạn lưu trữ hơn xử lý trong biến toàn cục ....)

Ví dụ: sử dụng biến toàn cục có thể trông như thế này

int looks_ok_but_isnt() {
  return global_int++;
}

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

Nhưng làm điều tương tự với cơ sở dữ liệu sẽ phải rõ ràng hơn về những gì nó đang làm

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);
   ...
}

Cơ sở dữ liệu rõ ràng là mucking với cơ sở dữ liệu. Nếu bạn muốn không sử dụng cơ sở dữ liệu, bạn có thể sử dụng trạng thái rõ ràng và nó trông gần giống như trường hợp cơ sở dữ liệu.

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);
   ...
}

Vì vậy, tôi cho rằng việc sử dụng một cơ sở dữ liệu giống như sử dụng trạng thái rõ ràng hơn là sử dụng các biến toàn cục.


2
Vâng, tôi nghĩ thật thú vị khi OP nói: " Bạn không quan tâm dữ liệu là gì; đó là toàn bộ vấn đề " - nếu chúng ta không quan tâm, vậy thì tại sao lại lưu trữ nó? Dưới đây là một ý nghĩ: chúng ta hãy chỉ dừng sử dụng các biến và dữ liệu ở tất cả . Điều đó sẽ làm cho mọi thứ đơn giản hơn nhiều. "Dừng lại thế giới, tôi muốn xuống!"

1
+1 Các chủ đề hoặc ứng dụng khác nhau viết và đọc từ cùng một cơ sở dữ liệu là nguồn tiềm năng của một số lượng lớn các vấn đề nổi tiếng, đó là lý do tại sao luôn phải có một chiến lược để xử lý vấn đề này, ở cấp độ cơ sở dữ liệu hoặc ứng dụng, hoặc cả hai. Vì vậy, chắc chắn KHÔNG đúng khi bạn (nhà phát triển ứng dụng) không quan tâm đến việc ai khác đang đọc hoặc viết từ cơ sở dữ liệu.
Andres F.

1
+1 Trên một lưu ý phụ, câu trả lời này giải thích khá nhiều điều tôi ghét nhất về tiêm phụ thuộc. Nó che giấu các loại phụ thuộc.
jpmc26

@ jpmc26 Tôi có thể đánh dấu các từ, nhưng đây không phải là một ví dụ điển hình về cách tiêm phụ thuộc (trái ngược với tra cứu toàn cầu) giúp làm cho phụ thuộc rõ ràng? Đối với tôi, có vẻ như bạn gặp vấn đề với một số API nhất định, như có lẽ là ma thuật chú thích được sử dụng bởi JAX-RS và Spring.
Emil Lundberg

2
@EmilLundberg Không, vấn đề là khi bạn có một hệ thống phân cấp. Việc tiêm phụ thuộc che giấu sự phụ thuộc của các tầng thấp hơn từ mã ở các tầng cao hơn, gây khó khăn cho việc theo dõi những thứ tương tác. Ví dụ, nếu MakeNewThingphụ thuộc MakeNewThingInDbvà lớp trình điều khiển của tôi sử dụng MakeNewThing, thì mã trong bộ điều khiển của tôi không rõ ràng về việc sửa đổi cơ sở dữ liệu. Vì vậy, sau đó những gì nếu tôi sử dụng một lớp mà thực sự cam kết giao dịch hiện tại của tôi để DB? DI làm cho nó rất khó kiểm soát phạm vi của một đối tượng.
jpmc26

18

Điểm mà lý do duy nhất khiến các biến toàn cầu không thể tin cậy được vì trạng thái có thể được thay đổi ở một nơi khác là, bản thân nó, không đủ lý do để không sử dụng chúng, đồng ý (mặc dù đó là một lý do khá chính đáng!). Có thể câu trả lời chủ yếu là mô tả việc sử dụng trong đó việc hạn chế quyền truy cập của một biến vào chỉ các lĩnh vực mã mà nó liên quan sẽ có ý nghĩa hơn.

Tuy nhiên, cơ sở dữ liệu là một vấn đề khác, bởi vì chúng được thiết kế cho mục đích truy cập "toàn cầu".

Ví dụ:

  • Cơ sở dữ liệu thường được xây dựng xác thực kiểu và cấu trúc đi xa hơn ngôn ngữ truy cập chúng
  • Cơ sở dữ liệu gần như nhất trí cập nhật dựa trên các giao dịch, điều này ngăn chặn các trạng thái không nhất quán, trong đó không có gì đảm bảo trạng thái cuối sẽ trông như thế nào trong một đối tượng toàn cầu (trừ khi nó ẩn sau một đơn)
  • Cấu trúc cơ sở dữ liệu ít nhất là được ghi lại một cách ngầm định dựa trên cấu trúc bảng hoặc đối tượng, hơn cả ứng dụng sử dụng nó

Quan trọng nhất là, cơ sở dữ liệu phục vụ một mục đích khác với một biến toàn cục. Cơ sở dữ liệu là để lưu trữ và tìm kiếm số lượng lớn dữ liệu có tổ chức, trong đó các biến toàn cục phục vụ các hốc cụ thể (khi chính đáng).


1
Huh. Bạn đã đánh bại tôi trong khi tôi đang viết được một nửa câu trả lời gần như giống hệt nhau. :)
Jules

@Jules câu trả lời của bạn cung cấp chi tiết hơn từ phía ứng dụng của sự vật; giữ nó
Jeffrey Sweeney

Nhưng, trừ khi bạn phụ thuộc hoàn toàn vào các thủ tục được lưu trữ để truy cập dữ liệu, tất cả cấu trúc đó vẫn sẽ không thực thi được rằng các bảng được sử dụng như dự định. Hoặc các hoạt động được thực hiện theo thứ tự thích hợp. Hoặc các khóa (giao dịch) được tạo ra khi cần thiết.
Svidgen

Xin chào, các điểm 1 và 3 có còn áp dụng được không nếu bạn đang sử dụng ngôn ngữ gõ tĩnh như Java?
Jesvin Jose

@aitchnyu Không nhất thiết. Vấn đề đang được đưa ra là cơ sở dữ liệu được xây dựng cho mục đích chia sẻ dữ liệu một cách đáng tin cậy, trong đó các biến toàn cục thường không có. Một đối tượng thực hiện giao diện tự viết tài liệu bằng một ngôn ngữ nghiêm ngặt phục vụ một mục đích khác với cả cơ sở dữ liệu NoQuery được gõ lỏng lẻo.
Jeffrey Sweeney

10

Nhưng khi tôi nhìn vào điều đó, tôi không thể không nghĩ rằng đó là một lời giải thích thực sự yếu kém, bởi vì làm thế nào khác với làm việc với dữ liệu được lưu trữ trong cơ sở dữ liệu?

Hoặc khác với làm việc với thiết bị tương tác, với tệp, với bộ nhớ dùng chung, v.v ... Một chương trình thực hiện chính xác điều tương tự mỗi khi chạy là một chương trình rất nhàm chán và khá vô dụng. Vì vậy, có, đó là một lập luận yếu.

Đối với tôi, sự khác biệt tạo ra sự khác biệt liên quan đến các biến toàn cầu là chúng tạo thành các đường truyền thông ẩn và không được bảo vệ. Đọc từ bàn phím là rất rõ ràng và được bảo vệ. Tôi phải thực hiện một cuộc gọi chức năng nhất định và tôi không thể truy cập trình điều khiển bàn phím. Điều tương tự cũng áp dụng cho truy cập tệp, bộ nhớ dùng chung và ví dụ của bạn, cơ sở dữ liệu. Rõ ràng với người đọc mã mà chức năng này đọc từ bàn phím, chức năng đó truy cập một tệp, một số chức năng khác truy cập vào bộ nhớ dùng chung (và có những biện pháp bảo vệ tốt hơn xung quanh đó), và một số chức năng khác truy cập cơ sở dữ liệu.

Với các biến toàn cầu, mặt khác, nó không rõ ràng chút nào. API nói để gọi foo(this_argument, that_argument). Không có gì trong chuỗi cuộc gọi cho biết biến toàn cục g_DangerWillRobinsonnên được đặt thành một số giá trị nhưng trước khi gọi foo(hoặc được kiểm tra sau khi gọi foo).


Google đã cấm sử dụng các đối số tham chiếu không phải là const trong C ++ vì điều này không rõ ràng đối với người đọc mã foo(x)sẽ thay đổi xvì điều đó foolấy tham chiếu không liên tục làm đối số. (So ​​sánh với C #, quy định rằng cả định nghĩa hàm và trang gọi đều phải đủ điều kiện tham số với reftừ khóa.) Trong khi tôi không đồng ý với tiêu chuẩn của Google về điều này, tôi hiểu điểm của họ.

Mã được viết một lần và sửa đổi một vài lần, nhưng nếu nó tốt, nó được đọc nhiều, nhiều lần. Đường ẩn của truyền thông là nghiệp rất xấu. Tham chiếu không liên tục của C ++ đại diện cho một dòng giao tiếp ẩn nhỏ. Một API tốt hoặc một IDE tốt sẽ cho tôi thấy rằng "Ồ! Đây là cuộc gọi bằng cách tham khảo." Biến toàn cầu là một dòng ẩn lớn của truyền thông.


Câu trả lời của bạn có ý nghĩa hơn.
Billal Begueradj

8

Tôi nghĩ rằng lời giải thích được trích dẫn quá mức cho vấn đề đến mức lý luận trở nên lố bịch. Tất nhiên, trạng thái của một cơ sở dữ liệu bên ngoài đóng góp cho trạng thái toàn cầu. Câu hỏi quan trọng là làm thế nàochương trình của bạn phụ thuộc vào trạng thái toàn cầu (có thể thay đổi). Nếu một chức năng thư viện để phân chia chuỗi trên không gian trắng sẽ phụ thuộc vào kết quả trung gian được lưu trữ trong cơ sở dữ liệu, tôi sẽ phản đối thiết kế này ít nhất là tôi sẽ phản đối một mảng ký tự toàn cầu được sử dụng cho cùng mục đích. Mặt khác, nếu bạn quyết định rằng ứng dụng của bạn không cần DBMS toàn diện để lưu trữ dữ liệu kinh doanh tại thời điểm này và cấu trúc giá trị khóa trong bộ nhớ toàn cầu sẽ hoạt động, đây không nhất thiết là dấu hiệu của thiết kế kém. Điều quan trọng là - cho dù bạn chọn giải pháp nào để lưu trữ dữ liệu của mình - lựa chọn này được tách biệt với một phần rất nhỏ của hệ thống để hầu hết các thành phần có thể không tin vào giải pháp được chọn để triển khai và thử nghiệm theo đơn vị và được triển khai giải pháp có thể được thay đổi sau đó với ít nỗ lực.


8

Là một kỹ sư phần mềm làm việc chủ yếu với phần mềm nhúng, tôi hầu như luôn sử dụng các biến toàn cục cho mọi thứ xảy ra giữa các mô-đun. Trong thực tế, đó là cách thực hành tốt nhất để nhúng. Chúng được gán tĩnh, do đó không có nguy cơ thổi heap / stack và không có thêm thời gian để phân bổ / dọn dẹp ngăn xếp khi vào / ra chức năng.

Nhược điểm của việc này là chúng ta phải xem xét các biến được sử dụng như thế nào, và rất nhiều mà đi xuống đến cùng một loại suy nghĩ mà đi vào cơ sở dữ liệu-tranh cãi. Bất kỳ đọc / ghi không đồng bộ của các biến PHẢI là nguyên tử. Nếu nhiều nơi có thể viết một biến, một số ý kiến ​​phải đảm bảo rằng họ luôn ghi dữ liệu hợp lệ, do đó việc ghi trước đó không được thay thế một cách tùy tiện (hoặc thay thế tùy ý là điều an toàn để làm). Nếu cùng một biến được đọc nhiều lần, một số suy nghĩ phải xem xét điều gì xảy ra nếu biến đó thay đổi giá trị giữa các lần đọc hoặc một bản sao của biến phải được thực hiện khi bắt đầu để xử lý được thực hiện bằng cách sử dụng giá trị nhất quán, ngay cả khi giá trị đó trở nên cũ kỹ trong quá trình xử lý.

(Lần cuối cùng, vào ngày đầu tiên tôi ký hợp đồng làm việc với hệ thống đối phó máy bay, vì vậy, liên quan đến an toàn rất cao, nhóm phần mềm đã xem xét một báo cáo lỗi mà họ đã cố gắng tìm ra trong một tuần. Tôi đã có đủ thời gian để tải xuống các công cụ dev và một bản sao của mã. Tôi đã hỏi "không thể biến số đó được cập nhật giữa các lần đọc và gây ra nó?" Nhưng thực sự không có câu trả lời. Vì vậy, trong khi họ vẫn đang thảo luận về nó, tôi đã thêm mã bảo vệ để đọc biến nguyên tử, thực hiện một bản dựng cục bộ và nói cơ bản là "này các bạn, hãy thử cái này". . :)

Vì vậy, các biến toàn cầu không phải là một điều xấu rõ ràng, nhưng chúng khiến bạn mở ra một loạt các vấn đề nếu bạn không suy nghĩ kỹ về chúng.


7

Tùy thuộc vào khía cạnh nào bạn đánh giá, các biến toàn cục và quyền truy cập cơ sở dữ liệu có thể tách biệt thế giới, nhưng miễn là chúng ta đánh giá chúng là phụ thuộc, chúng giống nhau.

Chúng ta hãy xem xét định nghĩa của lập trình hàm về một hàm thuần túy nói rằng nó phải phụ thuộc hoàn toàn vào các tham số mà nó lấy làm đầu vào, tạo ra đầu ra xác định. Nghĩa là, với cùng một tập hợp các đối số hai lần, nó phải tạo ra cùng một kết quả.

Khi một hàm phụ thuộc vào một biến toàn cục, nó không còn có thể được coi là thuần túy, vì, đối với cùng một tập hợp hoặc đối số, nó có thể mang lại các đầu ra khác nhau vì giá trị của biến toàn cục có thể đã thay đổi giữa các lệnh gọi.

Tuy nhiên, hàm vẫn có thể được coi là xác định nếu chúng ta coi biến toàn cục là một phần của giao diện của hàm như các đối số khác của nó, vì vậy nó không phải là vấn đề. Vấn đề chỉ là điều này bị ẩn cho đến khi chúng ta ngạc nhiên bởi hành vi bất ngờ từ các chức năng dường như rõ ràng, sau đó đi đọc các triển khai của chúng để khám phá các phụ thuộc ẩn .

Phần này, thời điểm mà một biến toàn cầu trở thành một phụ thuộc ẩn là những gì được các lập trình viên của chúng ta coi là xấu xa. Nó làm cho mã khó lý luận hơn, khó dự đoán nó sẽ hoạt động như thế nào, khó sử dụng lại, khó kiểm tra và đặc biệt, nó làm tăng gỡ lỗi và khắc phục thời gian khi xảy ra sự cố.

Điều tương tự xảy ra khi chúng ta ẩn sự phụ thuộc vào cơ sở dữ liệu. Chúng ta có thể có các hàm hoặc đối tượng thực hiện các cuộc gọi trực tiếp đến các truy vấn và lệnh của cơ sở dữ liệu, ẩn các phụ thuộc này và gây cho chúng ta chính xác những rắc rối mà các biến toàn cục gây ra; hoặc chúng ta có thể làm cho chúng rõ ràng, mà, hóa ra, được coi là một cách thực hành tốt nhất có nhiều tên, chẳng hạn như mẫu kho lưu trữ, lưu trữ dữ liệu, cổng, v.v.

Tái bút: Có những khía cạnh khác quan trọng đối với sự so sánh này, chẳng hạn như liệu có tham gia đồng thời hay không, nhưng điểm đó được bao phủ bởi các câu trả lời khác ở đây.


Tôi thích rằng bạn đã lấy điều này từ góc độ phụ thuộc.
cbojar

6

Được rồi, hãy bắt đầu từ điểm lịch sử.

Chúng tôi đang ở trong một ứng dụng cũ, được viết bằng cách kết hợp lắp ráp điển hình của bạn và C. Không có chức năng, chỉ có các thủ tục . Khi bạn muốn truyền một đối số hoặc trả về giá trị từ một thủ tục, bạn sử dụng biến toàn cục. Không cần phải nói, điều này khá khó để theo dõi, và nói chung, mọi thủ tục có thể làm bất cứ điều gì nó muốn với mọi biến toàn cầu. Không có gì đáng ngạc nhiên, mọi người đã chuyển sang truyền các đối số và trả về các giá trị theo một cách khác ngay khi nó khả thi (trừ khi đó là hiệu suất quan trọng không làm như vậy - ví dụ: nhìn vào mã nguồn Build Engine (Duke 3D)). Sự ghét các biến toàn cầu được sinh ra ở đây - bạn có rất ít ý tưởng về phần nào trạng thái toàn cầu mà mỗi thủ tục sẽ đọc và thay đổi, và bạn không thể thực sự gọi thủ tục lồng một cách an toàn.

Điều này có nghĩa là ghét biến toàn cầu là một điều của quá khứ? Không hẳn.

Đầu tiên, tôi phải đề cập rằng tôi đã thấy cách tiếp cận chính xác tương tự để chuyển các đối số trong dự án tôi đang thực hiện ngay bây giờ. Để vượt qua hai trường hợp loại tham chiếu trong C #, trong một dự án khoảng 10 năm. Thực sự không có lý do chính đáng nào để làm điều đó như thế này, và rất có thể được sinh ra từ việc nuôi cấy hàng hóa, hoặc một sự hiểu lầm hoàn toàn về cách thức hoạt động của C #.

Điểm quan trọng hơn là bằng cách thêm các biến toàn cục, bạn đang mở rộng phạm vi của từng đoạn mã có quyền truy cập vào biến toàn cục đó. Ghi nhớ tất cả những đề xuất như "giữ cho phương pháp của bạn ngắn"? Nếu bạn có 600 biến toàn cục (một lần nữa, ví dụ trong thế giới thực: /), tất cả các phạm vi phương thức của bạn sẽ được mở rộng hoàn toàn bởi 600 biến toàn cục đó và không có cách nào đơn giản để theo dõi xem ai có quyền truy cập vào cái gì.

Nếu làm sai (cách thông thường :)), các biến toàn cục có thể có khớp nối với nhau. Nhưng bạn không biết làm thế nào chúng được ghép nối và không có cơ chế để đảm bảo rằng trạng thái toàn cầu luôn nhất quán. Ngay cả khi bạn giới thiệu các phần quan trọng để thử và giữ mọi thứ nhất quán, bạn sẽ thấy rằng nó so sánh kém với cơ sở dữ liệu ACID thích hợp:

  • Không có cách nào để khôi phục một bản cập nhật một phần, trừ khi bạn giữ nguyên các giá trị cũ trước khi "giao dịch". Không cần phải nói, đến thời điểm này, việc chuyển một giá trị làm đối số đã là một chiến thắng :)
  • Mọi người truy cập vào cùng một trạng thái phải tuân thủ cùng một quy trình đồng bộ hóa. Nhưng không có cách nào để thực thi điều này - nếu bạn quên thiết lập phần quan trọng, bạn sẽ bị lừa.
  • Ngay cả khi bạn đồng bộ hóa chính xác tất cả quyền truy cập, có thể có các cuộc gọi lồng nhau truy cập trạng thái được sửa đổi một phần. Điều này có nghĩa là bạn hoặc bế tắc (nếu các phần quan trọng của bạn không được đăng ký lại) hoặc xử lý dữ liệu không nhất quán (nếu chúng được xác nhận lại).

Có thể giải quyết những vấn đề này? Không hẳn vậy. Bạn cần đóng gói để xử lý việc này, hoặc kỷ luật thực sự nghiêm ngặt. Thật khó để làm mọi thứ đúng, và đó thường không phải là một công thức tốt để thành công trong phát triển phần mềm :)

Phạm vi nhỏ hơn có xu hướng làm cho mã dễ dàng hơn để lý do về. Các biến toàn cục làm cho ngay cả các đoạn mã đơn giản nhất bao gồm các dải phạm vi khổng lồ.

Tất nhiên, điều này không có nghĩa là phạm vi toàn cầu là xấu xa. Nó không phải là giải pháp đầu tiên bạn tìm kiếm - đó là một ví dụ điển hình của "đơn giản để thực hiện, khó bảo trì".


Âm thanh rất giống với thế giới vật lý: rất khó để đẩy mọi thứ trở lại.

Đây là một câu trả lời tốt, nhưng nó có thể đứng một tuyên bố luận án (phần TL; DR) ngay từ đầu.
jpmc26

6

Một biến toàn cầu là một công cụ, nó có thể được sử dụng cho mục đích tốt và xấu.

Cơ sở dữ liệu là một công cụ, nó có thể được sử dụng cho mục đích tốt và xấu.

Như poster gốc ghi chú, sự khác biệt không quá lớn.

Sinh viên thiếu kinh nghiệm thường nghĩ rằng lỗi là một cái gì đó xảy ra với người khác. Giáo viên sử dụng "Biến toàn cầu là xấu" như một lý do đơn giản hóa để xử phạt thiết kế xấu. Các sinh viên thường không hiểu rằng chỉ vì chương trình 100 dòng của họ không có lỗi không có nghĩa là các phương pháp tương tự có thể được sử dụng cho các chương trình 10000 dòng.

Khi bạn làm việc với cơ sở dữ liệu, bạn không thể chỉ cấm trạng thái toàn cầu vì đó là tất cả những gì chương trình hướng tới. Thay vào đó, bạn nhận được nhiều hướng dẫn chi tiết hơn như ACID và Biểu mẫu thông thường, v.v.

Nếu mọi người sử dụng phương pháp ACID cho các biến toàn cầu, họ sẽ không tệ đến vậy.

Mặt khác, nếu bạn thiết kế cơ sở dữ liệu tồi, chúng có thể là những cơn ác mộng.


3
Yêu cầu sinh viên điển hình về stackoverflow: Giúp tôi với! Mã của tôi là hoàn hảo, nhưng nó không hoạt động đúng!
David Hammen

"Cách tiếp cận ACID với các biến toàn cầu" - xem phần giới thiệu trong Clojure.
Charles Duffy

@DavidHammen và bạn nghĩ các chuyên gia có bộ não không giống sinh viên?
Billal Begueradj

@BillalBEGUERADJ - Đó là sự khác biệt giữa các chuyên gia và sinh viên. Chúng tôi biết rằng mặc dù có nhiều năm kinh nghiệm và bất chấp những nỗ lực tốt nhất về đánh giá mã, thử nghiệm, v.v., mã của chúng tôi không hoàn hảo.
David Hammen


5

Đối với tôi, cái ác chính là Globals không có sự bảo vệ chống lại các vấn đề tương tranh. Bạn có thể thêm các cơ chế để xử lý các vấn đề như vậy với Globals, nhưng bạn sẽ thấy rằng càng giải quyết được nhiều vấn đề đồng thời, Globals của bạn càng bắt đầu bắt chước một cơ sở dữ liệu. Cái ác thứ cấp là không có hợp đồng về việc sử dụng.


3
Ví dụ: errnotrong C.
David Hammen

1
Điều này giải thích chính xác tại sao toàn cầu và cơ sở dữ liệu không giống nhau. Có thể có sự khác biệt khác nhưng bài đăng cụ thể của bạn phá hủy hoàn toàn khái niệm. Nếu bạn đã đưa ra một ví dụ mã nhanh thì tôi chắc chắn bạn sẽ nhận được rất nhiều sự ủng hộ. ví dụ: MyFunc () {x = globalVar * 5; // .... Một số xử lý khác; y = globalVar * 34; // Ooops, một số luồng khác có thể đã thay đổi globalVar trong một số xử lý khác và x và y đang sử dụng các giá trị khác nhau cho globalVar trong tính toán của họ, điều này gần như chắc chắn sẽ không mang lại kết quả mong muốn.
Dunk

5

Một số câu trả lời khác cố gắng giải thích tại sao sử dụng cơ sở dữ liệu là tốt. Họ sai! Một cơ sở dữ liệu là trạng thái toàn cầu và như vậy là xấu xa như một singleton hoặc một biến toàn cầu. Việc sử dụng cơ sở dữ liệu là sai khi bạn có thể dễ dàng sử dụng Bản đồ cục bộ hoặc Mảng thay thế!

Biến toàn cầu cho phép truy cập toàn cầu, có nguy cơ lạm dụng. Biến toàn cầu cũng có những mặt tăng. Các biến toàn cầu thường được cho là thứ bạn nên tránh, không phải là thứ bạn không bao giờ nên sử dụng. Nếu bạn có thể dễ dàng tránh chúng, bạn nên tránh chúng. Nhưng nếu lợi ích vượt trội hơn những nhược điểm, tất nhiên bạn nên sử dụng chúng! *

Điều tương tự chính xác ** áp dụng cho cơ sở dữ liệu, là trạng thái toàn cầu - giống như các biến toàn cục. Nếu bạn có thể thực hiện mà không cần truy cập cơ sở dữ liệu và logic kết quả sẽ làm tất cả những gì bạn cần và cũng phức tạp không kém, sử dụng cơ sở dữ liệu sẽ tăng rủi ro cho dự án của bạn, mà không có bất kỳ lợi ích tương ứng nào.

Trong cuộc sống thực, nhiều ứng dụng yêu cầu trạng thái toàn cầu theo thiết kế, đôi khi thậm chí là trạng thái toàn cầu liên tục - đó là lý do tại sao chúng ta có tệp, cơ sở dữ liệu, v.v.


* Ngoại lệ ở đây là sinh viên. Thật có ý nghĩa khi cấm sinh viên sử dụng các biến toàn cầu để họ phải tìm hiểu các lựa chọn thay thế là gì.

** Một số câu trả lời không chính xác cho rằng cơ sở dữ liệu được bảo vệ tốt hơn bằng cách nào đó so với các dạng khác của trạng thái toàn cầu (câu hỏi rõ ràng là về trạng thái toàn cầu , không chỉ các biến toàn cục). Đó là những cú đánh. Sự bảo vệ chính được cung cấp trong kịch bản cơ sở dữ liệu là theo quy ước, điều này hoàn toàn giống nhau đối với bất kỳ trạng thái toàn cầu nào khác. Hầu hết các ngôn ngữ cũng cho phép rất nhiều sự bảo vệ bổ sung cho trạng thái toàn cầu, dưới dạng const, các lớp chỉ đơn giản là không cho phép thay đổi trạng thái của chúng sau khi nó được đặt trong hàm tạo, hoặc getters và setters có thể tính đến thông tin luồng hoặc trạng thái chương trình.


2

Theo một nghĩa nào đó, sự khác biệt giữa các biến toàn cục và cơ sở dữ liệu tương tự như sự phân biệt giữa các thành viên riêng và công khai của một đối tượng (giả sử bất kỳ ai vẫn sử dụng các trường công khai). Nếu bạn nghĩ toàn bộ chương trình là một đối tượng, thì toàn cầu là các biến riêng tư và cơ sở dữ liệu là các trường công khai.

Họ phân biệt chính ở đây là một trong những trách nhiệm giả định.

Khi bạn viết một đối tượng, giả định rằng bất kỳ ai duy trì các phương thức thành viên sẽ đảm bảo các trường riêng vẫn hoạt động tốt. Nhưng bạn đã từ bỏ bất kỳ giả định nào về tình trạng của các lĩnh vực công cộng và đối xử với chúng một cách cẩn thận hơn.

Giả định tương tự áp dụng ở cấp độ rộng hơn cho cơ sở dữ liệu v / s toàn cầu. Ngoài ra, ngôn ngữ lập trình / hệ sinh thái đảm bảo các hạn chế truy cập đối với công chúng v / s riêng giống như khi nó thực thi chúng trên cơ sở dữ liệu v / s toàn cầu.

Khi đa luồng xuất hiện, khái niệm cơ sở dữ liệu v / s toàn cầu v / s công cộng v / s chỉ là sự phân biệt dọc theo một phổ.

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

Một cơ sở dữ liệu có thể là một trạng thái toàn cầu, nhưng nó không phải lúc nào cũng như vậy. Tôi không đồng ý với giả định rằng bạn không có quyền kiểm soát. Một cách để quản lý đó là khóa và bảo mật. Điều này có thể được thực hiện tại bản ghi, bảng hoặc toàn bộ cơ sở dữ liệu. Một cách tiếp cận khác là có một số loại trường phiên bản sẽ ngăn việc thay đổi bản ghi nếu dữ liệu cũ.

Giống như một biến toàn cục, (các) giá trị trong cơ sở dữ liệu có thể được thay đổi khi chúng được mở khóa, nhưng có nhiều cách để kiểm soát quyền truy cập (Đừng cung cấp tất cả các nhà phát triển mật khẩu cho tài khoản được phép thay đổi dữ liệu.). Nếu bạn có một biến có quyền truy cập hạn chế, thì đó không phải là toàn cầu.


0

Có một số khác biệt:

  • Một giá trị cơ sở dữ liệu có thể được sửa đổi trên bay. Mặt khác, giá trị của toàn cầu được đặt trong mã, không thể thay đổi trừ khi bạn triển khai lại ứng dụng của mình và sửa đổi mã của mình. Trong thực tế, đây là cố ý. Cơ sở dữ liệu dành cho các giá trị có thể thay đổi theo thời gian, nhưng các biến toàn cục chỉ nên dành cho những thứ sẽ không bao giờ thay đổi khi chúng không chứa dữ liệu thực tế.

  • Một giá trị cơ sở dữ liệu (hàng, cột) có bối cảnh và ánh xạ quan hệ trong cơ sở dữ liệu. Mối quan hệ này có thể được trích xuất và phân tích dễ dàng bằng các công cụ như Jailer (ví dụ). Mặt khác, một biến toàn cục là hơi khác nhau. Bạn có thể tìm thấy tất cả các cách sử dụng, nhưng bạn sẽ không thể nói cho tôi tất cả các cách thức mà biến tương tác với phần còn lại của thế giới của bạn.

  • Biến toàn cầu nhanh hơn . Nhận được một cái gì đó từ cơ sở dữ liệu đòi hỏi phải thực hiện kết nối cơ sở dữ liệu, chọn tôi chạy và sau đó kết nối cơ sở dữ liệu phải được đóng lại. Bất kỳ chuyển đổi loại nào bạn có thể cần đến trên đó. So sánh điều đó với toàn cầu đang được truy cập trong mã của bạn.

Đây là những điều duy nhất tôi có thể nghĩ ra ngay bây giờ, nhưng tôi chắc chắn có nhiều hơn nữa. Nói một cách đơn giản, chúng là hai thứ khác nhau và nên được sử dụng cho các mục tiêu khác nhau .


0

Tất nhiên toàn cầu không phải lúc nào cũng không phù hợp. Chúng tồn tại bởi vì chúng có một cách sử dụng hợp pháp. Vấn đề chính với toàn cầu và nguồn chính của lời khuyên để tránh chúng, đó là mã sử dụng toàn cầu được gắn với một và chỉ một toàn cầu.

Ví dụ, hãy xem xét một máy chủ HTTP lưu trữ tên máy chủ.

Nếu bạn lưu trữ tên máy chủ trong toàn cầu, thì quá trình không thể chạy đồng thời logic cho hai tên máy chủ khác nhau. Có lẽ thiết kế ban đầu không bao giờ dự tính chạy nhiều hơn một phiên bản máy chủ cùng một lúc, nhưng nếu sau này bạn quyết định muốn làm điều đó, bạn chỉ đơn giản là không thể nếu tên máy chủ nằm trong toàn cầu.

Ngược lại, nếu tên máy chủ nằm trong cơ sở dữ liệu, không có vấn đề gì. Bạn chỉ có thể tạo một phiên bản của cơ sở dữ liệu đó cho mỗi phiên bản của máy chủ HTTP. Bởi vì mỗi phiên bản của máy chủ có phiên bản cơ sở dữ liệu riêng, nên nó có thể có tên máy chủ riêng.

Vì vậy, sự phản đối chính đối với toàn cầu, chỉ có thể có một giá trị cho tất cả các mã truy cập toàn cầu đó, không áp dụng cho các mục cơ sở dữ liệu. Cùng một mã có thể dễ dàng truy cập các trường hợp cơ sở dữ liệu riêng biệt có các giá trị khác nhau cho một mục cụ thể.


0

Tôi nghĩ rằng đây là một câu hỏi thú vị nhưng hơi khó trả lời vì có hai vấn đề chính đang được giải thích theo thuật ngữ 'nhà nước toàn cầu'. Đầu tiên là khái niệm 'khớp nối toàn cầu'. Bằng chứng về điều đó là sự thay thế được đưa ra cho nhà nước toàn cầu là tiêm phụ thuộc. Vấn đề là DI không nhất thiết phải loại bỏ trạng thái toàn cầu. Đó là, nó hoàn toàn có thể và phổ biến để tiêm phụ thuộc vào trạng thái toàn cầu. Những gì DI làm là loại bỏ khớp nối đi kèm với các biến toàn cục và mẫu Singleton thường được sử dụng. Ngoài một thiết kế ít rõ ràng hơn, có rất ít nhược điểm để loại bỏ loại khớp nối này và lợi ích của việc loại bỏ khớp nối tăng theo cấp số nhân với số lượng phụ thuộc vào các toàn cầu đó.

Các khía cạnh khác của điều này là trạng thái chia sẻ. Tôi không chắc có sự phân biệt thực sự rõ ràng giữa trạng thái chia sẻ toàn cầu và trạng thái chia sẻ nói chung hay không nhưng chi phí và lợi ích mang nhiều sắc thái hơn. Đơn giản chỉ cần đặt có vô số hệ thống phần mềm yêu cầu trạng thái chia sẻ là hữu ích. Ví dụ, Bitcoin là một cách rất thông minh để chia sẻ trạng thái trên toàn cầu (theo nghĩa đen) theo cách phi tập trung. Chia sẻ trạng thái có thể thay đổi đúng cách mà không tạo ra các nút cổ chai lớn là khó khăn nhưng hữu ích. Vì vậy, nếu bạn không thực sự cần làm điều đó, bạn có thể đơn giản hóa ứng dụng của mình bằng cách giảm thiểu trạng thái có thể thay đổi được chia sẻ.

Vì vậy, câu hỏi về cách thức cơ sở dữ liệu khác với toàn cầu cũng được phân chia theo hai khía cạnh này. Họ có giới thiệu khớp nối không? Vâng, họ có thể nhưng nó phụ thuộc rất nhiều vào cách ứng dụng được thiết kế và cách thiết kế cơ sở dữ liệu. Có quá nhiều yếu tố để có một câu trả lời duy nhất cho việc cơ sở dữ liệu giới thiệu khớp nối toàn cầu mà không có chi tiết về thiết kế. Về việc họ có giới thiệu chia sẻ trạng thái hay không, đó là loại điểm chính của cơ sở dữ liệu. Câu hỏi là liệu họ làm điều đó tốt. Một lần nữa, tôi nghĩ rằng điều này quá phức tạp để trả lời mà không có nhiều thông tin khác như các lựa chọn thay thế và nhiều sự đánh đổi khác.


0

Tôi sẽ nghĩ về nó một chút khác biệt: "biến toàn cầu" như hành vi là một cái giá phải trả cho các quản trị viên cơ sở dữ liệu (DBA) vì đó là một điều ác cần thiết để thực hiện công việc của họ.

Vấn đề với các biến toàn cục, như một số người khác đã chỉ ra, không phải là một vấn đề tùy tiện. Vấn đề là việc sử dụng chúng làm cho hành vi của chương trình của bạn ngày càng ít dự đoán hơn vì việc xác định ai đang sử dụng biến và theo cách nào sẽ trở nên khó khăn hơn. Đây là một vấn đề lớn đối với phần mềm hiện đại, bởi vì phần mềm hiện đại thường được yêu cầu thực hiện nhiều điều linh hoạt. Nó có thể thực hiện hàng tỷ hoặc thậm chí hàng nghìn tỷ thao tác trạng thái phức tạp trong quá trình chạy. Khả năng chứng minh những tuyên bố chân thực về những gì phần mềm sẽ làm trong hàng tỷ hoặc hàng nghìn tỷ hoạt động đó là vô cùng quý giá.

Trong trường hợp phần mềm hiện đại, tất cả các ngôn ngữ của chúng tôi cung cấp các công cụ để hỗ trợ việc này, chẳng hạn như đóng gói. Sự lựa chọn không sử dụng nó là không cần thiết, điều này dẫn đến tâm lý "toàn cầu là xấu xa". Trong nhiều khu vực của lĩnh vực phát triển phần mềm, những người duy nhất sử dụng chúng là những người không biết cách viết mã tốt hơn. Điều này có nghĩa là họ không chỉ gặp rắc rối trực tiếp mà còn gián tiếp đề nghị nhà phát triển không biết họ đang làm gì. Ở các khu vực khác, bạn sẽ thấy toàn cầu là hoàn toàn bình thường (đặc biệt là phần mềm nhúng, yêu thích toàn cầu, một phần vì chúng hoạt động tốt với ISR). Tuy nhiên, giữa nhiều nhà phát triển phần mềm ngoài kia, họ là tiếng nói thiểu số, vì vậy giọng nói duy nhất bạn nghe được là "toàn cầu là xấu xa".

Phát triển cơ sở dữ liệu là một trong những tình huống tiếng nói thiểu số. Các công cụ cần thiết để thực hiện công việc DBA rất mạnh mẽ và lý thuyết của chúng không bắt nguồn từ việc đóng gói. Để loại bỏ mọi hiệu suất trong cơ sở dữ liệu của họ, họ cần truy cập đầy đủ vào mọi thứ, tương tự như toàn cầu. Sử dụng một trong những cơ sở dữ liệu 100 triệu hàng (hoặc hơn!) Quái vật của họ và bạn sẽ đánh giá cao lý do tại sao họ không để động cơ DB của họ giữ bất kỳ cú đấm nào.

Họ trả giá cho điều đó, một mức giá thân yêu. Các DBA bị buộc phải gần như bệnh hoạn với sự chú ý của họ đến từng chi tiết, bởi vì các công cụ của họ không bảo vệ họ. Điều tốt nhất họ có trong cách bảo vệ là ACID hoặc có lẽ là khóa ngoại. Những người không bệnh hoạn thấy mình với một mớ hỗn độn các bảng hoàn toàn không sử dụng được, hoặc thậm chí bị hỏng.

Không có gì lạ khi có các gói phần mềm 100k dòng. Về lý thuyết, bất kỳ dòng nào trong phần mềm có thể ảnh hưởng đến bất kỳ toàn cầu tại bất kỳ thời điểm nào. Trong các DBA, bạn không bao giờ tìm thấy 100 nghìn truy vấn khác nhau có thể sửa đổi cơ sở dữ liệu. Điều đó sẽ không hợp lý để duy trì với sự chú ý đến chi tiết cần thiết để bảo vệ bạn khỏi chính bạn. Nếu một DBA có bất cứ thứ gì lớn như vậy, họ sẽ cố tình đóng gói cơ sở dữ liệu của họ bằng cách sử dụng các bộ truy cập, bỏ qua các vấn đề "giống như toàn cầu", và sau đó làm hết sức có thể thông qua cơ chế "an toàn hơn" đó. Do đó, khi đẩy đến xô đẩy, ngay cả cơ sở dữ liệu mọi người cũng tránh được toàn cầu. Họ chỉ đơn giản là đi kèm với rất nhiều nguy hiểm, và có những lựa chọn thay thế cũng mạnh mẽ, nhưng không nguy hiểm.

Bạn có muốn đi bộ xung quanh trên kính vỡ, hoặc trên vỉa hè quét độc đáo, nếu tất cả những thứ khác bằng nhau? Vâng, bạn có thể đi bộ trên kính vỡ. Vâng, một số người thậm chí còn kiếm sống bằng cách đó. Nhưng vẫn vậy, chỉ cần để họ quét vỉa hè và đi tiếp!


0

Tôi nghĩ tiền đề là sai. Không có lý do gì một cơ sở dữ liệu cần phải là "trạng thái toàn cầu" chứ không phải là một đối tượng bối cảnh (rất lớn). Nếu bạn đang ràng buộc với cơ sở dữ liệu cụ thể, mã của bạn đang sử dụng thông qua các biến toàn cục hoặc các tham số kết nối cơ sở dữ liệu toàn cầu cố định, nó không khác biệt và không kém phần tệ hại, so với bất kỳ trạng thái toàn cầu nào khác. Mặt khác, nếu bạn chuyển xung quanh một đối tượng bối cảnh cho kết nối cơ sở dữ liệu, thì đó chỉ là trạng thái ngữ cảnh lớn (& được sử dụng rộng rãi), không phải là trạng thái toàn cầu.

Đo lường sự khác biệt rất dễ dàng: bạn có thể chạy hai phiên bản logic chương trình của mình, mỗi trường hợp sử dụng cơ sở dữ liệu riêng của nó, trong một chương trình / quy trình duy nhất mà không thực hiện các thay đổi xâm lấn đến mã không? Nếu vậy, cơ sở dữ liệu của bạn không thực sự là "trạng thái toàn cầu".


-2

Quả cầu không xấu xa; chúng chỉ đơn giản là một công cụ. MISUSE của toàn cầu là có vấn đề, cũng như việc sử dụng sai bất kỳ tính năng lập trình nào khác.

Khuyến nghị chung của tôi là toàn cầu chỉ nên được sử dụng trong các tình huống được hiểu rõ và suy nghĩ kỹ, trong đó các giải pháp khác ít tối ưu hơn. Quan trọng nhất, bạn muốn đảm bảo rằng bạn đã ghi lại rõ nơi giá trị toàn cầu đó có thể được sửa đổi và nếu bạn đang chạy đa luồng, bạn sẽ đảm bảo rằng toàn cầu và bất kỳ toàn cầu phụ thuộc nào đều truy cập theo cách giao dịch.


Một số người downvoters sẽ giải thích về downvote của bạn? Có vẻ thô lỗ với downvote mà không có lời giải thích.
Byron Jones

-2

Mẫu chỉ đọc và giả sử dữ liệu của bạn không cập nhật khi bạn in nó. Queue viết hoặc xử lý xung đột theo cách khác. Chào mừng bạn trong địa ngục quỷ, bạn đang sử dụng db toàn cầu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.