Menggunakan kelas publik bersarang untuk mengatur konstanta

21

Saya sedang mengerjakan aplikasi dengan banyak konstanta. Pada ulasan kode terakhir muncul bahwa konstanta terlalu tersebar dan semua harus diatur dalam satu file konstanta "master". Ketidaksepakatan adalah tentang bagaimana mengatur mereka. Mayoritas merasa bahwa menggunakan nama konstan harus cukup baik, tetapi ini akan mengarah pada kode yang terlihat seperti ini:

public static final String CREDITCARD_ACTION_SUBMITDATA = "6767";
public static final String CREDITCARD_UIFIELDID_CARDHOLDER_NAME = "3959854";
public static final String CREDITCARD_UIFIELDID_EXPIRY_MONTH = "3524";
public static final String CREDITCARD_UIFIELDID_ACCOUNT_ID = "3524";
...
public static final String BANKPAYMENT_UIFIELDID_ACCOUNT_ID = "9987";

Saya menemukan jenis konvensi penamaan ini tidak praktis. Saya pikir mungkin lebih mudah menggunakan kelas bersarang publik, dan memiliki sesuatu seperti ini:

public class IntegrationSystemConstants
{
    public class CreditCard
    {
        public static final String UI_EXPIRY_MONTH = "3524";
        public static final String UI_ACCOUNT_ID = "3524";
        ...
    }
    public class BankAccount
    {
        public static final String UI_ACCOUNT_ID = "9987";
        ...
    }
}

Gagasan ini tidak diterima dengan baik karena "terlalu rumit" (saya tidak mendapatkan banyak detail mengapa ini mungkin terlalu rumit). Saya pikir ini menciptakan pembagian yang lebih baik antara kelompok konstanta terkait dan pelengkapan otomatis membuatnya lebih mudah untuk menemukan ini juga. Saya belum pernah melihat ini dilakukan, jadi saya bertanya-tanya apakah ini adalah praktik yang diterima atau apakah ada alasan yang lebih baik yang seharusnya tidak dilakukan.

FrustratedWithFormsDesigner
sumber
1
Saya lebih suka ide itu. Saya menemukan diri saya melakukan sesuatu yang serupa di C ++ ketika saya ingin C # -style enum-seperti scoping dan perilaku, tetapi dengan nilai-nilai yang bermakna (saya pikir idenya muncul karena saya sudah terbiasa menggunakan kelas kasus di tempat enum di Scala). Memang, ini adalah proyek pribadi untuk bersenang-senang, dan bukan upaya tim.
KChaloux

Jawaban:

13

Saya tidak setuju dengan salah satu dari dua proposal.

Konstanta harus dalam kelas yang bersangkutan , bukan dalam kelas yang serba konstan dalam salah satu dari dua bentuk yang diusulkan.

Seharusnya tidak ada kelas / antarmuka hanya konstanta.

Kelas CreditCard(bukan kelas internal) harus ada. Kelas / antarmuka ini memiliki metode relatif terhadap kartu kredit serta konstanta UI_EXPIRY_MONTHdan UI_ACCOUNT_ID.

Seharusnya ada kelas / antarmuka BankAccount(bukan kelas internal). Kelas / antarmuka ini memiliki metode relatif terhadap rekening bank dan juga konstan UI_ACCOUNT_ID.

Sebagai contoh di Java API setiap kelas / antarmuka memiliki konstanta. Mereka tidak berada dalam kelas / antarmuka Konstanta dengan ratusan konstanta, baik dikelompokkan ke dalam kelas dalam atau tidak.

Sebagai contoh, konstanta-konstanta ini yang berkaitan dengan set hasil ada di antarmuka ResultSet:

static int  CLOSE_CURSORS_AT_COMMIT 
static int  CONCUR_READ_ONLY 
static int  CONCUR_UPDATABLE 
static int  FETCH_FORWARD 
static int  FETCH_REVERSE 
static int  FETCH_UNKNOWN 
static int  HOLD_CURSORS_OVER_COMMIT 
static int  TYPE_FORWARD_ONLY 
static int  TYPE_SCROLL_INSENSITIVE 
static int  TYPE_SCROLL_SENSITIVE 

Antarmuka ini memiliki tanda tangan metode relatif terhadap set hasil, dan kelas implementasi menerapkan perilaku itu. Mereka bukan pemegang konstan belaka.

Konstanta ini terkait dengan tindakan UI ada di antarmuka javax.swing.Action:

