Java 8 menambahkan konsep antarmuka fungsional , serta berbagai metode baru yang dirancang untuk mengambil antarmuka fungsional. Contoh dari antarmuka ini dapat dibuat secara ringkas menggunakan ekspresi referensi metode (misalnya SomeClass::someMethod
) dan ekspresi lambda (misalnya (x, y) -> x + y
).
Seorang kolega dan saya memiliki pendapat yang berbeda mengenai kapan sebaiknya menggunakan satu bentuk atau yang lain (di mana "terbaik" dalam hal ini benar-benar bermuara pada "yang paling mudah dibaca" dan "paling sesuai dengan praktik standar", karena pada dasarnya mereka sebaliknya setara). Secara khusus, ini melibatkan kasus di mana yang berikut ini benar:
- fungsi yang dimaksud tidak digunakan di luar cakupan tunggal
- memberi contoh nama membantu keterbacaan (sebagai lawan dari misalnya logika cukup sederhana untuk melihat apa yang terjadi sekilas)
- tidak ada alasan pemrograman lain mengapa satu formulir lebih disukai dari yang lain.
Pendapat saya saat ini tentang masalah ini adalah menambahkan metode pribadi, dan merujuknya dengan referensi metode, adalah pendekatan yang lebih baik. Rasanya seperti ini bagaimana fitur dirancang untuk digunakan, dan tampaknya lebih mudah untuk mengkomunikasikan apa yang terjadi melalui nama metode dan tanda tangan (misalnya "boolean isResultInFuture (hasil hasil)" jelas mengatakan itu mengembalikan boolean). Ini juga membuat metode pribadi lebih dapat digunakan kembali jika peningkatan masa depan ke kelas ingin menggunakan pemeriksaan yang sama, tetapi tidak memerlukan pembungkus antarmuka fungsional.
Preferensi kolega saya adalah memiliki metode yang mengembalikan instance antarmuka (mis. "Predicate resultInFuture ()"). Bagi saya, ini rasanya bukan bagaimana fitur itu dimaksudkan untuk digunakan, terasa agak clunkier, dan sepertinya lebih sulit untuk benar-benar mengomunikasikan maksud melalui penamaan.
Untuk membuat contoh ini konkret, berikut adalah kode yang sama, ditulis dalam gaya yang berbeda:
public class ResultProcessor {
public void doSomethingImportant(List<Result> results) {
results.filter(this::isResultInFuture).forEach({ result ->
// Do something important with each future result line
});
}
private boolean isResultInFuture(Result result) {
someOtherService.getResultDateFromDatabase(result).after(new Date());
}
}
vs.
public class ResultProcessor {
public void doSomethingImportant(List<Result> results) {
results.filter(resultInFuture()).forEach({ result ->
// Do something important with each future result line
});
}
private Predicate<Result> resultInFuture() {
return result -> someOtherService.getResultDateFromDatabase(result).after(new Date());
}
}
vs.
public class ResultProcessor {
public void doSomethingImportant(List<Result> results) {
Predicate<Result> resultInFuture = result -> someOtherService.getResultDateFromDatabase(result).after(new Date());
results.filter(resultInFuture).forEach({ result ->
// Do something important with each future result line
});
}
}
Apakah ada dokumentasi atau komentar resmi atau semi-resmi tentang apakah satu pendekatan lebih disukai, lebih sesuai dengan maksud perancang bahasa, atau lebih mudah dibaca? Kecuali sumber resmi, apakah ada alasan yang jelas mengapa seseorang menjadi pendekatan yang lebih baik?
Object::toString
). Jadi pertanyaan saya lebih tentang apakah lebih baik dalam jenis contoh khusus yang saya paparkan di sini, daripada apakah ada contoh di mana satu lebih baik dari yang lain, atau sebaliknya.