ฉันควรทิ้งค่าที่ไม่ใช่ฟังก์ชันไว้ในโมดูลหรือนำไปไว้ที่ไฟล์โปรแกรมหลักหรือไม่?

นี่เป็นคำถามว่าฉันควรจัดระเบียบรหัส F# ของฉันอย่างไร ฉันหวังว่ามันจะไม่ละเมิดกฎ SO

ฉันมีไฟล์ต้นฉบับหลายสิบไฟล์ (ชื่อที่สิ้นสุดด้วย .fs) ในโครงการของฉัน แต่ละไฟล์มีโมดูล ในไฟล์/โมดูลบางไฟล์ ฉันกำหนดเฉพาะฟังก์ชันเท่านั้น ในส่วนอื่นๆ ฉันกำหนดฟังก์ชันและค่าอื่นๆ (ไม่ใช่ฟังก์ชัน)

ไฟล์สุดท้ายใน Solution Explorer (Visual Studio) คือ Program.fs ซึ่งมีโค้ดน้อยมาก การคำนวณส่วนใหญ่ทำได้ "เหนือ" นั่นเอง

ฉันกำลังพิจารณาที่จะย้ายค่าที่ไม่ใช่ฟังก์ชันที่ประกาศในโมดูลอื่นไปที่ Program.fs นี่คือข้อดีและข้อเสียที่ฉันเห็นจากการเปลี่ยนแปลงนี้:

ข้อดี:

1) มุมมองการไหลของโปรแกรมที่ดีขึ้น

2) ง่ายกว่าในการเลือกรหัสทั้งหมดที่อยู่เหนือบรรทัดใดบรรทัดหนึ่งและส่งไปดำเนินการใน FSI

3) ง่ายกว่าเล็กน้อยในการค้นหาค่าเหล่านั้นในตัวแก้ไข

4) อาจจะง่ายกว่าที่จะแก้ไขจุดบกพร่องโดยการวางจุดพักบนบรรทัดที่มีการประกาศค่า

ข้อเสีย:

1) Program.fs อาจมีขนาดใหญ่และเทอะทะ

2) การสูญเสียความเป็นโมดูลาร์

3) หลังจากดำเนินการเปลี่ยนแปลงแล้ว หากการคำนวณค่า y ในโมดูล B ขึ้นอยู่กับค่า x ในโมดูล A "ด้านบน" ดังกล่าว ฉันก็จะไม่สามารถมีค่า y เป็นค่าได้อีกต่อไป จะต้องประกาศให้เป็นฟังก์ชันของ x ในทำนองเดียวกันหากการประกาศฟังก์ชันในโมดูล B ขึ้นอยู่กับค่าในโมดูล A ฉันจะต้องเพิ่มพารามิเตอร์ให้กับคำจำกัดความของฟังก์ชัน

ด้านล่างนี้คือสองตัวอย่างของโปรแกรมขนาดเล็กเดียวกันที่สร้างขึ้นภายใต้สองวิธีอื่น โดยทั่วไปแล้วอันไหนดีกว่ากัน?

// ///////////////// 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 แหล่งที่มา
comment
เพื่อให้เข้าใจได้ดีขึ้น คุณมีไฟล์ขนาดเท่าไรและมีกี่ไฟล์?   -  person Tomas Petricek    schedule 15.12.2017
comment
มี 60 ไฟล์ในโครงการของฉัน ไฟล์ที่ใหญ่ที่สุด (จนถึงตอนนี้) มี 2,600 บรรทัด (มีประมาณ 12 คลาส นี่เป็นไฟล์เดียวที่มีคลาส) แล้วผมก็มีไม่กี่เส้น 200-500 เส้น และที่เหลือก็เล็ก คลาสอื่นๆ อีกมากมายจะถูกเพิ่มเข้ามา ไฟล์ที่มีค่าที่ไม่ใช่ฟังก์ชันมีเพียงประมาณ 5 เท่านั้น   -  person Soldalma    schedule 15.12.2017


คำตอบ (1)


ตามที่คุณนำเสนอเวอร์ชันที่สอง (โดยมีค่าที่ย้ายไปที่ Main) จะดีกว่า คุณทำได้ดีมากด้วยข้อได้เปรียบอันดับ 1 และมันใหญ่มาก สำหรับข้อเสียที่คุณระบุไว้:

  1. Large main: ใช่ ขึ้นอยู่กับว่าเรากำลังพูดถึงเนื้อหามากแค่ไหน กรณีที่แย่ที่สุดที่คุณสามารถเก็บค่าไว้ในโมดูลอื่นที่ใช้เพียง main และสำหรับค่าเท่านั้น คิดว่า "โมดูลกำหนดค่า"
  2. การสูญเสียโมดูลาร์: ฉันไม่เข้าใจว่าทำไม หากมีสิ่งใดมันจะเพิ่มความเป็นโมดูลาร์? หลักของคุณไม่ได้ขึ้นอยู่กับโมดูล X ที่มีค่าบางอย่าง แต่มีให้ จากนั้นคุณสามารถสลับโมดูลกับอินเทอร์เฟซอื่นที่น่าพอใจและไม่สนใจเอฟเฟกต์ระลอกคลื่นที่อาจมีกับโมดูลอื่น หากคุณมีลำดับชั้นของโมดูลจำนวนมาก คุณสามารถดูการแสดงโมดูลนั้นในโมดูลหลักของคุณตามหลักการผกผันการพึ่งพา - มันอาจจะต้องใช้เวลาบ้าง แต่ข่าวดีก็คือในภาษาที่ใช้งานได้คุณไม่จำเป็นต้องใช้คอนเทนเนอร์ IoC แอปพลิเคชันบางส่วนจะทำงานได้
  3. หากโมดูล B ขึ้นอยู่กับค่าที่มีอยู่ในโมดูล A มันจะไม่ได้เป็นโมดูลาร์มากนักในการเริ่มต้นใช่ไหม เป็นสิ่งที่ดีที่คุณจะต้องเปลี่ยนเป็นฟังก์ชัน - มันจะพูดอย่างชัดเจนถึงสิ่งที่เป็นนัยในตอนนี้

โปรดทราบว่าฉันกำลังเขียนสิ่งนี้จากประสบการณ์ OOP ส่วนใหญ่ของฉัน ดังนั้นในการเขียนโปรแกรมเชิงฟังก์ชันบางส่วนอาจไม่สามารถใช้ได้

person DevNewb    schedule 15.12.2017