static String   ACCELERATOR_KEY 
static String   ACTION_COMMAND_KEY 
static String   DEFAULT 
static String   LONG_DESCRIPTION 
static String   MNEMONIC_KEY 
static String   NAME 
static String   SHORT_DESCRIPTION 
static String   SMALL_ICON 

Kelas implementasi memiliki perilaku relatif terhadap tindakan UI, mereka bukan pemegang konstan.

Saya tahu setidaknya satu antarmuka "konstanta" ( SwingConstants) tanpa metode tetapi tidak memiliki ratusan konstanta, hanya beberapa, dan semuanya terkait dengan arah dan posisi elemen UI:

static int  BOTTOM 
static int  CENTER 
static int  EAST 
static int  HORIZONTAL 
static int  LEADING 
static int  LEFT 
static int  NEXT 
static int  NORTH 
static int  NORTH_EAST 
static int  NORTH_WEST 
static int  PREVIOUS 
static int  RIGHT 
static int  SOUTH 
static int  SOUTH_EAST 
static int  SOUTH_WEST 
static int  TOP 
static int  TRAILING 
static int  VERTICAL 
static int  WEST 

Saya pikir hanya kelas konstanta yang tidak baik desain OO.

Tulains Córdova
sumber
1
Sementara saya setuju bahwa konstanta hanya kelas dalam banyak kasus tanda desain yang buruk, ada kegunaan yang sah. Misalnya, konstanta tidak selalu "milik" kelas tertentu. Kunci untuk ekstra Intent dalam pemrograman Android adalah salah satu contoh nyata.
curioustechizen
1
+1, tetapi konstanta UI mungkin tidak boleh dalam model bisnis seperti BankAccount. Mereka termasuk dalam beberapa kelas UI.
kevin cline
10

muncul bahwa konstanta terlalu tersebar dan semua harus diatur dalam file konstanta "master" tunggal.

Ini adalah solusi 100% salah untuk masalah konstanta "sulit ditemukan". Ini adalah kesalahan mendasar (sayangnya semua terlalu umum dilakukan oleh programmer) untuk mengelompokkan hal-hal berdasarkan kriteria teknis seperti menjadi konstanta, enum atau antarmuka.

Kecuali untuk lapisan arsitektur, hal yang harus digolongkan dengan domain mereka , dan konstanta lebih-lebih karena mereka sangat elemen tingkat rendah. Konstanta harus menjadi bagian dari kelas atau antarmuka yang menggunakannya sebagai bagian dari API mereka. Jika Anda tidak dapat menemukan tempat tinggal alami bagi mereka, Anda perlu membersihkan desain API Anda.

Selain itu, satu file konstanta besar membunuh kecepatan pengembangan di Java karena konstanta digabungkan ke dalam kelas yang menggunakannya pada waktu kompilasi, jadi setiap perubahan memaksa kompilasi ulang semua file tersebut dan semua yang bergantung padanya. Jika Anda memiliki satu file dengan konstanta yang digunakan di mana-mana, Anda sebagian besar kehilangan manfaat kompilasi tambahan: lihat Eclipse mengunci selama 15 menit saat mengkompilasi ulang seluruh proyek Anda untuk setiap perubahan pada file itu. Dan karena file itu mengandung semua konstanta yang digunakan di mana saja, Anda akan sering mengubahnya. Ya, saya berbicara dari pengalaman pribadi.

Michael Borgwardt
sumber
Saya tidak menyadari dampak potensial pada lingkungan pengembangan, dan saya kira pendekatan kelas bersarang tidak akan banyak membantu dengan itu, kan?
FrustratedWithFormsDesigner
1
@FrustratedWithFormsDesigner: Itu tergantung pada berapa banyak upaya yang dihabiskan mekanisme kompilasi inkremental pada dependensi pemodelan.
Michael Borgwardt
9

Kamu benar. Saran Anda memungkinkan seorang programmer untuk import static Constants.BankAccount.*dan menghilangkan pengulangan 'BANKACCOUNT_' yang tak terhitung jumlahnya. Penggabungan adalah pengganti yang buruk untuk pelingkupan yang sebenarnya. Karena itu, saya tidak memiliki banyak harapan bagi Anda untuk mengubah budaya tim. Mereka memiliki gagasan praktik yang tepat, dan tidak mungkin berubah bahkan jika Anda menunjukkan kepada mereka 100 ahli yang mengatakan mereka salah.

