Apakah cara memanggil fungsi ini merupakan praktik yang buruk?

10

Saya memiliki kode berikut:

public void moveCameraTo(Location location){
    moveCameraTo(location.getLatitude(), location.getLongitude());
}

public void moveCameraTo(double latitude, double longitude){
    LatLng latLng = new LatLng(latitude, longitude);
    moveCameraTo(latLng);
}

public void moveCameraTo(LatLng latLng){
    GoogleMap googleMap =  getGoogleMap();
    cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, INITIAL_MAP_ZOOM_LEVEL);
    googleMap.moveCamera(cameraUpdate);
}

Saya berpikir bahwa dengan cara ini saya menghilangkan tanggung jawab untuk mengetahui apa yang ada LatLngdi kelas lain, misalnya.

Dan Anda tidak perlu menyiapkan data sebelum memanggil fungsi.

Bagaimana menurut anda?

Apakah pendekatan ini memiliki nama? Apakah ini benar-benar praktik yang buruk?

Tlaloc-ES
sumber
2
Saya pikir Anda hanya berurusan dengan Enkapsulasi menggunakan Metode Overloading bawaan bahasa. Itu tidak baik / buruk. Hanya alat yang dapat membantu atau melukai kode Anda.
bitsoflogic
5
Jika tujuan Anda adalah menyembunyikan LatLngdari klien Camerakelas ini , maka Anda mungkin tidak ingin moveCameraTo(LatLng)menjadi public.
bitsoflogic
Selain saran yang diberikan dalam jawaban, ini terasa seperti tempat yang bagus untuk menyebut YAGNI. Anda Tidak Akan Membutuhkannya. Jangan mendefinisikan metode API sebelum ada kasus penggunaan yang baik karena ... Anda Tidak Akan Membutuhkannya.
Patrick Hughes
Tidak ada yang salah dengan moveCameraToLocationdan moveCameraTo/ moveCameraToCoords. Pasti tidak ingin melewati Lokasi / lat / long semua dengan nama yang sama.
Di dalam

Jawaban:

9

Anda menggunakan fitur kelebihan metode bahasa untuk menawarkan cara alternatif penelepon untuk menyelesaikan ketergantungan metode pada informasi posisi. Anda kemudian mendelegasikan ke metode lain untuk menyelesaikan pekerjaan memperbarui kamera yang tersisa.

Aroma kode di sini adalah jika Anda terus memperluas rangkaian metode memanggil metode. Metode pengambilan lokasi memanggil metode pengambilan ganda yang memanggil metode pengambilan latLng yang akhirnya memanggil sesuatu yang tahu cara memperbarui kamera.

Rantai panjang hanya sekuat rantai terlemah mereka. Setiap ekstensi rantai meningkatkan jejak kode yang harus bekerja atau hal ini rusak.

Ini adalah desain yang jauh lebih baik jika setiap metode mengambil jalan sesingkat mungkin untuk menyelesaikan masalah yang telah disajikan kepadanya. Itu tidak berarti masing-masing harus tahu cara memperbarui kamera. Masing-masing harus menerjemahkan jenis parameter posisi mereka ke satu jenis seragam yang dapat diteruskan ke sesuatu yang tidak tahu cara memperbarui kamera ketika disajikan jenis yang satu ini.

Lakukan seperti itu dan Anda dapat menghapus satu tanpa merusak setengah dari yang lainnya.

Mempertimbangkan:

public void moveCameraTo(Location location){
    moveCameraTo( new LatLng(location) );
}

Ini membuat berurusan dengan masalah garis lintang dan bujur LatLng. Biaya penyebarannya adalah pengetahuan LatLngsekitar. Itu mungkin tampak mahal tetapi dalam pengalaman saya itu adalah alternatif yang lebih disukai daripada obsesi primitif yang adalah apa yang menghindari membangun objek parameter membuat Anda terjebak.

Jika Locationdapat dilakukan kembali tetapi LatLngtidak, pertimbangkan untuk menyelesaikan ini dengan menambahkan pabrik ke Location:

moveCameraTo( location.ToLatLng() );

Ini juga menghindari obsesi primitif.

candied_orange
sumber
1
Sepertinya tidak buruk bagi saya - itu benar-benar hanya kenyamanan bagi konsumen. Jika ini dirantai 10 kali atau jika konsumen tidak benar-benar membutuhkan semua opsi ini maka saya akan menyebutnya bau kode.
mcknz
1
Tapi apa alternatifnya meletakkan semua logika untuk mentransformasikan ganda ke LagLng atau Lokasi ke LagLng di setiap fungsi?
Tlaloc-ES
@ Tlaloc-ES lebih baik?
candied_orange
@ Tlaloc-ES "Transformasi" hanya perlu terjadi sekali ketika primitif sedang dimuat ke dalam logika domain. Itu akan terjadi ketika Anda membatalkan deserialisasi DTO. Kemudian, semua logika domain Anda dapat diedarkan LatLngatau Locationobjek. Anda dapat menunjukkan hubungan antara keduanya dengan New LatLng(Location)atau Location.toLatLng()jika Anda harus beralih dari satu ke yang lain.
bitsoflogic
1
@ Tlaloc-ES Bacaan terkait: FlagArgument oleh Martin Fowler. Baca bagian "Implementasi Kusut".
Marc.2377
8

Tidak ada yang salah dengan solusi Anda.

Tetapi preferensi pribadi saya adalah bahwa metode-metode itu tidak berguna. Dan hanya menyulitkan antarmuka objek apa pun yang menjadi bagiannya.

Tidak void moveCameraTo(double latitude, double longitude)benar-benar menyederhanakan kode, karena saya tidak melihat masalah hanya memanggil moveCameraTo(new LatLng(latitude, longitude));tempat itu. Metode ini juga berbau obsesi primitif.

