Konvensi penamaan parameter tipe generik untuk Java (dengan banyak karakter)?

125

Di beberapa antarmuka saya menulis, saya ingin memberi nama parameter tipe generik dengan lebih dari satu karakter agar kode lebih mudah dibaca.

Sesuatu seperti....

Map<Key,Value>

Daripada ini ...

Map<K,V>

Tetapi ketika datang ke metode, tipe-parameter terlihat seperti kelas-java yang juga membingungkan.

public void put(Key key, Value value)

Sepertinya Kunci dan Nilai adalah kelas. Saya menemukan atau memikirkan beberapa notasi, tetapi tidak ada yang seperti konvensi dari Sun atau praktik terbaik umum.

Alternatif yang saya tebak atau temukan ...

Map<KEY,VALUE>
Map<TKey,TValue>
pengawal29
sumber
9
Mengapa Anda ingin membuat konvensi baru?
Amir Afghani
13
@AmirAfghani Dari pertanyaan: membuat kode lebih mudah dibaca.
SantiBailors
Secara teknis, perbedaan warna obat generik di IDE seharusnya berfungsi sebagai indikator yang cukup baik
Sudix

Jawaban:

182

Oracle merekomendasikan yang berikut ini di Tutorial Java> Generik> Jenis Generik :

Ketik Konvensi Penamaan Parameter

Menurut konvensi, nama parameter tipe adalah tunggal, huruf besar. Ini sangat kontras dengan konvensi penamaan variabel yang sudah Anda ketahui, dan dengan alasan yang bagus: Tanpa konvensi ini, akan sulit untuk membedakan antara variabel tipe dan kelas biasa atau nama antarmuka.

Nama parameter tipe yang paling umum digunakan adalah:

  • E - Element (digunakan secara ekstensif oleh Java Collections Framework)
  • K - Kunci
  • N - Nomor
  • T - Type
  • V - Nilai
  • S, U, V dll. - Tipe ke-2, ke-3, ke-4

Anda akan melihat nama-nama ini digunakan di seluruh Java SE API dan sisa pelajaran ini.

Saya akan tetap menggunakannya untuk menghindari kebingungan di antara para pengembang dan pengelola yang mungkin.

BalusC
sumber
14
Framework streaming baru juga digunakan Runtuk result dan Auntuk akumulator.
vandale
32
Blech, penamaan satu huruf. Saya mengikuti konvensi ini karena konvensi lebih penting daripada nama deskriptif, tapi sayangnya ini adalah yang terbaik yang bisa mereka hasilkan.
warbaker
4
@warbaker: Menurut saya ini cara yang baik untuk membedakan tipe berparameter dari kelas yang sebenarnya. Bagaimana Anda mengetahui jika misalnya Elementin List<Element>adalah tipe berparameter atau kelas?
BalusC
1
Sepertinya tidak BiFunction<T, U, R>mengikuti konvensi ini. Jika ya, itu akan terjadi BiFunction<T, S, R>.
michaelsnowden
4
Mengapa khawatir tentang membedakan tipe berparameter dari kelas yang sebenarnya? Mereka adalah kelas. Apa pun yang terjadi, Anda harus menggulir ke atas di suatu tempat di file untuk mengetahui apa yang mereka definisikan. Dan itu akan menjadi impor atau tipe berparameter.
Vectorjohn
47

Menambahkan Type

Diskusi yang bagus dapat ditemukan di komentar di halaman DZone, Penamaan Konvensi untuk Jenis Parameter .

Lihat komentar oleh Erwin Mueller. Sarannya sangat masuk akal bagi saya: Tambahkan kataType .

Sebut apel sebagai apel, mobil itu mobil. Nama yang dimaksud adalah nama dari suatu tipe data, bukan? (Dalam OOP , kelas pada dasarnya mendefinisikan tipe data baru.) Jadi, sebut saja "Jenis".

Contoh Mueller, diambil dari artikel postingan asli:

public interface ResourceAccessor < ResourceType , ArgumentType , ResultType > {
    public ResultType run ( ResourceType resource , ArgumentType argument );
}

Menambahkan T

Sebuah Pertanyaan duplikat memberikan Jawaban ini oleh Andy Thomas. Perhatikan kutipan dari panduan gaya Google yang menyarankan nama tipe multi-karakter harus diakhiri dengan satu huruf besar T.

Basil Bourque
sumber
3
Saya suka jawaban ini. Menambahkan "Jenis" begitu jelas dan memungkinkan Anda memiliki nama deskriptif. Saya muak dengan orang-orang yang mengatakan, "lakukan karena itu konvensi," tanpa alasan lain. Jika itu konvensi yang buruk, mungkin kita perlu yang baru.
Drew
16

Alasan konvensi penamaan resmi merekomendasikan penggunaan satu huruf adalah sebagai berikut:

Tanpa konvensi ini, akan sulit untuk membedakan antara variabel tipe dan kelas biasa atau nama antarmuka.

Saya pikir dengan IDE modern alasan itu tidak lagi valid sebagai mis. Ide IntelliJ menunjukkan parameter tipe generik dengan warna berbeda dari kelas biasa.

Kode dengan tipe generik seperti yang ditampilkan di IntelliJ Idea 2016.1 Kode dengan tipe generik seperti yang ditampilkan di IntelliJ Idea 2016.1

Karena perbedaan itu saya menggunakan nama deskriptif yang lebih panjang untuk tipe generik saya, dengan konvensi yang sama seperti tipe biasa. Saya menghindari menambahkan prefiks dan sufiks seperti T atau Type karena saya menganggapnya sebagai noise yang tidak perlu dan tidak lagi diperlukan untuk membedakan tipe generik secara visual.

