Saya memiliki kelas yang mengatur array node dan menghubungkannya satu sama lain dalam struktur seperti grafik. Apakah yang terbaik untuk:
- Jaga fungsionalitas untuk menginisialisasi dan menghubungkan node dalam satu fungsi
- Memiliki fungsi inisialisasi dan koneksi dalam dua fungsi yang berbeda (dan memiliki urutan tergantung pada fungsi yang harus dipanggil - meskipun perlu diingat fungsi-fungsi ini bersifat pribadi.)
Metode 1: (Buruk karena satu fungsi melakukan dua hal, TETAPI itu membuat fungsi dependen dikelompokkan bersama - node tidak boleh dihubungkan tanpa diinisialisasi terlebih dahulu.)
init() {
setupNodes()
}
private func setupNodes() {
// 1. Create array of nodes
// 2. Go through array, connecting each node to its neighbors
// according to some predefined constants
}
Metode 2: (Lebih baik dalam arti mendokumentasikan diri, TETAPI connectNodes () tidak boleh dipanggil sebelum setupNodes (), jadi siapa pun yang bekerja dengan kelas internal perlu tahu tentang pesanan ini.)
init() {
setupNodes()
}
private func setupNodes() {
createNodes()
connectNodes()
}
private func createNodes() {
// 1. Create array of nodes
}
private func connectNodes() {
// 2. Go through array, connecting each node to its neighbors
// according to some predefined constants
}
Gembira mendengar pikiran.
Jawaban:
Masalah yang Anda hadapi disebut temporal coupling
Anda benar untuk khawatir tentang bagaimana kode ini dapat dimengerti:
Saya bisa menebak apa yang terjadi di sana, tetapi beri tahu saya jika ini membuat apa yang terjadi sedikit lebih jelas:
Ini memiliki manfaat tambahan karena kurang digabungkan dengan memodifikasi variabel instan tetapi bagi saya yang dapat dibaca adalah nomor satu.
Ini membuat
connectNodes()
ketergantungan pada node eksplisit.sumber
Fungsi terpisah , karena dua alasan:
1. Fungsi pribadi bersifat pribadi untuk situasi ini.init
Fungsi Anda bersifat publik, dan itu antarmuka, perilaku, dan nilai kembali adalah apa yang Anda perlu khawatirkan tentang perlindungan dan perubahan. Hasil yang Anda harapkan dari metode itu akan tetap sama apa pun implementasi yang Anda gunakan.Karena fungsi lainnya disembunyikan di balik kata kunci pribadi itu, kata kunci itu dapat diimplementasikan sesuka Anda ... jadi Anda bisa membuatnya bagus dan modular, walaupun satu bit tergantung pada yang lain dipanggil terlebih dahulu.
2. Menghubungkan node satu sama lain mungkin bukan fungsi pribadiBagaimana jika pada titik tertentu Anda ingin menambahkan node lain ke array? Apakah Anda menghancurkan pengaturan yang Anda miliki sekarang, dan menginisialisasi ulang sepenuhnya? Atau apakah Anda menambahkan node ke array yang ada dan kemudian jalankan
connectNodes
lagi?Mungkin
connectNodes
dapat memiliki respons yang waras jika array node belum dibuat (melemparkan pengecualian? Mengembalikan set kosong? Anda harus memutuskan apa yang masuk akal untuk situasi Anda).sumber
Anda juga dapat menemukan (tergantung pada seberapa kompleks masing-masing tugas ini) bahwa ini adalah jahitan yang baik untuk membagi kelas lain.
(Tidak yakin apakah Swift bekerja dengan cara ini tetapi pseudo-code :)
Ini memisahkan tanggung jawab untuk membuat dan memodifikasi node ke kelas yang terpisah:
NodeGenerator
hanya peduli membuat / mengambil node, sementaraYourClass
hanya peduli tentang menghubungkan node yang diberikan.sumber
Selain ini menjadi tujuan tepat metode pribadi, Swift memberi Anda kemampuan untuk menggunakan fungsi-fungsi batin.
Metode internal sempurna untuk fungsi yang hanya memiliki satu situs panggilan, tetapi merasa seperti itu tidak membenarkan menjadi fungsi pribadi yang terpisah.
Misalnya, sangat umum untuk memiliki fungsi "entri" rekursif publik, yang memeriksa prasyarat, mengatur beberapa parameter, dan mendelegasikan ke fungsi rekursif pribadi yang berfungsi.
Berikut adalah contoh bagaimana hal itu terlihat dalam kasus ini:
Perhatikan bagaimana saya menggunakan nilai dan parameter pengembalian untuk mengedarkan data, daripada memutasikan status bersama. Ini membuat aliran data jauh lebih jelas pada pandangan pertama, tanpa perlu melompat ke implementasi.
sumber
Setiap fungsi yang Anda nyatakan memiliki beban untuk menambahkan dokumentasi dan membuatnya digeneralisasikan sehingga dapat digunakan oleh bagian lain dari program. Itu juga membawa beban memahami bagaimana fungsi lain dalam file dapat menggunakannya untuk seseorang yang membaca kode.
Namun jika itu tidak digunakan oleh bagian lain dari program Anda, saya tidak akan mengeksposnya sebagai fungsi terpisah.
Jika bahasa Anda mendukungnya, Anda masih dapat memiliki satu-fungsi-melakukan-satu-hal dengan menggunakan fungsi bersarang
Tempat deklarasi sangat penting, dan dalam contoh di atas jelas tanpa perlu petunjuk lebih lanjut bahwa fungsi-fungsi batin dimaksudkan untuk digunakan hanya di dalam tubuh fungsi luar.
Bahkan jika Anda mendeklarasikannya sebagai fungsi pribadi, saya berasumsi mereka masih dapat dilihat oleh keseluruhan file. Jadi, Anda perlu mendeklarasikannya dekat dengan deklarasi fungsi utama, dan menambahkan beberapa dokumentasi yang menjelaskan bahwa mereka hanya akan digunakan oleh fungsi luar.
Saya tidak berpikir bahwa Anda harus melakukan satu atau yang lain secara ketat. Hal terbaik untuk dilakukan bervariasi berdasarkan kasus per kasus.
Memecahnya menjadi beberapa fungsi tentu saja menambah pemahaman mengapa ada 3 fungsi dan bagaimana mereka semua bekerja satu sama lain, tetapi jika logikanya kompleks maka overhead yang ditambahkan ini mungkin jauh lebih sedikit daripada kesederhanaan yang diperkenalkan dengan memecah logika kompleks menjadi bagian-bagian yang lebih sederhana.
sumber
private
memungkinkan akses hanya dalam tipe penutup (struct / class / enum), sedangkanfileprivate
mengizinkan akses di seluruh file