Beberapa kelas dengan nama yang sama, tetapi ruang nama yang berbeda?


11

Saya telah mengalami beberapa kode (C # jika itu penting) yang memiliki kelas yang memiliki nama yang sama, tetapi berbeda dalam ruang nama mereka. Mereka semua cenderung mewakili hal logis yang sama, tetapi seringkali berbeda "pandangan" dari objek yang sama. Ruang nama yang berbeda kadang-kadang bagian dari solusi yang sama, dan bahkan dll yang sama.

Saya memiliki pemikiran, tetapi tidak dapat menemukan sesuatu yang pasti tentang praktik ini untuk dianggap sebagai penggunaan alat yang pintar atau pola yang harus dihindari.

Pertanyaan tentang penamaan smurf menyentuh ini, tetapi dari arah lain. Mengaburkan nama kemungkinan akan membutuhkan awalan yang sewenang-wenang dan luas, yang ingin dihilangkan pertanyaan itu.

Apa pedoman seputar praktik ini?


1
Dalam OOP ada banyak pengecualian, tetapi pada awalnya saya menganggap desain yang buruk ini, terutama jika semua kelas memiliki tingkat aksesibilitas yang sama. Ketika saya membaca nama kelas, dalam file apa pun, maka saya ingin tahu di namespace apa kelas itu terletak segera tanpa harus merujuk ke direktif namespace.
Leopold Asperger

Ada kasus yang valid untuk memiliki beberapa objek terkait yang berhubungan dengan keadaan yang sama, tetapi biasanya mereka dipisahkan oleh fungsi. Mungkin Anda memiliki satu objek yang mengadaptasi model untuk tampilan. Yang lain mungkin melakukan perhitungan pada objek. Yang lain mungkin adaptor atau fasad. Jadi Anda mungkin memiliki FooAdapter, FooViewer, FooCalculator, dll tapi tentu tidak bernama hal yang sama. Namun, tanpa informasi lebih lanjut tentang kelas-kelas spesifik yang Anda bicarakan, sulit untuk memberikan jawaban.

@JohnGaughan - pertimbangkan Employeesebagai contoh. Ada karyawan yang untuk karyawan lain, satu untuk SDM, satu untuk paparan luar. Mereka semua bernama "karyawan" dan mereka semua memiliki jenis pembantu (EmployeeRepository, EmployeeView, dll.). Mereka semua berada di dll yang sama, dan sementara mereka berbagi beberapa sifat umum (nama, judul), mereka semua berbeda (nomor telepon, gaji).
Telastyn

Setelah bekerja dengan sistem bahwa model Employees beberapa kali, suara seperti Anda membutuhkan model dengan serikat dari semua atribut dan termasuk typeatau departmentatribut. Kalau tidak, ada duplikasi kode yang tidak perlu.

5
Bukankah ini salah satu alasan ruang nama untuk memulai? Untuk mengizinkan tabrakan nama?
Dan Pichelman

Jawaban:


5

Saya akan mencoba memberikan jawaban terhadap penggunaan tersebut, setelah melihat dan mengerjakan ini di salah satu proyek saya juga.

Keterbacaan kode

Pertama-tama, pertimbangkan bahwa keterbacaan kode penting dan praktik ini bertentangan dengan itu. Seseorang membaca sepotong kode dan katakan saja ia memiliki fungsi doSomething(Employee e). Ini tidak lagi dapat dibaca, karena karena 10 Employeekelas berbeda yang ada dalam paket yang berbeda, Anda harus terlebih dahulu menggunakan deklarasi impor untuk mengetahui apa input Anda sebenarnya.

Namun, ini adalah tampilan tingkat tinggi dan kita sering memiliki bentrokan nama yang tampaknya acak, yang tidak dipedulikan atau bahkan ditemukan oleh siapa pun, karena artinya dapat diturunkan dari kode yang tersisa dan paket yang Anda gunakan. Jadi orang bahkan dapat berdebat bahwa, secara lokal, tidak ada masalah, karena tentu saja jika Anda melihat Employeedalam sebuah hrpaket Anda harus tahu bahwa kita sedang berbicara tentang pandangan SDM karyawan.

Hal-hal pecah begitu Anda meninggalkan paket-paket ini. Setelah Anda bekerja dalam modul / paket / etc yang berbeda dan perlu bekerja dengan karyawan, Anda sudah mengorbankan keterbacaan jika Anda tidak sepenuhnya memenuhi syarat jenisnya. Selain itu, memiliki 10 Employeekelas yang berbeda berarti bahwa penyelesaian otomatis IDE Anda tidak lagi berfungsi dan Anda harus memilih secara manual dari tipe karyawan.

Duplikasi kode

Karena sifat masing-masing kelas yang terkait satu sama lain, kode Anda cenderung memburuk karena banyak duplikasi. Dalam kebanyakan kasus, Anda akan memiliki sesuatu seperti nama karyawan atau nomor identifikasi, yang harus diterapkan oleh masing-masing kelas. Meskipun setiap kelas menambahkan jenis pandangannya sendiri, jika mereka tidak membagikan data karyawan yang mendasarinya, maka Anda akan berakhir dengan banyak sekali kode yang tidak berguna, tetapi mahal.

Kompleksitas kode

Apa yang bisa begitu rumit yang mungkin Anda tanyakan? Bagaimanapun, masing-masing kelas dapat menjaganya sesederhana yang diinginkan. Yang benar-benar menjadi masalah adalah bagaimana Anda menyebarkan perubahan. Dalam perangkat lunak kaya fitur yang masuk akal, Anda mungkin dapat mengubah data karyawan - dan Anda ingin mencerminkannya di mana-mana. Katakan bahwa seorang wanita baru saja menikah dan Anda harus mengganti namanya dari XmenjadiYkarena itu. Cukup sulit untuk melakukan ini dengan benar di semua tempat, tetapi bahkan lebih sulit ketika Anda memiliki semua kelas yang berbeda ini. Bergantung pada pilihan desain Anda yang lain, ini dapat dengan mudah berarti bahwa masing-masing kelas harus mengimplementasikan jenis pendengarnya sendiri atau diberitahukan perubahan - yang pada dasarnya berarti faktor yang diterapkan pada jumlah kelas yang harus Anda tangani . Dan tentu saja lebih banyak duplikasi kode, dan lebih sedikit keterbacaan kode, .. Faktor-faktor seperti ini mungkin tidak dapat diabaikan dalam analisis kompleksitas, tetapi mereka tentu saja mengganggu ketika diterapkan pada ukuran basis kode Anda.

Komunikasi kode

Terlepas dari masalah di atas dengan kompleksitas kode, yang juga terkait dengan pilihan desain, Anda juga mengurangi kejelasan desain tingkat tinggi dan kehilangan kemampuan untuk berkomunikasi dengan benar dengan pakar domain. Ketika Anda mendiskusikan arsitektur, desain, atau persyaratan, Anda tidak lagi bebas membuat pernyataan sederhana seperti given an employee, you can do .... Pengembang tidak akan lagi tahu apa employeearti sebenarnya pada saat itu. Meskipun seorang pakar domain tentu akan mengetahuinya. Kita semua melakukannya. semacam itu. Tetapi dalam hal perangkat lunak itu tidak begitu mudah untuk berkomunikasi lagi.

Bagaimana cara menyingkirkan masalahnya

Setelah mengetahui hal ini dan jika tim Anda setuju bahwa itu adalah masalah yang cukup besar untuk diatasi, maka Anda harus mencari cara untuk menghadapinya. Biasanya, Anda tidak dapat meminta manajer Anda untuk memberi seluruh tim libur seminggu sehingga mereka dapat membuang sampah. Jadi intinya, Anda harus menemukan cara untuk menghilangkan sebagian kelas-kelas ini, satu per satu. Bagian terpenting dari ini adalah memutuskan - bersama seluruh tim - apa yang Employeesebenarnya. Jangan tidak mengintegrasikan semua atribut individu ke dalam satu dewa-karyawan. Pikirkan lebih banyak karyawan inti dan yang paling penting, tentukan di mana Employeekelas itu akan berada.

Jika Anda melakukan review kode, maka sangat mudah untuk memastikan bahwa masalahnya setidaknya tidak tumbuh lebih jauh, yaitu menghentikan semua orang tepat di jalur mereka ketika mereka ingin menambahkan Employeelagi. Juga berhati-hatilah agar subsistem baru mematuhi yang disepakati Employeedan tidak diizinkan untuk mengakses versi lama.

Bergantung pada bahasa pemrograman Anda, Anda mungkin juga ingin menandai kelas yang pada akhirnya akan dihilangkan dengan sesuatu seperti @Deprecateduntuk membantu tim Anda segera menyadari bahwa mereka sedang bekerja dengan sesuatu yang harus diubah.

Adapun untuk menyingkirkan kelas karyawan yang sudah ketinggalan zaman, Anda dapat memutuskan untuk setiap kasus bagaimana cara terbaik untuk dihilangkan, atau hanya setuju pada pola umum. Anda dapat menempelkan nama kelas dan membungkusnya dengan karyawan asli, Anda dapat menggunakan pola (penghias atau adaptor datang ke pikiran), atau, atau atau.

Singkatnya: "latihan" ini secara teknis bagus, tetapi tersedak biaya tersembunyi yang hanya akan terjadi di ujung jalan. Meskipun Anda mungkin tidak dapat segera menyingkirkan masalah, Anda dapat segera mulai dengan mengandung efek berbahaya.


Memiliki kelas Core sepertinya solusi yang bagus. Kelas-kelas lain dapat diperluas darinya. Tentang IDE, penyelesaian otomatis cukup cerdas untuk mengetahui kelas mana yang disarankan kepada Anda agar paling cocok dengan konteksnya. Secara keseluruhan, saya tidak melihat mengapa ini merupakan masalah besar terutama jika basis kode digunakan secara internal.
InformedA

1
Ini tidak cukup pintar begitu Anda berada di luar satu konteks. Pertimbangkan kelas, yang sebenarnya membutuhkan kedua kelas bermasalah - pelengkapan otomatis tidak akan membantu sama sekali. Dan itu bahkan tidak akan membedakan ini dari sepuluh kelas lainnya. Tetapi masalah sebenarnya adalah bahwa anggota tim baru, yang bahkan tidak tahu apa sebenarnya semua paket domain itu dan mana yang harus ia pilih.
Frank

Jika beberapa kelas dengan nama yang sama digunakan dalam konteks yang sama, maka itu sulit. Saya belum melihat kasus itu. Saya telah melihat banyak kelas dengan nama yang sama, tetapi mereka tidak sering digunakan dalam konteks yang sama seperti yang Anda sebutkan.
InformedA

@randomA - sayangnya, kasing ini cukup umum di basis kode ini.
Telastyn

Poin yang bagus, tetapi Anda belum benar-benar memberikan solusi untuk masalah inti, hanya metodologi setelah masalah inti diselesaikan ("apa sebenarnya seorang Karyawan"). Satu-satunya "solusi" yang jelas ("mengintegrasikan semua atribut individu ke dalam satu karyawan-dewa") yang Anda buang, memang demikian. Katakanlah Anda memiliki DB.Employee, Marshalling.Employee, ViewModels.Employee, GUI.Views.Employee, dll., Apa solusi Anda?
Pablo H

9

Kerangka Koleksi Scala adalah contoh yang bagus untuk ini. Ada koleksi yang bisa berubah dan tidak dapat diubah serta koleksi serial dan paralel (dan di masa depan mungkin didistribusikan juga). Jadi, ada, misalnya, empat Mapsifat:

scala.collection.Map
scala.collection.immutable.Map
scala.collection.mutable.Map
scala.collection.concurrent.Map

ditambah tiga ParMaps:

scala.collecion.parallel.ParMap
scala.collecion.parallel.immutable.ParMap
scala.collecion.parallel.mutable.ParMap

Yang lebih menarik:

scala.collection.immutable.Map            extends scala.collection.Map
scala.collection.mutable.Map              extends scala.collection.Map
scala.collection.concurrent.Map           extends scala.collection.mutable.Map

scala.collecion.parallel.ParMap           extends scala.collection.Map
scala.collecion.parallel.immutable.ParMap extends scala.collecion.parallel.ParMap
scala.collecion.parallel.mutable.ParMap   extends scala.collecion.parallel.ParMap

Jadi, ParMapmeluas ParMapmeluas Mapdan Mapmeluas Mapmeluas Map.

Tapi, mari kita hadapi itu: apa lagi yang akan Anda menghubungi mereka? Ini masuk akal. Itulah gunanya ruang nama!


3
"Itulah gunanya ruang nama!" => +1
svidgen

Saya suka ini, tetapi di dunia C # /. NET ketika saya memindahkan kelas paralel ke dalam sub-namespace Paralel ini kemudian berbenturan dengan System kelas helper.Threading.Parallel, yang kebetulan saya gunakan dengan berat untuk mendapatkan paralelisme. Saya tidak ingin menggunakan namespace 'Bersamaan' sebagai gantinya karena sudah digunakan berarti 'akses bersamaan' pada kelas koleksi. Sebagai kompromi, saya memilih sub-namespace 'Parallelized'.
redcalx

2

Ini adalah pertanyaan yang sangat menarik di mana kedua jawaban yang pada dasarnya bertentangan keduanya benar. Berikut adalah contoh nyata dari diskusi ini yang kami lakukan pada proyek saya.

Saya pikir ada dua pertimbangan yang sangat menonjol sejauh ini yang akan membuat Anda ingin pergi ke satu arah atau yang lain, mengambil dua jawaban dari @Jorg dan @Frank:

  1. Jika Anda mengantisipasi situasi di mana lebih dari satu kelas dengan nama yang sama mungkin perlu digunakan dalam konteks kode yang sama, ini adalah alasan untuk tidak menggunakan nama yang sama. Artinya, jika Anda perlu bekerja dengan hr.Employeetetapi pada saat yang sama harus melihat izin melalui security.Employee, itu akan sangat cepat menyebalkan menjengkelkan.
  2. Sebaliknya, jika kelas Anda dengan nama yang sama semuanya memiliki API yang sama atau sangat mirip, maka itu adalah contoh yang baik tentang kapan Anda harus menggunakan nama yang sama dengan ruang nama yang berbeda. Contoh Scala adalah persis ini, di mana semua Mapkelas mengimplementasikan antarmuka yang sama atau merupakan subkelas satu sama lain. Dalam hal ini ambiguitas atau "kebingungan" dapat dikatakan sebagai hal yang baik, karena pengguna dapat memperlakukan semua implementasi dari kelas atau antarmuka dengan cara yang sama ... yang merupakan titik antarmuka dan subkelas.
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.