Konteks permintaan global - anti-pola?

12

Saya berbicara hari ini dengan seorang rekan kerja saya tentang kerangka kerja web Python dan kesan kami tentang mereka. Saya mengatakan kepadanya bahwa saya pikir Flask memiliki permintaan global berbau tidak enak dan merupakan anti-pola.

The docs katakan tentang konteks permintaan:

Sebaliknya, selama penanganan permintaan, ada beberapa aturan lain:

  • saat permintaan aktif, konteks objek lokal (flask.request dan lainnya) menunjuk ke permintaan saat ini.
  • kode apa pun dapat memperoleh benda-benda ini setiap saat.

Saya pikir saya mengerti ide di balik keputusan desain ini - untuk membuat aplikasi lebih sederhana. Ini hanya kompromi, seperti dalam kasus Thread Locals :

Ya itu biasanya bukan ide yang cemerlang untuk menggunakan thread lokal. Mereka menyebabkan masalah untuk server yang tidak didasarkan pada konsep utas dan membuat aplikasi besar lebih sulit untuk dipelihara. Namun Flask tidak dirancang untuk aplikasi besar atau server asinkron. Flask ingin membuatnya cepat dan mudah untuk menulis aplikasi web tradisional.

Apakah menambal objek global dengan informasi permintaan saat ini merupakan anti-pola?

Saya percaya itu, karena dalam pandangan penganalisa kode statis negara global, meskipun tidak. Dan saya sebagai programmer tidak akan mengerti cara kerjanya tanpa membaca dokumen dengan hati-hati. Dan ini memiliki konsekuensi pada tes .

Bukankah itu praktik yang baik untuk menyampaikan permintaan sebagai argumen untuk dilihat? Saya pikir ini lebih mudah dibaca, eksplisit dan lebih mudah untuk di-debug. Dan menghindari negara global.

warvariuc
sumber
2
Anda belum benar-benar menyatakan apa efek negatif spesifik dari antipattern tersebut. Saya tidak percaya generalisasi besar yang tidak memiliki dasar faktual.
Robert Harvey
2
Pertanyaan bagus, tapi sayangnya tidak banyak jawaban berkualitas
sleepycal

Jawaban:

4

Banyak kerangka kerja web memiliki struktur yang sama: permintaan global. Dalam arti tertentu, ini adalah hal yang benar untuk dilakukan karena hei, sebenarnya hanya ada satu permintaan pada satu waktu.

Jadi apakah ada gunanya menyampaikan permintaan sebagai parameter? Tidak. Permintaan adalah permintaan, dan parameter untuk melewati hal-hal yang berbeda pada waktu yang berbeda.

Masalah sebenarnya muncul saat Anda mulai mempertimbangkan level yang lebih rendah dari aplikasi yang lebih besar. Dengan permintaan global ada godaan untuk menulis kode di semua tempat yang mengakses permintaan secara global. Itu adalah hal yang sangat buruk . Ini menghasilkan sambungan antara berbagai bagian kode, membuatnya sulit untuk mengubah hal-hal dan membuatnya sulit untuk menguji hal-hal.

Jadi jawaban saya adalah: pertahankan permintaan global dan ikuti saja. Namun, di mana pun modul atau fungsi individual tidak memerlukan seluruh permintaan, kirimkan hanya data yang diperlukan sebagai parameter. Lewati saja pengarah, atau url, atau ekor perintah dan bit apa pun yang Anda butuhkan ke dalam fungsi Anda. Ini akan membantu menjaga kode tetap modular, mengurangi sambungan dan meningkatkan kemampuan uji.

Untuk program-program kecil, ini hampir tidak penting, tetapi untuk yang lebih besar ini bisa menjadi penyelamat nyata.

david.pfx
sumber
3

(Saya akan berani dan membuat ini menjadi jawaban, meskipun saya mungkin mendapatkan beberapa downvotes.)

