Apa itu invarian kelas di java?

94

Saya mencari topik tersebut di Google, tetapi selain Wikipedia, saya tidak menemukan dokumentasi atau artikel berguna lainnya.

Adakah yang bisa menjelaskan kepada saya dengan kata-kata sederhana apa artinya atau merujuk saya ke beberapa dokumentasi yang bagus dan mudah dimengerti?

Saurabh Kumar
sumber
2
+1 untuk pertanyaan karena halaman Wikipedia memiliki contoh yang sangat bagus tentang sesuatu yang saya tidak tahu dapat Anda lakukan - bahkan memiliki contoh. Penjelasan mereka lebih baik daripada yang bisa saya lakukan untuk Anda; itu cukup mudah.
iandisme
Jika Anda tertarik dengan invariants wrt Java, mungkin Anda akan tertarik dengan kontrak untuk Java .
Mike Samuel
1
Penjelasan yang lebih sederhana - < stackoverflow.com/questions/112064/what-is-an-invariant?rq=1 >
ip_x

Jawaban:

93

Ini tidak berarti apa-apa secara khusus terkait dengan java.

Sebuah invarian kelas hanyalah properti yang menampung semua instance kelas, selalu, apa pun yang dilakukan kode lain.

Sebagai contoh,

class X {
  final Y y = new Y();
}

X memiliki kelas invarian bahwa ada yproperti dan tidak pernah nulldan memiliki nilai tipe Y.

class Counter {
  private int x;

  public int count() { return x++; }
}

gagal mempertahankan dua invarian penting

  1. Itu counttidak pernah mengembalikan nilai negatif karena kemungkinan aliran bawah.
  2. Panggilan countitu meningkat secara monoton.

Kelas yang dimodifikasi mempertahankan kedua invarian tersebut.

class Counter {
  private int x;

  public synchronized int count() {
    if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); }
    return x++;
  }
}

tetapi gagal untuk mempertahankan invarian yang memanggil untuk countselalu berhasil secara normal (tidak ada pelanggaran TCB ) karena countdapat memunculkan pengecualian atau mungkin memblokir jika thread yang mengalami kebuntuan memiliki monitor penghitung.

Setiap bahasa dengan kelas memudahkan untuk mempertahankan beberapa kelas invarian tetapi tidak yang lain. Java tidak terkecuali:

  1. Kelas Java secara konsisten memiliki atau tidak memiliki properti dan metode, sehingga invarian antarmuka mudah dipelihara.
  2. Kelas Java dapat melindungi privatekolomnya, sehingga invarian yang mengandalkan data pribadi mudah dikelola.
  3. Kelas Java bisa bersifat final, sehingga invarian yang bergantung pada tidak adanya kode yang melanggar invarian dengan membuat subkelas berbahaya dapat dipertahankan.
  4. Java memungkinkan nullnilai-nilai menyelinap dalam banyak cara, jadi sulit untuk mempertahankan invarian "memiliki nilai nyata".
  5. Java memiliki utas yang berarti bahwa kelas yang tidak disinkronkan mengalami masalah dalam mempertahankan invarian yang bergantung pada operasi sekuensial dalam utas yang terjadi bersamaan.
  6. Java memiliki pengecualian yang membuatnya mudah untuk mempertahankan invarian seperti "mengembalikan hasil dengan properti p atau tidak mengembalikan hasil" tetapi lebih sulit untuk mempertahankan invarian seperti "selalu mengembalikan hasil".

† - Pelanggaran eksternalitas atau TCB adalah peristiwa yang diasumsikan oleh perancang sistem secara optimis tidak akan terjadi.

Biasanya kami hanya percaya bahwa perangkat keras dasar berfungsi seperti yang diiklankan ketika berbicara tentang properti bahasa tingkat tinggi yang dibangun di atasnya, dan argumen kami yang dipegang oleh invarian tidak memperhitungkan kemungkinan:

  • Seorang programmer menggunakan kait debug untuk mengubah variabel lokal karena program berjalan dengan cara yang tidak bisa dilakukan oleh kode.
  • Rekan Anda tidak menggunakan refleksi dengan setAccessibleuntuk mengubah privatetabel pencarian.
  • Loki mengubah fisika menyebabkan prosesor Anda salah membandingkan dua angka.

Untuk beberapa sistem, TCB kami mungkin hanya menyertakan beberapa bagian dari sistem, jadi kami mungkin tidak berasumsi demikian

  • Administrator atau daemon dengan hak istimewa tidak akan menghentikan proses JVM kami,