Catatan: Karena saya bukan pengguna Eclipse atau Netbeans, saya tidak tahu apakah mereka menawarkan fitur serupa.

Vojtech Ruzicka
sumber
Saya tidak akan mendasarkan konvensi penamaan di sekitar kemampuan yang diasumsikan dari alat yang dimiliki setiap orang yang pernah membaca / memodifikasi file yang sama. Saya pribadi suka menggunakan editor teks untuk pengkodean saya (Sublime Text) yang bukan IDE. Editor teks biasanya saat ini memiliki pewarnaan sintaks, tetapi tidak memiliki pemahaman yang mendalam tentang struktur kode yang mendasarinya yang menurut saya akan diperlukan untuk mewarnai nama variabel dengan benar. Dan mendasarkan argumen ini pada warna secara inheren eksklusif untuk orang dengan penglihatan warna yang buruk (saya adalah bagian dari 8% laki-laki dengan buta warna merah-hijau)
joonas.fi
1
Poin bagus tentang orang dengan penglihatan warna yang buruk. Mengenai tidak menggunakan IDE - jika orang lebih suka menggunakan editor teks sederhana, itu baik-baik saja, tetapi mereka secara sukarela mengorbankan fitur yang ditawarkan IDE kepada mereka demi alat yang lebih ringan. Ini mungkin hanya salah satu fitur yang hilang. Namun pada akhirnya, jika nama deskriptif digunakan alih-alih satu huruf, Anda harus dapat mengetahui artinya berdasarkan nama tanpa IDE dan tanpa kode warna. Pengodean warna membuat ini lebih cepat.
Vojtech Ruzicka
16

Ya, Anda dapat menggunakan nama multi-karakter untuk variabel tipe, asalkan dibedakan dengan jelas dari nama kelas.

Ini berbeda dari konvensi yang disarankan oleh Sun dengan diperkenalkannya obat generik pada tahun 2004. Namun:

  • Ada lebih dari satu konvensi.
  • Nama multi-karakter konsisten dengan gaya Java lainnya, seperti gaya Google untuk Java .
  • Nama-nama yang dapat dibaca (kejutan!) Lebih mudah dibaca.

Keterbacaan

Dalam beberapa antarmuka saya menulis, saya ingin memberi nama parameter tipe generik dengan lebih dari satu karakter agar kode lebih mudah dibaca.

Keterbacaan itu bagus.

Membandingkan:

    public final class EventProducer<L extends IEventListener<E>,E> 
            implements IEventProducer<L,E> {

untuk:

    public final class EventProducer<LISTENER extends IEventListener<EVENT>,EVENT> 
           implements IEventProducer<LISTENER, EVENT> {

atau, dengan konvensi multi-karakter Google:

    public final class EventProducer<ListenerT extends IEventListener<EventT>,EventT> 
           implements IEventProducer<ListenerT, EventT> {

    public final class EventProducer<ListenerT extends IEventListener<EventT>,EventT> 
           implements IEventProducer<ListenerT, EventT> {

Gaya Google

The Google Java Style Guide memungkinkan kedua nama huruf tunggal dan multi-karakter kelas-seperti nama yang diakhiri dengan T.

5.2.8 Ketikkan nama variabel

Setiap jenis variabel diberi nama dalam salah satu dari dua gaya:

  • Sebuah huruf kapital tunggal, opsional diikuti dengan angka tunggal (seperti E, T, X, T2)

  • Sebuah nama dalam bentuk digunakan untuk kelas (lihat Bagian 5.2.2, nama-nama kelas ), diikuti oleh huruf T (contoh: RequestT, FooBarT).

Masalah

“Tanpa konvensi ini, akan sulit untuk membedakan antara variabel tipe dan kelas biasa atau nama antarmuka.” - dari tutorial Oracle, "Jenis umum"

Nama karakter tunggal bukanlah satu-satunya cara untuk membedakan parameter tipe dari nama kelas, seperti yang telah kita lihat di atas.

Mengapa tidak mendokumentasikan arti parameter type di JavaDoc?

Memang benar @paramelemen JavaDoc dapat memberikan deskripsi yang lebih panjang. Tetapi juga benar bahwa JavaDocs belum tentu terlihat. (Misalnya, ada bantuan konten di Eclipse yang menunjukkan nama parameter tipe.)

Nama parameter tipe multi-karakter tidak mengikuti konvensi Oracle!

Banyak konvensi asli Sun diikuti hampir secara universal dalam pemrograman Java.

Namun, konvensi khusus ini tidak.

Pilihan terbaik di antara konvensi yang bersaing adalah masalah opini. Konsekuensi memilih konvensi selain Oracle dalam kasus ini kecil. Anda dan tim Anda dapat memilih konvensi yang paling sesuai dengan kebutuhan Anda.

Andy Thomas
sumber
15

Anda dapat menggunakan javadoc untuk setidaknya memberi petunjuk kepada pengguna kelas generik Anda. Saya masih tidak menyukainya (saya setuju dengan @ chaper29) tetapi dokumen membantu.

misalnya,

/**
 * 
 * @param <R> - row
 * @param <C> - column
 * @param <E> - cell element
 */
public class GenericTable<R, C, E> {

}

Hal lain yang pernah saya lakukan adalah menggunakan IDE saya untuk memfaktor ulang kelas yang melanggar konvensi. Kemudian kerjakan kode dan lakukan refaktorisasi kembali ke huruf tunggal. Mempermudah saya juga jika banyak parameter tipe digunakan.

Tom Carchrae
sumber
1
Saya akan mengatakan komentar Javadoc untuk parameter tipe biasanya suatu keharusan.
migu