Quả cầu là không thể tránh khỏi.
Đó là một cuộc thảo luận cũ, nhưng tôi vẫn muốn thêm một số suy nghĩ vì tôi nhớ chúng trong các câu trả lời đã đề cập ở trên. Những câu trả lời đó đơn giản hóa những gì một toàn cầu là quá nhiều và đưa ra các giải pháp không phải là tất cả các giải pháp cho vấn đề. Vấn đề là: đâu là cách thích hợp để đối phó với một biến toàn cục và việc sử dụng từ khóa toàn cục? Để làm được điều đó, trước tiên chúng ta phải kiểm tra và mô tả toàn cầu là gì.
Hãy xem đoạn mã này của Zend - và hãy hiểu rằng tôi không cho rằng Zend bị viết xấu:
class DecoratorPluginManager extends AbstractPluginManager
{
/**
* Default set of decorators
*
* @var array
*/
protected $invokableClasses = array(
'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
);
Có rất nhiều phụ thuộc vô hình ở đây. Các hằng số đó thực sự là các lớp. Bạn cũng có thể thấy request_once trong một số trang của khuôn khổ này. Request_once là một phụ thuộc toàn cục, do đó tạo ra các phụ thuộc bên ngoài. Đó là điều không thể tránh khỏi đối với một khuôn khổ. Làm thế nào bạn có thể tạo một lớp như DecoratorPluginManager mà không cần nhiều mã bên ngoài mà nó phụ thuộc vào? Nó không thể hoạt động nếu không có nhiều tính năng bổ sung. Sử dụng khung công tác Zend, bạn đã bao giờ thay đổi việc triển khai một giao diện chưa? Một giao diện trên thực tế là một toàn cầu.
Một ứng dụng khác được sử dụng trên toàn cầu là Drupal. Họ rất quan tâm đến thiết kế phù hợp, nhưng cũng giống như bất kỳ khuôn khổ lớn nào, chúng có rất nhiều yếu tố phụ thuộc bên ngoài. Hãy xem các hình cầu trong trang này:
/**
* @file
* Initiates a browser-based installation of Drupal.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
/**
* Global flag to indicate that site is in installation mode.
*/
define('MAINTENANCE_MODE', 'install');
// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the <a href="http://drupal.org/requirements">system requirements</a> page for more information.';
exit;
}
// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();
Đã bao giờ viết một chuyển hướng đến trang đăng nhập? Điều đó đang thay đổi một giá trị toàn cầu. (Và sau đó bạn không nói 'WTF', mà tôi coi như một phản ứng tốt trước tài liệu xấu về ứng dụng của bạn.) Vấn đề với hình cầu không phải là chúng là hình cầu, bạn cần chúng để có một ứng dụng có ý nghĩa. Vấn đề là sự phức tạp của ứng dụng tổng thể có thể khiến nó trở thành cơn ác mộng để xử lý. Phiên là toàn cầu, $ _POST là toàn cầu, DRUPAL_ROOT là toàn cầu, bao gồm / install.core.inc 'là toàn cầu không thể thay đổi. Có một thế giới rộng lớn bên ngoài bất kỳ chức năng nào được yêu cầu để chức năng đó thực hiện công việc của nó.
Câu trả lời của Gordon là không chính xác, bởi vì anh ta đánh giá cao tính độc lập của một hàm và gọi một hàm là kẻ nói dối đang đơn giản hóa tình huống. Các hàm không nói dối và khi bạn xem ví dụ của anh ta, hàm được thiết kế không đúng - ví dụ của anh ta là một lỗi. (Nhân tiện, tôi đồng ý với kết luận này rằng người ta nên tách mã.) Câu trả lời của lừa dối không thực sự là một định nghĩa thích hợp về tình huống. Các hàm luôn hoạt động trong một phạm vi rộng hơn và ví dụ của anh ấy quá đơn giản. Tất cả chúng ta sẽ đồng ý với anh ta rằng hàm đó hoàn toàn vô dụng, bởi vì nó trả về một hằng số. Chức năng đó dù sao cũng là một thiết kế tồi. Nếu bạn muốn chỉ ra rằng thực hành là xấu, hãy đi kèm với một ví dụ có liên quan. Đổi tên các biến trong toàn bộ ứng dụng không phải là vấn đề lớn nếu có một IDE (hoặc một công cụ) tốt. Câu hỏi là về phạm vi của biến, không phải là sự khác biệt về phạm vi với hàm. Có một thời gian thích hợp để một hàm thực hiện vai trò của nó trong quy trình (đó là lý do tại sao nó được tạo ngay từ đầu) và vào thời điểm thích hợp đó nó có thể ảnh hưởng đến hoạt động của toàn bộ ứng dụng, do đó cũng hoạt động trên các biến toàn cục . Câu trả lời của xzyfer là một tuyên bố không cần tranh luận. Globals cũng xuất hiện trong ứng dụng nếu bạn có các hàm thủ tục hoặc thiết kế OOP. Hai cách tiếp theo để thay đổi giá trị của toàn cục về cơ bản giống nhau: do đó cũng làm việc trên các biến toàn cục. Câu trả lời của xzyfer là một tuyên bố không cần tranh luận. Globals cũng xuất hiện trong ứng dụng nếu bạn có các hàm thủ tục hoặc thiết kế OOP. Hai cách tiếp theo để thay đổi giá trị của toàn cục về cơ bản giống nhau: do đó cũng làm việc trên các biến toàn cục. Câu trả lời của xzyfer là một tuyên bố không cần tranh luận. Globals cũng xuất hiện trong ứng dụng nếu bạn có các hàm thủ tục hoặc thiết kế OOP. Hai cách tiếp theo để thay đổi giá trị của toàn cục về cơ bản giống nhau:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
Trong cả hai trường hợp, giá trị của $ z được thay đổi trong một hàm cụ thể. Trong cả hai cách lập trình, bạn có thể thực hiện những thay đổi đó ở một loạt các vị trí khác trong mã. Bạn có thể nói rằng sử dụng global, bạn có thể gọi $ z ở bất kỳ đâu và thay đổi ở đó. Có, bạn có thể. Nhưng bạn sẽ? Và khi được thực hiện ở những nơi không phù hợp, nó sẽ không được gọi là lỗi?
Bob Fanger bình luận về xzyfer.
Sau đó có nên sử dụng bất cứ ai và đặc biệt là từ khóa 'toàn cầu' không? Không, nhưng cũng giống như bất kỳ kiểu thiết kế nào, hãy cố gắng phân tích xem nó phụ thuộc vào cái gì và cái gì phụ thuộc vào nó. Cố gắng tìm hiểu khi nào nó thay đổi và nó thay đổi như thế nào. Thay đổi giá trị toàn cục chỉ nên xảy ra với những biến có thể thay đổi theo mọi yêu cầu / phản hồi. Có nghĩa là, chỉ đối với những biến thuộc dòng chức năng của một quá trình, chứ không phải việc thực hiện kỹ thuật của nó. Việc chuyển hướng một URL đến trang đăng nhập thuộc về quy trình chức năng, lớp triển khai được sử dụng cho một giao diện để triển khai kỹ thuật. Bạn có thể thay đổi cái sau trong các phiên bản khác nhau của ứng dụng, nhưng không nên thay đổi cái sau với mọi yêu cầu / phản hồi.
Để hiểu rõ hơn khi nào đó là vấn đề khi làm việc với các hình cầu và từ khóa toàn cầu và khi nào thì không, tôi sẽ giới thiệu câu tiếp theo, xuất phát từ Wim de Bie khi viết về blog: 'Cá nhân có, riêng tư không'. Khi một hàm thay đổi giá trị của một biến toàn cục vì lợi ích của chính nó, thì tôi sẽ gọi đó là việc sử dụng riêng một biến toàn cục và một lỗi. Nhưng khi sự thay đổi của biến toàn cục được thực hiện để xử lý toàn bộ ứng dụng một cách thích hợp, chẳng hạn như chuyển hướng của người dùng đến trang đăng nhập, thì theo tôi đó có thể là thiết kế tốt, không phải là xấu và chắc chắn không phải là một chống hoa văn.
Hồi tưởng lại câu trả lời của Gordon, cheat và xzyfer: tất cả đều có 'có riêng' (và lỗi) làm ví dụ. Đó là lý do tại sao họ phản đối việc sử dụng các quả cầu. Tôi cũng sẽ làm. Tuy nhiên, chúng không đi kèm với các ví dụ 'cá nhân có, không riêng tư' như tôi đã làm trong câu trả lời này vài lần.