Sesuatu tentang namespace

Saya pemrograman dalam PHP . Dan sedikit di JS . Setelah saya diprogram di Java , bahkan lebih awal - di LotusScript . Mencoba rasa python dan dart . Basic , Fortran , Pascal , Prolog , VisualBasic , ++ / , perl - pada semua ini saya juga menggambarkan sesuatu yang dapat dieksekusi. Bahasa pemrograman membuat saya tertarik dalam hal membuat aplikasi komputer. Aplikasi web. Aplikasi web yang canggih. Mereka yang menulis orang asing satu sama lain. Lebih tepatnya, mereka secara pribadi tidak terbiasa - mereka mengenal satu sama lain dengan tanda tangan dalam melakukan ke repositori umum dan dengan nama panggilan di pelacak bug. Saya tidak terlalu pintar untuk memprogram dalam / ++ untuk berbagai OS, dan karenanya saya pemrograman dalam PHP untuk Magento .


Jadi, kembali ke topik artikel, saya dapat mengatakan bahwa namespace adalah salah satu pilar yang sangat penting di mana penulisan aplikasi web yang kompleks didasarkan pada sekelompok pengembang yang tidak terbiasa satu sama lain.


Dalam teks ini, dengan namespace, maksud saya namespace dari sudut pandang PHP , bukan namespace dari sudut pandang python :


 <?php namespace Vendor\Project\Module\Component\Unit; 

Untuk pertama kalinya, saya menemukan namespace ketika mempelajari Java , ketika saya mencoba memahami rahasia dari petunjuk " paket ":


 package com.sun.source.util; 

Tujuan dari arahan ini tidak jelas, dan apa sebenarnya yang harus ditunjukkan di dalamnya, jika ada garis yang bisa ditunjukkan. Rekomendasi dari penulis bahasa untuk digunakan sebagai bagian dari nama paket terdaftar pada Anda (di perusahaan Anda) domain tampak agak boros. Sekarang semua orang, semua orang, siapa pun memiliki domain sendiri, dan rekomendasi ini tidak terlalu memalukan, dan 15-20 tahun yang lalu saya sangat memikirkan domain mana yang akan digunakan sebagai nama untuk paket pertama saya dan apa pengaruhnya di masa depan. Baru kemudian, ketika saya membangun aplikasi menggunakan maven , saya menghargai wawasan dari rekomendasi ini.


Manajer ketergantungan


Manajer ketergantungan membantu saya memahami arti namespace. Jika kode Anda menggunakan kode pihak ketiga, yang tergantung pada paket lain yang tergantung pada yang ketiga, sangat sulit untuk menjaga ketertiban dalam dump tersebut. Namun demikian, justru karena aturan domain-belakang untuk penamaan paket di tumpukan JAR yang ditumpuk ke dalam satu direktori (misalnya, di WEB-INF/lib ), cukup mudah untuk dinavigasi:


gambar


Bandingkan dengan npm ( JavaScript ):


gambar


Di Java pengembang telah mengadopsi nama paket " domain-belakang " (sebagai hasil dari modul) secara luas, sementara di JS tidak. Akibatnya, di Java Anda dapat secara mandiri membuat sejumlah besar paket (modul) tanpa konflik tanpa secara eksplisit menyetujui nama mereka sebagai grup pengembangan independen, dan di JS Anda harus secara eksplisit menggunakan registri npm . Ya, di Java , registri domain global secara implisit terlibat dalam menyelesaikan konflik, tetapi komunitas mana pun, tidak hanya penyandi Java , dapat menggunakan aturan penamaan yang sama.


Dalam PHP , manajer dependensi composer membuat struktur direktori dua tingkat: ./company/module :


gambar


yang memberikan beberapa keuntungan dalam navigasi ketergantungan daripada alokasi satu tingkat.


Berikut adalah statistik untuk repositori paket pusat untuk Java / JS / PHP :


https://mvnrepository.com/repos/central - 3 358 578 guci yang diindeks
https://www.npmjs.com/ - 872 459 paket
https://packagist.org/statistics - 207 560 paket (1.472.944 versi)