Itu void moveCameraTo(Location location)bisa lebih baik diselesaikan dengan membuktikan Location.ToLatLng()metode dan panggilan moveCameraTo(location.ToLatLng()).

jika ini adalah C # dan jika metode seperti itu benar-benar diperlukan, saya lebih suka mereka sebagai metode ekstensi daripada metode contoh. Penggunaan metode ekstensi akan menjadi sangat jelas jika Anda mencoba abstrak dan uji unit contoh ini. Karena akan jauh lebih mudah untuk hanya memalsukan metode tunggal daripada banyak kelebihan dengan konversi sederhana.

Saya pikir dengan cara ini saya menghilangkan tanggung jawab untuk mengetahui apa itu LatLng di kelas lain, misalnya.

Saya tidak melihat alasan mengapa ini akan menjadi masalah. Selama kode Anda merujuk kelas yang berisi void moveCameraTo(LatLng latLng), itu masih secara tidak langsung bergantung pada LatLng. Bahkan jika kelas itu tidak pernah langsung dipakai.

Dan Anda tidak perlu menyiapkan data sebelum memanggil fungsi.

Saya tidak mengerti maksud Anda. Jika itu berarti membuat instance baru atau mengubah kelas dari satu ke yang lain, saya tidak melihat masalah dengan itu.

Memikirkan hal itu, saya merasa bahwa apa yang saya katakan juga didukung oleh desain API. NET itu sendiri. Secara historis, banyak kelas .NET mengikuti pendekatan Anda karena memiliki banyak kelebihan dengan parameter berbeda, dan konversi sederhana di dalamnya. Tapi itu sebelum metode penyuluhan ada. Kelas .NET yang lebih modern lebih ringan di API mereka sendiri dan jika ada metode dengan kelebihan parameter, mereka disediakan sebagai metode ekstensi. Contoh yang lebih lama adalah NLog ILogger yang memiliki lusinan beban berlebih untuk menulis log. Bandingkan dengan Microsoft.Extensions.Logging.ILogger yang lebih baru yang memiliki total 3 metode (dan hanya 1 jika Anda menghitung pencatatan sendiri). Tetapi ada banyak pembantu dan berbagai parameter sebagai metode ekstensi .

Saya pikir jawaban ini menunjukkan bahwa beberapa bahasa akan memiliki alat untuk membuat desain seperti ini lebih bagus. Saya tidak tahu banyak tentang Java, jadi saya tidak yakin apakah akan ada yang setara. Tetapi bahkan menggunakan metode statis biasa mungkin bisa menjadi pilihan.

Euforia
sumber
Tidak yakin mengapa, tetapi saya menemukan diri saya rooting untuk jawaban ini meskipun memiliki satu yang bersaing. Saya pikir Anda baru saja berhasil membuat poin lebih baik. Umpan balik saya hanya untuk mengingat bahwa tidak semua orang yang berurusan dengan masalah ini ada di .NET. +1
candied_orange
@candied_orange Benar. Sekarang saya melihat lebih baik pada pertanyaan OP, yang lebih mirip Java daripada C #.
Euforia
Saya pikir itu benar-benar tidak memiliki masalah dalam penggunaan moveCameraTo(new LatLng(latitude, longitude));di mana pun dari proyek ini, tetapi saya pikir yang lebih jelas menggunakan langsung moveCametaTo (latLng), seperti File di java Anda dapat melewati path seperti string, atau seperti kelas Path
Tlaloc-ES
1

Saya tidak yakin apa nama yang tepat untuk ini, jika ada, tetapi itu adalah praktik yang baik. Anda mengekspos beberapa kelebihan, memungkinkan kelas panggilan untuk menentukan parameter yang mengaturnya ingin digunakan. Seperti yang Anda katakan, kelas lain mungkin tidak tahu apa LatLngobjek itu, tetapi mungkin tahu itu Location.

Memiliki satu metode panggilan yang lain juga penting, karena Anda tidak ingin kode duplikat di seluruh metode tersebut. Seperti yang telah Anda lakukan, pilih satu metode untuk menjadi yang melakukan pekerjaan, dan mintalah metode lain menyebutnya (langsung atau tidak langsung)

mmathis
sumber
1

Jika Anda keberatan menggunakan jenis metode, itu hanya fitur metode overload yang bagus.

Tetapi tidak ada menghilangkan tanggung jawab untuk mengetahui apa itu LatLng . Karena Anda menginisialisasi LatLng latLng = new LatLng(latitude, longitude). Ini benar-benar ketergantungan kepada LatLng. (Untuk memahami mengapa Inisialisasi adalah masalah ketergantungan, Anda dapat memeriksa Dependency Injection ) Membuat metode kelebihan beban hanya membantu klien yang tidak peduli LatLng. Jika Anda maksudkan ini, itu juga bagus tapi saya rasa itu bukan pendekatan. Ini hanya banyak metode layanan untuk klien.

Jadi, ada dua opsi untuk mendesain arsitektur Anda:

  1. Buat banyak metode kelebihan beban dan berikan kepada klien.
  2. Buat beberapa metode kelebihan beban yang membutuhkan parameter sebagai antarmuka atau kelas beton.

Saya lari sejauh mungkin dari menciptakan metode yang membutuhkan tipe primitif sebagai parameter (Opsi 1). Karena jika bisnis Anda berubah banyak waktu dan Anda perlu memainkan parameter metode, sangat sulit untuk mengubah dan mengimplementasikan semua fungsi pemanggil.

Alih-alih ini, gunakan antarmuka (Injeksi Ketergantungan). Jika Anda pikir itu biaya dan membutuhkan waktu lebih lama, maka gunakan kelas dan berikan metode ekstensi mapper mereka (Opsi 2).

Insinyur
sumber