tapi kita mungkin berasumsi seperti itu

  • Kami dapat memeriksa ke sistem file transaksi yang andal.

Semakin tinggi level suatu sistem, semakin besar TCB-nya, tetapi semakin tidak dapat diandalkan hal-hal yang dapat Anda keluarkan dari TCB, semakin besar kemungkinan invarian Anda ditahan, dan semakin andal sistem Anda dalam jangka panjang.

Mike Samuel
sumber
2
Apakah "yang counttidak pernah mengembalikan nilai yang sama dua kali" benar-benar dianggap sebagai invarian kelas?
ruakh
1
@ruakh, itu pertanyaan yang bagus. Saya tidak begitu yakin. Hal-hal seperti stabilitas kode hash (untuk setiap contoh i, i.hashCode () tidak berubah) sering disebut invarian kelas yang memerlukan alasan tentang nilai yang dikembalikan sebelumnya, jadi tampaknya masuk akal untuk mengatakan bahwa "untuk setiap contoh i, i.count () tidak dalam (hasil sebelumnya dari i.count ()) "adalah invarian kelas.
Mike Samuel
@ruakh Bukankah itu hal definisi murni? Jika saya mendalilkan seperti itu, mengapa tidak? Ini tentu bisa menjadi jaminan yang menarik dan penting (katakanlah untuk menghasilkan ID unik). Secara pribadi saya juga berpikir sesuatu seperti "jika hanya kode berulir tunggal yang mengakses kelas ini, properti berikut akan ditahan" berguna, tetapi saya tidak yakin apakah mungkin untuk memperluas definisi sedemikian rupa sehingga hanya harus menahan sementara tertentu kondisi benar. (Dan mempertimbangkan refleksi pada dasarnya tidak mungkin untuk menjamin sesuatu yang menarik sebaliknya!)
Voo
1
@ruakh - Anda dapat memodelkannya sebagai invarian kelas atau metode invarian. Apa pun itu, pemodelannya memerlukan riwayat konseptual panggilan sebelumnya ke metode pada objek tertentu. Sebenarnya, Anda bahkan dapat membuat model ini sebagai kondisi pasca pada metode; yaitu bahwa nilai hasil adalah nilai yang belum dikembalikan sebelumnya.
Stephen C
@Voo: Re: "Bukankah itu definisi murni?": Tentu saja, tapi karena pertanyaannya di sini adalah, "Apa itu 'class invariant'?", Saya pikir definisi tersebut 100% relevan. Tampaknya lebih disukai, sejauh mungkin, menggunakan contoh-contoh yang jelas, atau secara eksplisit menyebutkan kasus-kasus yang tidak jelas. (Ngomong-ngomong, saya tidak secara aktif tidak setuju dengan contoh itu; saya hanya terkejut olehnya, dan bertanya untuk memastikan.)
ruakh
21

Invariant berarti sesuatu yang harus tetap pada kondisinya tidak peduli apapun perubahannya atau siapapun yang menggunakan / mengubahnya. Artinya, properti kelas selalu memenuhi atau memenuhi beberapa kondisi bahkan setelah melalui transformasi dengan menggunakan metode publik. Jadi, klien atau pengguna kelas ini dipastikan tentang kelas dan propertinya.

Sebagai contoh,

  1. kondisi pada argumen fungsi adalah, itu harus selalu> 0 (lebih besar dari nol) atau tidak boleh nol.
  2. minimum_account_balance properti dari sebuah kelas akun menyatakan, tidak bisa di bawah 100. Jadi semua fungsi publik harus menghormati kondisi ini dan memastikan kelas invarian.
  3. ketergantungan berbasis aturan antar variabel, yaitu, nilai satu variabel bergantung pada variabel lain, jadi jika satu berubah, menggunakan beberapa aturan tetap, yang lain juga harus berubah. Hubungan antara 2 variabel ini harus dipertahankan. Jika tidak, maka invariant dilanggar.
aab10
sumber
11

Itu adalah fakta yang harus benar tentang kelas instance. Misalnya jika sebuah kelas memiliki properti X dan invarian dapat X harus lebih besar dari 0. Sepengetahuan saya tidak ada metode bawaan untuk mempertahankan invarian, Anda harus membuat properti menjadi pribadi dan memastikan pengambil dan penyetel Anda menerapkan properti invarian.

Ada anotasi yang tersedia yang dapat memeriksa properti menggunakan refleksi dan interseptor. http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

Usman Ismail
sumber