Global Değişkenler (Global Variables) ve Java

Zaman zaman Java programcılarının, üye değişkenlerden bahsederken “global değişkenler” (global variable) ifadesini kullandıklarına şahit oluyorum. Her duyduğumda da düzeltme ve üzerine bir miktar konuşma ihtiyacı hissediyorum. Yakınlarda da yine böyle bir şey oldu ve ben de artık yazayım dedim.

Temelde bu konuda bilinecek tek şey var: Java’da global değişken yoktur. Dolayısıyla Java’da bazı değişkenleri “global” olarak nitelemek doğru değildir. İsterseniz bu gerçeği kısaca açıklayalım:

Değişkenlerin görülebildiği ya da erişilebildiği alana, kapsam (scope) denir. Java’da değişkenlerin kapsamları derleme zamanında belirlenir ve çalışma zamanında değişmez. Bu yüzden Java, statik kapsamlı (statically scoped ya da lexically scoped) dillerdendir.

Açıkçası, kapsam sadece değişkenler için geçerli değildir. Herhangi bir tanıtımın (declaration) kapsamından bahsedilebilir. Nitekim”The Java Language Specification, Java SE 7 Edition”da ilgili 6.3 nolu konunun başlığı “Scope of a Declaration”dır yani “Bir Tanıtımın Kapsamı”. Bu başlık altında sadece değişkenlerin değil aynı zamanda örneğin “package” ya da “import” ifadelerinin kapsamları da ele alınır. Bunlarla anlatılmak istenen şey, bir Java kaynak kodu dosyasında bir “package” ya da bir “import” ifadesi varsa, bu ifadelerin getirdiği şeylerin etki alanıdır. Örneğin java paketi daima kapsamdadır. Fakat biz bu yazıda sadece değişkenleri göz önüne alacağız çünkü konumuz Java’da global değişkenlerin olup olmadığıdır.

Java’da bir değişkenin kapsamını belirleyen şeyin genel olarak bloklar olduğunu söyleyebiliriz. (Bunun bir istisnası, Java SE 5.0 ile gelen bir özellik olan “static import” ile import edilen statik değişkenler olabilir. Burada import edilen statik değişkenin kapsamı, içinde bulunduğu dosyadaki tüm Java kaynak kodudur.) Bir blokta tanımlanan bir değişkenin kapsamı, tanıtıldığı (declaration) yerden içinde bulunduğu bloğun sonuna kadardır. Değişkenlerin kapsamlarına, içinde tanıtıldığı bloğun alt bloklarında da dahildir. Java’da en geniş blok sınıf bloğudur.

Buna göre üye değişkenlerin (member variables) kapsamı, tanıtıldıkları yerden sınıfın sonuna kadardır. Tabi olarak bu kapsama başlatma blokları (initialization blocks), metotlar ya da metotlardaki if, for vb. bloklar yanında bütün alt tipler olmak üzere tüm alt kapsamlar da dahildir. Bu durum “The Java Language Specification, Java SE 7 Edition”da şöyle ifade ediliyor:

“The scope of a declaration of a member m declared in or inherited by a class type C (§8.1.6) is the entire body of C, including any nested type declarations.”

Java’da sınıf kapsamında tanıtılan değişkenlere “üye değişkenler” (member variables) denir. Üye değişkenler ya nesne değişkenidir (instance variable ya da object variable) ya da sınıf değişkenidir (class variable). Sınıf değişkenleri ise “static” olarak tanımlanır. Üye değişkenler dışındaki her türlü değişken Java’da sınıfın alt kapsamlarında tanımlanır ve bu yüzden “yerel değişken” olarak adlandırılır. Yerel değişkenleri ifade etmek için Ingilizce’de “local”, “stack”, “temporary” ve “automatic” sıfatları da kullanılır.

Yerel değişkenlerin kapsamı, tanıtıldıkları yerden, o blokun sonuna kadardır. Buna, benzer şekilde tüm alt kapsamlar dahildir. Bu durum da”The Java Language Specification, Java SE 7 Edition”da yine şöyle ifade ediliyor:

“The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer and including any further declarators to the right in the local variable declaration statement.”