Kemungkinan besar untuk maven semua versi modul diperhitungkan dalam statistik, sementara modul itu sendiri diperhitungkan dalam npm dan composer .


Untuk apa namespace itu?


Jawaban utama adalah untuk mencegah konflik antara berbagai elemen kode (konstanta, fungsi, kelas, ...) yang memiliki nama yang sama tetapi berada dalam modul yang berbeda. Ruang nama python berhasil mengatasi hal ini. Tetapi saya masih akan mengambil "namespace" di sini dalam tanda kutip, karena pada dasarnya, ini lebih dekat ke ruang lingkup .


Namespace sesuai dengan versi Java ( package ) dan PHP ( namespace ) memungkinkan, pertama-tama, untuk secara jelas membahas elemen kode tertentu dalam komunitas agregat. Dan ini adalah properti namespace (pengelompokan logis) yang memungkinkan untuk membuat sistem perangkat lunak yang lebih kompleks oleh kelompok pengembang yang kurang terhubung.


Mengatasi elemen perangkat lunak


Dalam PHP kelas \Doctrine\DBAL\Schema\Column ditangani secara unik, tidak peduli bagaimana kode sumber terhubung ke proyek. IDE dapat dengan mudah membentuk alamat ini. Di PhpStorm, ini dilakukan seperti ini (klik kanan pada elemen kode):


gambar


PhpStorm yang sama hilang jika Anda menerapkan teknik serupa ke kode JS (di mana tidak ada namespace). Mari kita coba bentuk alamat untuk tautan ke fungsi query JS dengan cara ini:


gambar


Outputnya adalah module.query , yang tidak cukup informatif.


Untuk mengatasi fungsi query dalam dokumentasi (korespondensi, pelacak bug, dll.), Anda harus merujuk ke baris kode tertentu dalam file:


gambar


Hasil: ./node_modules/express/lib/middleware/query.js:25


Tentu saja, ketika mengubah jumlah baris dalam file atau memindahkan / mengganti nama file, dalam dokumentasi akan ada alamat yang sudah usang dari elemen program yang menarik bagi kami.


Dengan demikian, penggunaan namespace memungkinkan tautan ke berbagai elemen kode proyek tetap relevan lebih lama daripada tautan ke baris dalam file.


Mendeteksi versi kode yang bertentangan


Aplikasi kompleks modern tidak dapat dikembangkan tanpa manajer ketergantungan ( maven , composer , npm , ...). Pada saat yang sama, dependensi kami menarik dependensi mereka, yang menariknya sendiri, dll., Yang akibatnya dapat menyebabkan konflik versi untuk paket yang sama ditarik melalui dependensi berbeda ( neraka jar ).


Di JS ini tidak terjadi karena kurangnya namespace'ov. Saya sendiri menemukan situasi ketika, ketika memasang modul tambahan di Magento jumlah versi yang berbeda dari perpustakaan jQuery dimuat oleh mereka melebihi 5-6. Di satu sisi, perilaku semacam itu memberikan kebebasan yang lebih besar kepada pengembang sendiri, di sisi lain - lebih banyak kebebasan membuat lebih banyak tuntutan pada kualifikasi. Yah, mencari kesalahan dalam mie dependensi multi-versi seperti itu - kualifikasi adalah urutan atau dua lebih tinggi dari kualifikasi untuk membuat kesalahan ini.


Menggunakan namespace di PHP memudahkan untuk mendeteksi konflik semacam itu di tingkat IDE (misalnya, saya membuat file kedua dengan duplikat kelas di dalamnya):


gambar


Dengan demikian, tugas mendeteksi elemen kode rangkap dalam suatu proyek menjadi cukup mudah untuk diselesaikan.


Startup kode


Fungsi spl_autoload_register di PHP memungkinkan pengembang untuk tidak repot-repot dengan lokasi file dengan sumber kelasnya. Dalam proyek apa pun, Anda dapat mengganti fungsi ini dan mengimplementasikan algoritma pemuatan skrip Anda sendiri dengan nama kelas. Tanpa menggunakan namespace, perlu untuk menuliskan nama yang cukup keriting untuk kelas untuk memastikan keunikan mereka dalam proyek yang kompleks (terutama dengan mempertimbangkan perpustakaan pihak ketiga). Di Zend1 adaptor abstrak untuk bekerja dengan database didefinisikan sebagai berikut:


 abstract class Zend_Db_Adapter_Abstract {} 