Labu adalah kerangka kerja mikro; Anda mendapat manfaat dari kesederhanaan sambil menyerah pada embel-embel. Sementara pada level usus saya setuju dengan Anda, saya tahu bahwa saya menggunakan labu + gunicorn di satu toko untuk memberi saya multi-threading yang saya butuhkan. Itu bekerja dengan sangat baik. Setiap instance dari skrip hanya menyerahkan satu permintaan (yaitu satu utas), dan gunicorn menangani "fan out" di antara beberapa utas. Sangat hebat dalam hal itu.

Jadi kerugian yang Anda rasakan - bahwa banyak utas dapat bersaing untuk keadaan global - tidak hanya menjadi masalah, karena itu satu skrip per utas.

(Di sinilah saya mungkin mendapat masalah) Threading dan konkurensi hanya berbeda di dunia Python, dan jika Anda sampai pada itu dengan kerangka pikir Java, sulit untuk memerasnya. Pengalaman saya adalah masalah konkurensi yang saya ambil untuk diberikan di Jawa, atau yang ditangani secara transparan oleh wadah aplikasi, jauh lebih dekat ke permukaan dengan Python.

Aneh bagi saya bahwa satu utas akan menangani satu permintaan naskah saya, tetapi setelah saya memiliki beberapa lusin menjalankan pada kotak pada saat yang sama, saya merasa lebih baik tentang itu.

rampok
sumber
4
Saya tidak khawatir tentang keamanan benang dan semacamnya. Saya percaya Flask berfungsi dengan baik dalam kasus ini. Pertanyaan saya adalah tentang desain dan arsitektur aplikasi. Bukankah itu praktik yang baik untuk menyampaikan permintaan sebagai argumen untuk dilihat? Saya pikir ini lebih mudah dibaca, eksplisit dan lebih mudah untuk di-debug.
warvariuc
2

Dalam Python Anda memiliki printperintah (berfungsi sejak v3) yang mencetak ke output standar. Anda tidak menentukan secara eksplisit bahwa Anda ingin mencetak ke STDOUT - ini dilakukan untuk Anda secara implisit di belakang layar.

Secara implisit. Dengan Python Dan tidak ada yang punya masalah dengan itu. Mengapa?

printadalah bagian dari bahasa Python, dan salah satu syarat pemrograman dalam Python adalah ... yah ... mengetahui Python. Dan jika Anda tahu Python, Anda tahu bahwa printmenargetkan STDOUT. Tidak ada kejutan di sana.

Python - sebagai bahasa - dapat mendefinisikan konvensi itu sendiri dan berasumsi bahwa para programmer menyadarinya.

Kerangka kerja juga menikmati hak istimewa itu - itulah salah satu perbedaan utama antara kerangka kerja dan perpustakaan. Anda tidak harus mempelajari perpustakaan untuk menggunakannya - Anda hanya perlu menemukan bagian API yang Anda butuhkan, dan menganggapnya mengikuti konvensi bahasa (atau kerangka kerja). Itu sebabnya Anda tidak melihat perekrut mencari orang yang berpengetahuan di GSON atau Apache Commons. Tetapi Anda memang melihat perekrut mencari orang-orang yang berpengalaman dengan JQuery atau Ruby on Rails atau ASP.NET MVC - karena itu adalah kerangka kerja yang menentukan konvensi mereka sendiri yang perlu Anda pelajari dan ketahui.

Flask, sebagai kerangka kerja, dapat mendefinisikan konvensi untuk menyimpan konteks dalam global thread-lokal - dan seharusnya tidak mengejutkan siapa pun, jadi itu bukan anti-pola.

Idan Arye
sumber
2
Perhatikan bahwa "stdout" berarti deskriptor file apa pun yang ditunjuk oleh sys.stdout. Jika Anda mengubahnya, hasil cetak pergi ke tempat lain.
Phoshi
1
Selain itu, Anda bisa mengganti aliran keluaran menggunakan >>operator atau meneruskan fileargumen agar printberfungsi di Python3. Jadi, sys.stdouthanya nilai default yang bisa diganti.
warvariuc