Haruskah saya meninggalkan nilai non-fungsi dalam modul atau membawanya ke file program utama?

Ini adalah pertanyaan tentang bagaimana saya harus mengatur kode F# saya. Saya harap ini tidak melanggar aturan SO.

Saya memiliki lusinan file sumber (nama diakhiri dengan .fs) di proyek saya. Setiap file berisi modul. Di beberapa file/modul ini saya hanya mendefinisikan fungsi. Di tempat lain saya mendefinisikan fungsi dan nilai lain (bukan fungsi).

File terakhir di Solution Explorer (Visual Studio) adalah Program.fs yang sebenarnya hanya berisi sedikit kode. Sebagian besar perhitungan telah dilakukan "di atas" itu.

Saya sedang mempertimbangkan untuk memindahkan nilai non-fungsi yang dideklarasikan di modul lain ke Program.fs. Inilah kelebihan dan kekurangan yang saya lihat dari perubahan ini:

Keuntungan:

1) Pandangan yang lebih baik tentang alur program.

2) Lebih mudah untuk memilih semua kode di atas baris tertentu dan mengirimkannya untuk dieksekusi di FSI.

3) Sedikit lebih mudah untuk mencari nilai-nilai tersebut di editor.

4) Mungkin lebih mudah untuk melakukan debug dengan menempatkan breakpoint pada baris tempat nilai dideklarasikan.

Kekurangan:

1) Program.fs bisa menjadi besar dan berat.

2) Hilangnya modularitas.

3) Setelah mengimplementasikan perubahan, jika perhitungan nilai y pada modul B bergantung pada nilai x pada modul A "di atasnya" maka saya tidak dapat lagi memiliki y sebagai nilai, harus dideklarasikan sebagai fungsi dari x. Demikian pula jika deklarasi fungsi dalam modul B bergantung pada nilai dalam modul A saya harus menambahkan parameter ke definisi fungsi.

Di bawah ini adalah dua contoh program kecil yang sama yang dibuat dengan dua metode alternatif. Manakah dari keduanya yang secara umum lebih baik?

// ///////////////// Values in modules \\\\\\\\\\\\\\\\\\\\

// File A.fs

module A

let i = 1
let add x y : float = x + y

// File B.fs

module B

let sqr z = z * z + float i
let x = sqr 99.9

// File Program.fs

open A
open B

let y =
    add (float i) x 
    |> sqr

printfn "%f" y

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

// This is the calculated value for y: 99640524.640100

// ///////////////// Values in Program.fs \\\\\\\\\\\\\\\\\\\\

// File A.fs

module A

let add x y : float = x + y

// File B.fs

module B

open A

let sqr i z = z * z + float i // notice the additional parameter

//File Program.fs

open A
open B

let i = 1
let x = sqr i 99.9

let y =
    add (float i) x 
    |> sqr i

printfn "%f" y

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

// This is the calculated value for y: 99640524.640100

person Soldalma    schedule 14.12.2017    source sumber
comment
Sekadar untuk mendapatkan gambaran yang lebih baik, seberapa besar dan berapa banyak file yang Anda miliki?   -  person Tomas Petricek    schedule 15.12.2017
comment
Ada 60 file dalam proyek saya. File terbesar (sejauh ini) memiliki 2600 baris (dengan sekitar 12 kelas, ini adalah satu-satunya file dengan kelas). Lalu saya punya beberapa dengan 200-500 baris dan yang lainnya kecil. Masih banyak lagi kelas yang akan ditambahkan. File yang berisi nilai non-fungsi hanya sekitar 5.   -  person Soldalma    schedule 15.12.2017


Jawaban (1)


Saat Anda mempresentasikannya, versi kedua (dengan nilai dipindahkan ke Utama) lebih baik menurut saya. Anda cukup berhasil dengan keunggulan #1 dan itu sangat besar. Adapun kekurangan yang Anda sebutkan:

  1. Main besar: Ya, tergantung pada seberapa banyak hal yang kita bicarakan, kasus terburuk Anda dapat menyimpan nilai-nilai di modul lain yang digunakan hanya oleh main dan hanya untuk nilai. Pikirkan "Modul konfigurasi"
  2. Hilangnya modularitas: Saya tidak mengerti alasannya. Jika ada yang meningkatkan modularitas? Utama Anda tidak bergantung pada modul X yang memiliki nilai tertentu, ia menyediakannya. Anda kemudian dapat menukar modul dengan modul lain yang memenuhi antarmuka yang sama dan tidak peduli dengan efek riak yang mungkin terjadi pada modul lain. Jika Anda memiliki hierarki modul yang besar, Anda dapat mempertimbangkan untuk merepresentasikannya di modul utama Anda sesuai dengan prinsip inversi ketergantungan - ini akan memerlukan beberapa usaha tetapi kabar baiknya adalah bahwa dalam bahasa fungsional Anda tidak memerlukan wadah IoC, aplikasi parsial akan melakukan pekerjaan tersebut.
  3. Jika modul B bergantung pada nilai yang ada di modul A, modul itu tidak terlalu modular, bukan? Ada baiknya Anda harus mengubahnya menjadi sebuah fungsi - ini akan secara eksplisit mengatakan apa yang sekarang tersirat

Perhatikan bahwa saya menulis ini sebagian besar berdasarkan pengalaman OOP, jadi dalam pemrograman fungsional beberapa di antaranya mungkin tidak dapat diterapkan

person DevNewb    schedule 15.12.2017