Globale są nieuniknione.
To stara dyskusja, ale nadal chciałbym dodać kilka myśli, ponieważ brakuje mi ich w powyższych odpowiedziach. Te odpowiedzi upraszczają to, czym globalność jest za dużo i przedstawiają rozwiązania, które wcale nie są rozwiązaniami problemu. Problem w tym, że jaki jest właściwy sposób radzenia sobie ze zmienną globalną i użycie słowa kluczowego global? W tym celu musimy najpierw zbadać i opisać, czym jest globalność.
Spójrz na ten kod Zend - i proszę zrozumieć, że nie sugeruję, że Zend jest źle napisany:
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',
);
Jest tu wiele niewidocznych zależności. Te stałe są w rzeczywistości klasami. Możesz również zobaczyć require_once na niektórych stronach tego frameworka. Require_once to zależność globalna, stąd tworzenie zależności zewnętrznych. Jest to nieuniknione w przypadku ram. Jak możesz stworzyć klasę taką jak DecoratorPluginManager bez dużej ilości zewnętrznego kodu, od którego to zależy? Nie może funkcjonować bez wielu dodatków. Używając frameworka Zend, czy kiedykolwiek zmieniłeś implementację interfejsu? Interfejs jest w rzeczywistości globalny.
Inną aplikacją używaną na całym świecie jest Drupal. Bardzo zależy im na odpowiednim zaprojektowaniu, ale tak jak w przypadku każdego dużego frameworka mają wiele zewnętrznych zależności. Spójrz na globale na tej stronie:
/**
* @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();
Napisałeś kiedyś przekierowanie do strony logowania? To zmienia globalną wartość. (A więc czy nie mówisz „WTF”, co uważam za dobrą reakcję na złą dokumentację twojej aplikacji). Problem z globalnymi nie polega na tym, że są one globalne, potrzebujesz ich, aby mieć sensowną aplikację. Problem polega na złożoności całej aplikacji, która może sprawić, że obsługa jest koszmarem. Sesje są globalne, $ _POST to globalny, DRUPAL_ROOT to globalny, a include / install.core.inc 'jest globalną niemodyfikowalną. Istnieje duży świat poza jakąkolwiek funkcją, która jest wymagana, aby pozwolić tej funkcji wykonać swoją pracę.
Odpowiedź Gordona jest nieprawidłowa, ponieważ przecenia niezależność funkcji, a nazwanie funkcji kłamcą zbytnio upraszcza sytuację. Funkcje nie kłamią, a kiedy spojrzymy na jego przykład, funkcja jest zaprojektowana nieprawidłowo - jego przykładem jest błąd. (Nawiasem mówiąc, zgadzam się z tym wnioskiem, że należy oddzielić kod.) Odpowiedź deceze nie jest tak naprawdę właściwą definicją sytuacji. Funkcje zawsze działają w szerszym zakresie, a jego przykład jest zbyt uproszczony. Wszyscy zgodzimy się z nim, że ta funkcja jest całkowicie bezużyteczna, ponieważ zwraca stałą. Ta funkcja jest w każdym razie złym projektem. Jeśli chcesz pokazać, że praktyka jest zła, podaj odpowiedni przykład. Zmiana nazw zmiennych w całej aplikacji to nic wielkiego, mając dobre IDE (lub narzędzie). Pytanie dotyczy zakresu zmiennej, a nie różnicy w zakresie z funkcją. Jest odpowiedni czas, aby funkcja spełniała swoją rolę w procesie (dlatego jest tworzona w pierwszej kolejności) i w tym odpowiednim czasie może wpływać na działanie aplikacji jako całości, a więc również na zmienne globalne . Odpowiedzią xzyfera jest stwierdzenie bez argumentacji. Globale są tak samo obecne w aplikacji, jeśli masz funkcje proceduralne lub projekt OOP. Kolejne dwa sposoby zmiany wartości globalnej są zasadniczo takie same: stąd też pracuje nad zmiennymi globalnymi. Odpowiedzią xzyfera jest stwierdzenie bez argumentacji. Globale są tak samo obecne w aplikacji, jeśli masz funkcje proceduralne lub projekt OOP. Kolejne dwa sposoby zmiany wartości globalnej są zasadniczo takie same: stąd też praca nad zmiennymi globalnymi. Odpowiedzią xzyfera jest stwierdzenie bez argumentacji. Globale są tak samo obecne w aplikacji, jeśli masz funkcje proceduralne lub projekt OOP. Kolejne dwa sposoby zmiany wartości globalnej są zasadniczo takie same:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
W obu przypadkach wartość $ z zmienia się w ramach określonej funkcji. Na oba sposoby programowania możesz wprowadzić te zmiany w wielu innych miejscach w kodzie. Można powiedzieć, że używając global, możesz zadzwonić do $ z gdziekolwiek i tam się zmienić. Tak, możesz. Ale czy będziesz? A kiedy zrobi się to w nieodpowiednich miejscach, czy nie należy tego nazwać błędem?
Bob Fanger komentuje xzyfer.
Czy zatem ktoś powinien po prostu użyć czegokolwiek, a zwłaszcza słowa kluczowego „globalny”? Nie, ale tak jak w przypadku każdego rodzaju projektu, spróbuj przeanalizować, od czego to zależy, a co od tego zależy. Spróbuj dowiedzieć się, kiedy się zmienia i jak się zmienia. Zmiana wartości globalnych powinna mieć miejsce tylko w przypadku tych zmiennych, które mogą się zmieniać przy każdym żądaniu / odpowiedzi. To znaczy tylko do tych zmiennych, które należą do funkcjonalnego przepływu procesu, a nie do jego technicznej realizacji. Przekierowanie adresu URL do strony logowania należy do funkcjonalnego przepływu procesu, klasy implementacji używanej jako interfejs do implementacji technicznej. Możesz zmienić to drugie podczas różnych wersji aplikacji, ale nie należy zmieniać tych przy każdym żądaniu / odpowiedzi.
Aby lepiej zrozumieć, kiedy jest problem z pracą z globalnymi i słowem kluczowym global, a kiedy nie, przedstawię następne zdanie, które pochodzi od Wim de Bie pisząc o blogach: „Osobiste tak, prywatne nie”. Kiedy funkcja zmienia wartość zmiennej globalnej ze względu na swoje własne działanie, wtedy będę nazywać to prywatne użycie zmiennej globalnej i błąd. Ale kiedy zmiana zmiennej globalnej ma na celu poprawne przetworzenie aplikacji jako całości, jak przekierowanie użytkownika na stronę logowania, to moim zdaniem jest to możliwie dobry projekt, nie z definicji zły i na pewno nie anty-wzór.
Patrząc wstecz na odpowiedzi Gordona, deceze and xzyfer: wszyscy mają „prywatne tak” (i błędy) jako przykłady. Dlatego sprzeciwiają się używaniu globali. Ja też bym zrobił. Nie zawierają jednak przykładów „osobistych tak, prywatnych nie”, jak to robiłem w tej odpowiedzi kilka razy.