Mengapa variabel global jahat? [Tutup]

121

Saya mencoba mencari tahu mengapa penggunaan globalpython dianggap praktik yang buruk (dan dalam pemrograman secara umum). Adakah yang bisa menjelaskan? Tautan dengan info lebih lanjut juga akan dihargai.

LarsVegas
sumber
Memberi suara untuk membuka kembali - Saya mengedit pertanyaan untuk mengalihkan fokus ke penjelasan dan menjauh dari sumber daya di luar situs. (Saya berasumsi bahwa ini mengapa itu tertutup, tetapi hanya dalam kasus sesuatu untuk dilakukan dengan menjadi pertanyaan tentang praktek yang buruk, membandingkan pertanyaan-pertanyaan lainnya tentang praktik buruk yang masih terbuka: eval, import *, penggabungan string , variabelid , bayangan atribut )
wjandrea

Jawaban:

156

Ini tidak ada hubungannya dengan Python; variabel global buruk dalam bahasa pemrograman apa pun.

Namun, konstanta global secara konseptual tidak sama dengan variabel global ; konstanta global sama sekali tidak berbahaya. Dalam Python perbedaan antara keduanya murni berdasarkan konvensi: CONSTANTS_ARE_CAPITALIZEDdan globals_are_not.

Alasan variabel global buruk adalah karena mereka mengaktifkan fungsi untuk menyembunyikan efek samping (tidak jelas, mengejutkan, sulit dideteksi, sulit didiagnosis), yang mengarah ke peningkatan kompleksitas, yang berpotensi mengarah ke kode Spaghetti .

Namun, penggunaan status global yang wajar dapat diterima (seperti status lokal dan mutabilitas) bahkan dalam pemrograman fungsional, baik untuk pengoptimalan algoritme, pengurangan kompleksitas, caching dan memoization, atau kepraktisan struktur port yang berasal dari basis kode yang sangat penting.

Secara keseluruhan, pertanyaan Anda dapat dijawab dengan berbagai cara, jadi taruhan terbaik Anda adalah hanya dengan google "mengapa variabel global buruk". Beberapa contoh:

Jika Anda ingin lebih dalam dan mencari tahu mengapa semua efek samping itu, dan banyak hal lain yang mencerahkan, Anda harus mempelajari Pemrograman Fungsional:

Erik Kaplun
sumber
35

Ya, secara teori , global (dan "negara" secara umum) itu jahat. Dalam praktiknya, jika Anda melihat ke dalam direktori paket python Anda, Anda akan menemukan bahwa sebagian besar modul di sana dimulai dengan sekumpulan deklarasi global. Jelas, orang tidak punya masalah dengan mereka.

Khususnya untuk python, visibilitas global terbatas pada modul, oleh karena itu tidak ada global "sebenarnya" yang memengaruhi keseluruhan program - yang membuatnya tidak terlalu berbahaya. Poin lain: tidak ada const, jadi ketika Anda membutuhkan konstanta, Anda harus menggunakan global.

Dalam praktik saya, jika kebetulan saya memodifikasi global dalam suatu fungsi, saya selalu mendeklarasikannya dengan global, meskipun secara teknis tidak diperlukan, seperti dalam:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Ini membuat manipulasi global lebih mudah dilacak.

georg
sumber
3
dalam banyak hal, modul dalam python mirip dengan kelas tunggal, dan modul global mirip dengan properti kelas.
Corley Brigman
9
@CorleyBrigman: kelas tunggal sebenarnya sering mengalami masalah yang sama yang biasanya dikaitkan dengan global :)
Erik Kaplun
4
visibilitas modul python tidak terbatas pada sebuah modul. Mereka tersedia di seluruh penafsir, dan (inilah yang terpenting) perubahan di sana memengaruhi seluruh penafsir. Ini tidak seperti string yang Anda buat instance ... itu seperti memodifikasi semua instance string. Bau tambalan monyet.
graffic
2
Kebanyakan modul tidak dimulai dengan mendefinisikan global kecuali konstanta. Globals buruk berarti variabel / keadaan global bukan konstanta.
BlackJack
2
Menggunakan global adalah ide yang buruk, salah satu alasannya mungkin ketidakmampuan untuk menguji fungsi dengan benar yang memperbarui beberapa kamus sembarang yang ada "di suatu tempat". Basis kode dengan global tidak dapat benar-benar terbukti berfungsi.
Tomasz Sosiński
10

Pendapat pribadi tentang topik ini adalah bahwa variabel global yang digunakan dalam logika fungsi berarti bahwa beberapa kode lain dapat mengubah logika dan keluaran yang diharapkan dari fungsi tersebut yang akan membuat proses debug menjadi sangat sulit (terutama dalam proyek besar) dan akan membuat pengujian lebih sulit. demikian juga.