Untuk memastikan keunikan, pada dasarnya, perlu menambahkan namespace ke nama kelas. Tentu saja, ketika menggunakan nama kelas seperti itu dalam kode, Anda harus mengarahkan mata Anda lebih lebar di sepanjang garis.


Di Zend2 , di mana ruang nama sudah digunakan, definisi kelas yang serupa terlihat seperti ini:


 namespace Zend\Db\Adapter; class Adapter implements ... {} 

Kode akhirnya menjadi lebih mudah dibaca, tetapi hasil paling signifikan dari penggunaan namespace adalah kemungkinan menyatukan fungsionalitas pemuat kelas dengan pengikatan hirarki logis kelas ke struktur file. Berikut ini kutipan dari file ./vendor/composer/autoload_namespaces.php yang dibuat composer di PHP agar loader ./vendor/autoload.php berfungsi:


 <?php $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( 'Zend_' => array($vendorDir . '/magento/zendframework1/library'), 'Yandex' => array($vendorDir . '/allure-framework/allure-codeception/src', $vendorDir . '/allure-framework/allure-php-api/src', $vendorDir . '/allure-framework/allure-php-api/test'), 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'), 'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src'), 'PhpCollection' => array($vendorDir . '/phpcollection/phpcollection/src'), 'PHPMD\\' => array($vendorDir . '/phpmd/phpmd/src/main/php'), 'OAuth\\Unit' => array($vendorDir . '/lusitanian/oauth/tests'), 'OAuth' => array($vendorDir . '/lusitanian/oauth/src'), ... 

Dapat dilihat bahwa sumber-sumber di perpustakaan yang berbeda dapat ditemukan dengan cara yang berbeda (struktur intra-modul yang berbeda), dan composer ketika membentuk proyek, membuat peta melapis hierarki logis kelas pada sistem file. Dan ruang nama memainkan peran penting dalam hamparan ini.


Untuk mengevaluasi peran ini, cukup untuk mencoba memecah beberapa modul npm menjadi beberapa modul yang lebih kecil dan membangun kembali proyek Anda untuk menggunakan dua modul baru alih-alih satu modul besar. By the way, kehadiran kelas di ES6 dan kurangnya namespace dalam arti pengelompokan kode logis mungkin akan mengarah pada penampilan nama yang mirip dengan yang ada di Zend1 ( Module_Path_To_Class ) dalam proyek ES6 besar.


IoC


Pengidentifikasi objek dalam wadah IoC adalah string (setidaknya dalam PHP ). Dalam contoh sederhana, pengidentifikasi seperti dbAdapter , serviceB , serviceB , dll. Sangat dapat diterima. Tetapi semakin besar proyek, semakin sulit untuk searchFilterList mana objek dengan pengenal dibuat, misalnya, searchFilterList dan di mana ia digunakan. Jalan keluar logis adalah dengan menggunakan nama kelas sebagai pengidentifikasi untuk objek. Dalam hal ini, logika membuat objek oleh wadah menjadi dapat diprediksi, dan kode sumber dan tempat penggunaan secara elementer ditentukan oleh IDE. Namespace memungkinkan Anda untuk mengatur semua kelas proyek dalam satu struktur logis dan menggunakan jalur yang sesuai saat membuat objek dengan wadah.


Ringkasan


Sehubungan dengan hal di atas, saya percaya bahwa bahasa pemrograman yang secara asli menggunakan ruang nama untuk menyusun kode sumber menggunakan pengelompokan logis dari elemen-elemennya memungkinkan membangun aplikasi yang lebih kompleks dengan biaya lebih murah daripada bahasa yang tidak memiliki pengelompokan logis. Dengan demikian, kompleksitas maksimum aplikasi yang dapat dibuat di Java / PHP / C++ / ... tidak dapat dicapai oleh pengembang dengan kualifikasi yang sama dalam JavaScript / Python / C / ....

Source: https://habr.com/ru/post/id434968/


All Articles