Saya juga bertanya-tanya mengapa Anda memiliki satu file 'Konstanta' sama sekali. Ini adalah praktik yang sangat buruk, kecuali jika semua konstanta ini saling terkait dan sangat stabil. Lebih khasnya itu menjadi semacam kelas wastafel dapur yang berubah terus-menerus dan bergantung pada segalanya.

kevin cline
sumber
Saat ini kami memiliki satu file Konstanta yang berisi sebagian besar konstanta ID bidang-UI, dan beberapa file konstanta lainnya yang spesifik untuk sub-proyek. Tapi sekarang, konstanta spesifik-sub proyek perlu digunakan oleh subproyek terkait lainnya sehingga itulah yang mendorong gagasan untuk menggabungkan mereka semua menjadi satu file konstanta "master". Yang lebih baik daripada sekarang karena kadang-kadang saya bahkan tidak tahu file konstanta mana yang dirujuk untuk nilai, dan orang lain membuat duplikat konstanta karena mereka tidak dapat menemukannya dalam file konstanta subproyek yang berbeda.
FrustratedWithFormsDesigner
8
Kelas konstanta yang terus berubah ... ada sesuatu zen di sana, jika kau gali cukup keras.
KChaloux
2
@FrustratedWithFormsDesigner: ID bidang UI? Tidak tahu di mana menemukan nilai? Kedengarannya seperti tumpukan besar WTF. Anda mendapatkan simpati saya.
kevin cline
6

Kedua pendekatan itu berhasil, dan itulah yang penting pada akhirnya.

Yang mengatakan, pendekatan Anda cukup umum untuk dianggap sebagai pola, atau lebih tepatnya peningkatan yang cukup baik atas antarmuka konstan anti-pola. Saya tidak melihat apa yang rumit tentang itu, tetapi itu adalah diskusi yang harus Anda lakukan dengan tim Anda.

yannis
sumber
Untuk daftar konstanta yang cukup panjang, saya bahkan lebih suka antarmuka konstan daripada memiliki mereka semua di kelas yang sama. Sangat mungkin untuk memilih yang salah dari pelengkapan otomatis. Tentu saja, itu tergantung pada berapa lama cukup lama :)
Goran Jovic
1
@ GoranJovic Yah setiap anti-pola berguna dalam beberapa cara (atau setidaknya nyaman), itu tidak akan menjadi pola jika tidak.
yannis
1

Salah satu tantangan dengan daftar panjang konstanta adalah menemukan konstanta "benar" untuk digunakan. Selalu, seseorang mengetuk konstanta di akhir baris alih-alih menambahkannya ke grup miliknya.

Yang memunculkan poin lain untuk dibahas dengan tim Anda - sudah ada kategorisasi de facto konstanta melalui nama mereka. Jadi itu seharusnya tidak menjadi perubahan besar bagi mereka dari keadaan saat ini ke apa yang Anda usulkan. Menggunakan pelengkapan otomatis membuat pencarian konstan lebih mudah.

Jika ada, saran Anda membantu mencegah penggunaan konstanta "salah" meskipun mungkin cocok dalam situasi tertentu. Dengan membungkus konstanta dalam kelas representatif, itu akan mendorong pengembang untuk memikirkan jika mereka harus menggunakannya. Sebagai contoh, jika saya menarik CreditCard.SomeConstantuntuk penggunaan umum, saya benar-benar harus bertanya-tanya mengapa tidak ada General.SomeConstantuntuk situasi itu.

Saya telah mengerjakan proyek dengan jumlah konstanta monster, dan saya lebih suka memiliki metode yang Anda sarankan. Ini lebih bersih, lebih langsung, dan membantu menghindari penggunaan yang tidak disengaja.


sumber
1

Saya melakukan ini sesekali (dalam C #), terutama jika saya perlu memprogram terhadap / parse struktur XML yang terkenal dan diperbaiki atau sesuatu yang sama bersarang dan string yang berat ... misalnya parser blok konfigurasi config kustom.

Saya membangun struktur kelas bersarang yang cocok dengan struktur hierarki XML dengan nama-nama kelas yang sesuai dengan elemen yang berisi properti string string "ElementName" dan properti serupa yang sesuai dengan masing-masing Atribut (jika ada).

Itu membuatnya sangat mudah untuk memprogram terhadap Xml yang sesuai.

Ed Hastings
sumber