Antarmuka Java memperluas pertanyaan

Saya harus mengimplementasikan server RMI yang akan menjadi ujung depan untuk dua layanan RMI lainnya. Jadi saya memutuskan hal yang logis untuk dilakukan adalah membuat antarmuka untuk mengimplementasikan antarmuka untuk dua layanan lainnya.

public interface FrontEndServer extends Remote, BookServer, StudentServer
{
    // Block empty so far
}

Namun ada metode di StudentServer

/**
 * Allows a student to borrow a book
 * 
 * @param studentID of the student who wishes to borrow a book
 * @param bookID of the book the student wishes to borrow
 * @throws RemoteException
 * @throws StudentNotFoundException when a student is not found in the system
 */
void addBookToStudent(int studentID, int bookID) throws RemoteException, StudentNotFoundException;

Saya ingin FrontEndServer juga memberikan BookNotFoundException karena layanan ini juga akan memvalidasi apakah buku tersebut benar-benar ada sebelum mencoba menambahkan detailnya.

Apakah ini mungkin atau ide desain saya benar-benar hilang dan ini sebenarnya ide desain yang buruk seolah-olah antarmuka lain berubah dan sebagainya? Dan apakah saya akan lebih baik menulis tanda tangan metode untuk semua metode di dalam FrontEndServer?


person Malachi    schedule 05.03.2009    source sumber


Jawaban (6)


Jika Anda memperluas sebuah antarmuka (hal yang sama juga berlaku jika Anda mengimplementasikan sebuah antarmuka), Anda tidak dapat mengganti suatu metode dan membuatnya mengeluarkan lebih pengecualian yang dicentang daripada metode aslinya. Anda bisa melemparnya sama atau kurang tetapi tidak lebih.

Pikirkan tentang itu:

interface A {
  void foo();
}

interface B extends A {
  void foo() throws IOException;
}

A a = new B() { ... }
a.foo();

berpotensi memunculkan IOException tetapi Anda tidak akan tahu. Itu sebabnya kamu tidak bisa melakukannya.

Hal ini tentu saja dapat diterima:

interface A {
  void foo() throws IOException;
}

interface B extends A {
  void foo();
}

A a = new B() { ... }
try {
    a.foo();
} catch (IOException e) {
    // must catch even though B.foo() won't throw one
}

Namun BookNotFoundException Anda dapat memperpanjang RuntimeException atau RemoteException. Namun tidak yakin itu pendekatan yang baik.

person cletus    schedule 05.03.2009
comment
Terima kasih - Sepertinya saya hanya akan menerapkan metode di FrontEndServer - Saya rasa masuk akal untuk bersikap adil. - person Malachi; 06.03.2009
comment
meskipun jika Anda ingin mendefinisikan pengecualian buku Anda tidak ditemukan sebagai jenis RuntimeException maka Anda dapat membuangnya tanpa mendeklarasikannya. Tapi itu jahat. - person Guss; 06.03.2009

Apa gunanya satu tipe yang memperluas kedua antarmuka ini? Apakah Anda kehilangan sesuatu ketika klien bergantung pada dua objek berbeda?

Penggunaan pewarisan yang berlebihan adalah kesalahan umum yang dilakukan pemula, karena "warisan" adalah salah satu ciri penting dari pemrograman berorientasi objek. Namun, dalam banyak kasus, komposisi adalah pilihan yang lebih baik. Dalam hal ini, mengapa tidak memiliki dua layanan terpisah? Lalu, menambahkan CafeteriaService dan DormitoryService nanti tidak memengaruhi antarmuka yang ada.

Berkenaan dengan desain, metode addBookToStudent akan mendapatkan keuntungan karena dapat melempar BookNotFoundException. Antarmukanya rapuh, dalam artian mengubahnya dengan cara apa pun akan merusak banyak kode. Anda harus sangat berhati-hati dalam desain awalnya. Misalnya, BookNotFoundException mungkin terlalu spesifik; tidak bisakah ada berbagai pengecualian yang mencegah "menambahkan" buku ke siswa? (Saya menduga siswa sedang memeriksa buku dari perpustakaan peminjaman.) Misalnya: CheckOutLimitExceededException, UnpaidFinePendingException, AdultLiteraturePermissionException, dll.

Pikirkan baik-baik tentang jenis pengecualian yang dicentang yang mungkin sesuai untuk tingkat abstraksi saat mendesain antarmuka, karena nanti sulit diubah.

person erickson    schedule 05.03.2009

Beberapa ide untuk Anda:

  1. Deklarasikan metode addBookToStudent di antarmuka untuk menampilkan BookNotFoundException. Meskipun StudentServer mungkin tidak pernah benar-benar mengeluarkan pengecualian, itu tidak berarti Anda tidak dapat memasukkannya ke dalam antarmuka.

  2. Anda dapat membuat pengecualian baru - ObjectNotFoundException dan mewarisi BookNotFoundException dan StudentNotFoundException dari sana, lalu mendeklarasikan addBookToStudent untuk melempar ObjectNotFoundException.

  3. Apa yang mungkin akan saya lakukan dalam "kehidupan nyata" - minta StudentServer berbicara dengan BookServer untuk memvalidasi id buku dan memberikan pengecualian itu sendiri, daripada melakukan pemeriksaan itu di FrontEndServer. Terutama jika StudentServer sebenarnya digunakan langsung oleh apa pun selain FrontEndServer.

person Eric Petroelje    schedule 05.03.2009

Saya menyarankan Anda mencoba memisahkan API yang terekspos dari API yang digunakan untuk mengimplementasikan fungsi Anda. Dugaan saya adalah tujuan front end layanan RMI adalah untuk memberikan pemisahan dan stabilitas dari aplikasi panggilan.

Dengan itu saya menyarankan Anda:

  • Tulis API yang ingin Anda ekspos
  • Tulis implementasi yang menjembatani antara API Anda dan layanan back-end
person Kam    schedule 05.03.2009

Secara teori dimungkinkan jika BookNotFoundException memperluas RemoteExcepiton.

Namun, saya berasumsi Anda tidak memiliki kendali atas antarmuka StudentServer. Tampaknya maksud dari antarmuka itu adalah untuk tidak memunculkan BookNotFoundException. Meskipun saya dapat memahami mengapa Anda menginginkannya, antarmuka tampaknya tidak mendorong hal itu.

person Rob Di Marco    schedule 05.03.2009

Pengecualian diberikan oleh metode, bukan antarmuka atau kelas. Jadi, jika ada metode di antarmuka BookServer, hal itu dapat memberi Anda pengecualian saat Anda menambahkannya ke antarmuka.

Jika Anda berpikir untuk menambahkan pengecualian pada metode addBookToStudent di antarmuka FrontEndServer, jawabannya adalah tidak, itu tidak mungkin. Metode yang diganti di kelas dan antarmuka hanya dapat mempersempit pengecualian atau menghapusnya sepenuhnya tetapi tidak menambah pengecualian baru.

Jika Anda memikirkannya, Anda melihat bahwa ini logis. FrontEndServer Anda dapat digunakan sebagai Server Buku dengan beberapa kode. Kode selama kompilasi mengharapkan pengecualian yang ditentukan di BookServer. Kemudian saat runtime tiba-tiba sebuah pengecualian dilemparkan oleh BookServer yang tidak ditentukan dalam antarmuka BookServer. Jika potongan kode tersebut hanya mengetahui bahwa BookException tidak terduga, tidak ada pernyataan catch atau throw untuk menanganinya.

person DefLog    schedule 05.03.2009