Masalah dengan Menghindari kelas Penamaan Smurf dengan ruang nama


39

Saya menarik istilah penamaan smurf dari sini (nomor 21). Untuk menyelamatkan siapa pun yang tidak mengenal masalahnya, penamaan Smurf adalah tindakan prefixing sekelompok kelas terkait, variabel, dll dengan awalan umum sehingga Anda berakhir dengan "a SmurfAccountViewpass a SmurfAccountDTOto the SmurfAccountController", dll.

Solusi yang umumnya saya dengar adalah membuat namespace smurf dan meletakkan awalan smurf. Ini umumnya bermanfaat bagi saya, tetapi saya mengalami dua masalah.

  1. Saya bekerja dengan perpustakaan dengan Configurationkelas. Itu bisa saja dipanggil WartmongerConfigurationtapi ada di namespace Wartmonger, jadi baru saja dipanggil Configuration. Saya juga memiliki Configurationkelas yang bisa dipanggil SmurfConfiguration, tetapi berada di namespace Smurf sehingga akan menjadi berlebihan. Ada tempat di kode saya di mana Smurf.Configurationmuncul di samping Wartmonger.Configurationdan mengetik nama yang sepenuhnya memenuhi syarat adalah kikuk dan membuat kode kurang dapat dibaca. Akan lebih baik untuk berurusan dengan SmurfConfigurationdan (jika itu kode saya dan bukan perpustakaan) WartmongerConfiguration.

  2. Saya memiliki kelas yang dipanggil Servicedalam namespace Smurf saya yang bisa dipanggil SmurfService. Serviceadalah fasad di atas perpustakaan Smurf yang kompleks yang menjalankan pekerjaan Smurf. SmurfServicesepertinya nama yang lebih baik karena Servicetanpa awalan Smurf sangat luar biasa. Saya dapat menerima bahwa SmurfServiceitu sudah generik, nama yang tidak berguna dan menghapus smurf hanya membuat ini lebih jelas. Tapi itu bisa saja dinamai Runner,, Launcherdll dan itu akan tetap "terasa lebih baik" bagi saya SmurfLauncherkarena saya tidak tahu apa yang Launcherdilakukan, tetapi saya tahu apa yang SmurfLaunchertidak. Anda bisa berargumen bahwa apa yang Smurf.Launcherdilakukan harus sejelas aSmurf.SmurfLauncher, tapi saya bisa melihat `Smurf.Launcher menjadi semacam kelas yang terkait dengan pengaturan daripada kelas yang meluncurkan smurf.

Jika ada cara terbuka dan tertutup untuk menangani salah satu dari ini, itu akan menjadi hebat. Jika tidak, apa sajakah praktik umum untuk mengurangi gangguan mereka?


3
Apakah Smurf.Launchermeluncurkan smurf, atau meluncurkan SmurfJob? Mungkin itu bisa disebut Smurf.JobLauncher?
Blorgbeard

2
Ini bau kode untuk menamai kelas XService, XManager, dll. Ini tidak berarti apa-apa. Ini seperti Util. Jika Anda membaca sekilas nama-nama file apa pun bisa ada di sana atau hilang dari sana. Tidak ada cara untuk mengetahui kecuali Anda melihat ke dalam. Saya akan mengganti nama dari SmurfService ke yang lain sepenuhnya.
Daniel Kaplan

1
Itu benar-benar meluncurkan SmurfJobs, atau secara teknis menjalankannya agar konsisten dengan bahasa dokumentasi Smurf. Mengingat itu dan jawaban lainnya, saya akan mengganti nama SmurfServicemenjadi SmurfJobRunner. Tampaknya nomor 1 tidak memiliki resolusi agnostik bahasa terbaik seperti yang saya harapkan. Saya dapat melihat contoh di mana pergi dengan SmurfConfigurationakan menjadi panggilan yang tepat, tetapi dalam kasus saya, saya pikir Configurationyang terbaik bahkan dengan kerumitan Wartmonger.Configuration.
Daniel Koverman

6
Saya mencoba memahami mengapa Anda memiliki satu kelas yang peduli untuk mengkonfigurasi Wartmongers dan Smurf sama sekali.
Donal Fellows

Mengapa Smurf.Configurationdan SmurfConfigurationterasa berbeda? Tentunya itu bukan char ekstra, kan? (Lebih Configpendek jika panjang masalahnya). Apakah Smurf.Configurationada masalah yang SmurfConfigurationtidak?
Pablo H

Jawaban:


16

Anda menaikkan beberapa poin bagus.

  1. Sehubungan dengan memiliki kelas duplikat, Anda dapat alias kelas di C #. Gunakan misalnya using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;Lihat posting ini di StackOverflow . Anda belum menunjukkan bahasa pemrograman Anda, tetapi saya telah menyimpulkannya dari apa yang Anda tulis. Jadi di mana Anda berurusan dengan dua proyek yang berbeda, Anda bisa menyebutnya sebagai SmurfConfigurationdan WartmongerConfigurationyang akan membebaskan ambiguitas ketika mengkonsumsi kedua kelas.

  2. Karena suatu layanan terkena aplikasi eksternal, saya melihat tidak ada masalah dalam merek layanan dengan nama aplikasi Anda, jadi dalam hal ini SmurfServiceakan valid karena sebenarnya akan membingungkan kelompok layanan dalam aplikasi yang mengkonsumsi.

Saya merasa bahwa ruang nama harus digunakan untuk menghindari gaya penamaan ini. Itu membuatnya lebih sulit untuk grok kode dan melihat pada nilai nominal apa kelas tanpa membaca MyCompanyMyProductMyAreaClassName. Menggunakan teknik aliasing memungkinkan Anda untuk mengurangi ambiguitas di mana diperlukan. Satu-satunya waktu saya pikir Anda harus memperkenalkan kompleksitas ke dalam penamaan Anda adalah, seperti yang saya tunjukkan di # 2, ketika orang akan mengkonsumsi layanan. Di sinilah masuk akal untuk memiliki gaya penamaan ini karena jika konsumen memiliki berbagai layanan yang dikonsumsi, ambiguitasnya dapat membingungkan.


5
alias hanya mengacaukan segalanya. Alih-alih Smurf.Service Anda sekarang memiliki SmurfService = Smurf.Service. Jadi Anda mungkin hanya memiliki SmurfService sebagai nama benda di tempat pertama. Mereka punya tempat, tetapi tidak untuk masalah khusus ini. Namun, itu mungkin jawaban terbaik untuk masalah yang tidak memiliki jawaban :)
gbjbaanb

C # dalam diri saya muncul dalam pertanyaan saya, tapi saya sebenarnya sedang berurusan dengan java dan org.apache.smurfville.wartmonger.configuration. Sayangnya ini mengesampingkan alias. 2 adalah poin yang kuat, jadi saya akan terus mencantumkan merek Smurf untuk Layanan.
Daniel Koverman

25

Titik ruang nama adalah agar Anda dapat memiliki kelas dengan nama yang sama dari perpustakaan yang berbeda tanpa bertabrakan. Saat Anda perlu menggunakan kelas bernama yang sama dari keduanya, Anda harus menghapus ambiguitas dengan mengawali satu atau keduanya dengan cakupan namespace-nya.

Yang mengatakan, itu tidak terlalu buruk untuk memiliki banyak kelas Smurf jika Smurf memberi tahu Anda sesuatu yang spesifik tentang kelas. Nama-nama kelas harus cukup deskriptif untuk memberi Anda beberapa informasi tentang apa yang dilakukan kelas.

      Session
       ^   ^
      /     \
DBSession   HttpSession

Demikian pula DBSessionmungkin mengambil DBRequestobjek yang mengembalikan DBResponseobjek. The HttpSessionkekuatan juga beroperasi pada HttpRequestdan HttpResponsebenda-benda.

Ini adalah kelas Smurf dengan tujuan.

Mereka mungkin tinggal di MyCompanynamespace tetapi MyCompanyHttpSessiondan MyCompanyDBSessiontidak memberi Anda informasi lebih dari yang Anda miliki sebelumnya. Dalam hal ini drop Smurf dan jadikan namespace.

MyCompany.HttpSession

3

Saya telah berlari melawan titik kebingungan yang sama ini sebelumnya dan biasanya benar-benar pertanyaan tentang apakah kita memasukkan jenis hal itu sebagai bagian dari namanya.

Anda menyebutkan SmurfConfigurationdan WartmongerConfigurationsebagai jenis konfigurasi yang potensial. Anda mengindikasikan bahwa Anda menghapus kata sifat (jenisnya) ke namespace-nya sehingga yang tersisa hanyalah vanila Configuration. Saya akan menghindari melakukan itu.

Ini seperti memutuskan bahwa es krim stroberi hanyalah es krim di ruang nama stroberi dan juga dengan cokelat, tetapi yang terjadi adalah Anda menceraikan kata sifat yang memberinya identitas dari benda itu sendiri. Ini bukan es krim dalam kategori stroberi. Ini es krim stroberi - sejenis es krim.

Mari kita bayangkan bahwa di aplikasi Anda, Anda mengimpor Strawberry.IceCreamkelas dan kemudian mulai instantiating langsung dari IceCream.

var ic = new IceCream(); //actually I'm strawberry ice cream

Ini mungkin terlihat baik dan bagus, sampai saat Anda akhirnya mengimpor IceCreamkelas lain . Sekarang Anda kembali ke masalah awal karena harus entah bagaimana membedakan di antara mereka, yang bermasalah. Yang Anda inginkan selama ini adalah:

var sic = new StrawberryIceCream();
var cic = new ChocolateIceCream();

Ruang nama lebih baik dibiarkan untuk menghindari potensi konflik antara pihak ketiga yang mungkin secara kebetulan mewakili konsep yang sama di perpustakaan mereka. Namun, ketika satu pengembang membuat perpustakaan atau proyek, ia harus menamai setiap konsep secara unik dan menggunakan ruang nama sebagai folder untuk organisasi saja. Seringkali nama folder akan ditemukan dalam nama konsep yang diorganisir dan tidak apa-apa.


2

Ini jelas merupakan aturan praktis yang baik bahwa jika Anda memiliki awalan umum pada sekelompok kelas, maka mereka mungkin layak masuk dalam namespace mereka sendiri. Untuk menangani masalah itu, saat Anda perlu menggunakan kelas yang bernama serupa dari dua ruang nama:

1) Alias ​​ruang nama, meskipun saya akan membuatnya singkat dan to the point, singkatan alami, bahkan mungkin hanya 1 huruf:

using Sm = Smurf;
using W = Wartmonger;

Kemudian selalu awali di mana saja digunakan dan beri nama instance dengan tepat:

Sm::Configuration smConf; 
W::Configuration wConf;

2) Alias ​​kelas, seperti yang disarankan dalam jawaban lain.

using SmConf = Smurf.Configuration;

3) Setiap perpustakaan yang Anda kendalikan, pertimbangkan untuk tidak menggunakan istilah 'Konfigurasi'. Gunakan tesaurus: misalnya 'Pengaturan', 'Model', 'Parameter'. Mungkin akan lebih bermakna bagi konteksnya: Misalnya jika Smurf adalah semacam modul analisis numerik yang Anda tulis, mungkin 'Parameter' akan lebih baik untuk konfigurasinya. Gunakan kosa kata tertentu yang terkait dengan konteks modul untuk keuntungan Anda untuk menghasilkan nama-nama unik yang memiliki keunikan bahkan ketika dicampur ke dalam ruang nama lain. Saya merasa ini mungkin semacam jawaban untuk pertanyaan OP 2.

4) Kode refactor sehingga Anda tidak perlu mencampur penggunaan konfigurasi dari dua tempat yang berbeda. Detail itu terserah Anda.

5) Gabungkan dua konfigurasi menjadi satu sebelum Anda meneruskannya ke kelas Anda. Gunakan kelas conf gabungan untuk mewakili:

struct Conf {
    SmurfConfiguration smurf;
    WartmongerConfiguation wart;
}

Nama-nama variabel anggota pendek sekarang semacam mencapai hal yang sama dengan alias kelas / namespace.


0

Tampaknya aneh bahwa menambahkan satu poin pada nama itu mengganggu Anda.

Wartmonger.Configuration configuration = Wartmonger.Configuration .new();

// vs

WartmongerConfiguration configuration = WartmongerConfiguration.new();

Jika keduanya Smurfdan Wartmongerkonfigurasi digunakan bersama di satu tempat, tetapi secara terpisah keduanya digunakan di banyak tempat - maka namespace jelas merupakan pendekatan yang baik.

Memiliki namespace akan memberikan kemungkinan untuk penggunaan nama "bersih" di kode internal, di mana dengan awalan yang Anda akhirnya menggunakan SmurfConfigurationdalam SmurfService's kode internal, yang dapat menjadi menjengkelkan setiap kali Anda akan membuka kode itu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.