Java’da sınıfın içindeki bloklardan herhangi birinde tanımlanan değişkenlere, kapsamları açısından “local” yani “yerel” değişken denmesi, yerel olmayan, üye değişkenlere “global” denmesini gerektirmez. Hatta global değişken (global variable) kavramının programlama dilleri açısından ifade ettiği özel anlamdan dolayı ki “global değişken” bu şekilde bir terim olmuştur, Java’da global değişken yoktur. Üye değişkenlerin global oluşundan bahsedeceksek, olsa olsa “sınıfa global” (global to class) denebilir.

Global değişken, programlama dillerinde kullanılan bir terimdir, bir ıstılahtır, özel anlama sahip bir kavramdır ve tekniktir. Global değişkenler her dilde desteklenmezler. Ama desteklendiklerinde farklı dillerde farklı şekillere, kurallara hatta anahtar kelimelere sahiptir. Örneğin C ve C++, global değişkenler için “extern” anahtar kelimesine sahiptir. PHP ya da Python gibi bazı diller ise “global” anahtar kelimesiyle global değişken oluşturmaya izin verirler.

Global değişkenlerin kapsamlarının tüm program ya da bir başka deyişle tüm kod tabanının (code base) olmasından dolayı, bu türden değişkenlerin faydadan çok zarar getirdikleri iddia edilerek eleştirilmiştir. Örneğin Steve McConnell, Code Complete isimli kitabının 2. baskısındaki 5. bölümde bu konuda şöyle demektedir:

Class Data Mistaken For Global Data

If you’re a conscientious programmer, one of the barriers to effective information hiding might be thinking of class data as global data and avoiding itbecause you want to avoid the problems associated with global data. While the road to programming hell is paved with global variables, class data presents far fewer risks.

Global data is generally subject to two problems: (1) Routines operate on global data without knowing that other routines are operating on it; and (2) routines are aware that other routines are operating on the global data, but they don’t know exactly what they’re doing to it. Class data isn’t subject to either of these problems. Direct access to the data is restricted to a few routines organized into a single class. The routines are aware that other routines operate on the data, and they know exactly which other routines they are.

Of course this whole discussion assumes that your system makes use of well designed, small classes. If your program is designed to use huge classes that contain dozens of routines each, the distinction between class data and global data will begin to blur, and class data will be subject to many of the same problems as global data.

Kısaca özetlemek istersek, global değişkenlerin bulunmasının, çalışma zamanında,programın farklı kısımları tarafından kullanılmasının getireceği sıkıntılardan bahsederek ilk paragrafın sonunda “programlama cehenneminin yolu global değişkenlerle döşeliyken, sınıf verisi daha az risk sunar” diyor.

Peki, Java’da global değişken olmamasına rağmen biz Java ile yazdığımız programlarda global olarak kullanılabilecek değişkenler oluşturmaz mıyız? Tabi ki oluşturabiliriz. Nihayetinde pek çok dil ve Java, veriyi saklamak için pek çok farklı bilgi saklama (information hiding) yapısına sahiptir. Ama nihayetinde bu yapıları kullanıp kullanmamak programcının elindedir. Örneğin public anahtar kelimesiyle her yerden ulaşılır yapılan her static değişken, içinde bulunduğu sınıf üzerinden rahatlıkla erişilebilir. Bu durumun problem olmaması için bu tür değişkenlerin, final anahtar kelimesiyle “değişken” olmaktan çıkarılıp, sabite haline getirilmesi tavsiye edilir ki sistemde hiç bir başka yer bu tür sabitelerin değerini değiştiremesin, sadece okusun. Bu şekilde bu gibi sabiteleri kimin ne zaman güncelleyeceğini ya da güncellediğini takip etmek gerekmez ve bu durum thread-safe bir yapı sunar.

Kısaca söylersek, Java’da global değişken yoktur çünkü hiç bir değişkenin global bir kapsamı yoktur. Fakat yine de sınıf üzerinde tanımlanıp, her yerden ulaşılabilen değişkenler oluşturulabilir. Bu durumlarda, bu türden değişkenlerin sadece okunabilen olarak kullanılması ve mümkünse final yapılarak sabite haline getirilmesi, sistemin parçalarının aralarındaki bağımlılıkları azaltmak açısından önemlidir.

Global değişkensiz günler dilerim 🙂

Bu yazı toplam 1032 defa görüntülenmiştir.