Selain itu, jika Anda menganggap orang lain membaca kode Anda (komunitas sumber terbuka, kolega, dll.), Mereka akan kesulitan memahami di mana variabel global disetel, di mana telah diubah dan apa yang diharapkan dari variabel global ini sebagai lawan ke fungsi terisolasi yang fungsinya dapat ditentukan dengan membaca definisi fungsi itu sendiri.

(Mungkin) Melanggar definisi Fungsi Murni

Saya percaya bahwa kode yang bersih dan (hampir) bebas bug harus memiliki fungsi yang semurni mungkin (lihat fungsi murni ). Fungsi murni adalah fungsi yang memiliki kondisi berikut:

  1. Fungsi selalu mengevaluasi nilai hasil yang sama dengan nilai argumen yang sama . Nilai hasil fungsi tidak dapat bergantung pada informasi atau status tersembunyi yang dapat berubah saat eksekusi program berlangsung atau di antara berbagai eksekusi program, juga tidak dapat bergantung pada input eksternal apa pun dari perangkat I / O (biasanya — lihat di bawah).
  2. Evaluasi hasil tidak menyebabkan efek samping atau keluaran yang dapat diamati secara semantik , seperti mutasi objek yang dapat berubah atau keluaran ke perangkat I / O.

Memiliki variabel global melanggar setidaknya salah satu hal di atas jika tidak keduanya sebagai kode eksternal mungkin dapat menyebabkan hasil yang tidak diharapkan.

Definisi lain yang jelas dari fungsi murni: "Fungsi murni adalah fungsi yang mengambil semua masukannya sebagai argumen eksplisit dan menghasilkan semua keluarannya sebagai hasil eksplisit ." [1] . Memiliki variabel global melanggar gagasan fungsi murni karena input dan mungkin salah satu output (variabel global) tidak diberikan atau dikembalikan secara eksplisit.

(Mungkin) Prinsip PERTAMA pengujian Unit melanggar

Selanjutnya pada itu, jika Anda mempertimbangkan pengujian unit dan prinsip PERTAMA ( F tes ast, saya tes ndependent, R epeatable, S elf-Memvalidasi dan T imely) mungkin akan melanggar Independen tes prinsip (yang berarti bahwa tes tidak tergantung satu sama lain).

Memiliki variabel global (tidak selalu) tetapi dalam kebanyakan kasus (setidaknya dari apa yang telah saya lihat sejauh ini) adalah mempersiapkan dan meneruskan hasil ke fungsi lain. Ini juga melanggar prinsip ini. Jika variabel global telah digunakan dengan cara itu (yaitu variabel global yang digunakan dalam fungsi X harus disetel dalam fungsi Y terlebih dahulu) itu berarti bahwa untuk menguji unit fungsi X Anda harus menjalankan uji / menjalankan fungsi Y terlebih dahulu.

Global sebagai konstanta

Di sisi lain dan seperti yang telah disebutkan orang lain, jika variabel global digunakan sebagai variabel "konstan" bisa sedikit lebih baik karena bahasa tidak mendukung konstanta. Namun, saya selalu lebih suka bekerja dengan kelas dan memiliki "konstanta" sebagai anggota kelas dan tidak menggunakan variabel global sama sekali. Jika Anda memiliki kode yang diperlukan oleh dua kelas berbeda untuk berbagi variabel global, Anda mungkin perlu memfaktorkan ulang solusi Anda dan membuat kelas Anda independen.

Saya tidak percaya bahwa global tidak boleh digunakan. Tetapi jika mereka digunakan, penulis harus mempertimbangkan beberapa prinsip (yang mungkin disebutkan di atas dan prinsip rekayasa perangkat lunak lainnya dan praktik yang baik) untuk kode yang lebih bersih dan hampir bebas bug.

Rafael
sumber
1
Saya suka "global sebagai konstanta adalah masalah" ... karena jika Anda melakukan desain OO ... memang begitu. Mengapa ada orang selain kelas IdCreator yang perlu mengetahui ID_LEN?
Erik Aronesty
3

Mereka penting, layar menjadi contoh yang baik. Namun, dalam lingkungan multithread atau dengan banyak pengembang yang terlibat, dalam praktiknya sering muncul pertanyaan: siapa yang (secara keliru) menetapkan atau menghapusnya? Bergantung pada arsitekturnya, analisis bisa jadi mahal dan sering dibutuhkan. Meskipun tidak masalah, membaca var global, menulis ke sana harus dikontrol, misalnya dengan satu thread atau kelas threadsafe. Oleh karena itu, para vars global menimbulkan ketakutan akan biaya pengembangan yang tinggi yang mungkin disebabkan oleh konsekuensi yang dianggap jahat. Oleh karena itu secara umum, merupakan praktik yang baik untuk menjaga jumlah vars global tetap rendah.

Horst Schlawutzke
sumber