การเขียนโปรแกรมเชิงฟังก์ชันเพิ่มความซับซ้อนในรหัสหรือไม่ [ปิด]


17

ตลอดปีที่ผ่านมาฉันเขียนโค้ดScala (มาจากพื้นหลัง Java) ฉันชอบวิธีที่คุณสามารถสร้างรหัสที่ง่ายและสะอาดยิ่งขึ้นด้วย vals คลาส case, ฟังก์ชัน map / filter / lambda, implicits และการอนุมานประเภท ฉันใช้มันเป็นส่วนใหญ่สำหรับแอปพลิเคชันAkka

ปีนี้ฉันอยู่ในโปรเจค Scala กับทีมใหม่ที่ชอบการเขียนโปรแกรมที่ใช้งานได้จริง พวกเขาใช้Scalazอย่างหนักและรหัสจะถูกเติมเต็มทุกที่ด้วยผู้สมัครขอบเขตบริบทผู้อ่าน / นักเขียน / รัฐ monad แม้วิธีการหลักคือ "พัน" ใน I / O monad เหตุผลของพวกเขาคือสิ่งนี้ทำให้คอมไพเลอร์ "ทำงานเพื่อเรา" ในการยืนยันว่ารหัสถูกต้องและแต่ละฟังก์ชั่นเป็นอิสระจากผลข้างเคียง

ถึงกระนั้นจากมุมมองของฉันทุกไวยากรณ์นี้จริงๆได้รับในทางของตรรกะทางธุรกิจ ตัวอย่างเช่นประเภทของ "MyBusinessObject" นั้นใช้ได้เช่นเดียวกับประเภทเช่น "รายการ [MyBusinessObject]", "ตัวเลือก [MyBusinessObject]" หรือแม้แต่ "อนาคต [MyBusinessObject]" พวกเขาทั้งหมดมีความหมายและวัตถุประสงค์ที่ชัดเจน ในทางกลับกันโค้ดที่ต้องการ:

def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}

มันเพิ่มความซับซ้อนให้กับโปรแกรมหรือเป็นเพียงฉันเท่านั้นที่ฉันไม่คุ้นเคยกับวิธีการเขียนโปรแกรมนี้


6
คำถามที่ตอบได้อย่างเป็นกลางของคุณคืออะไร
Deer Hunter

1
ดูเหมือนว่าจะนำไปสู่โค้ดมากมายที่มีชื่อตัวแปรตัวอักษรหนึ่งหรือสองตัว ดูเหมือนว่า APL เล็กน้อย นั่นไม่ใช่ส่วนเติมเต็ม
user949300

3
ฉันเริ่มเล่นกับ Haskell เมื่อปีที่แล้ว มันดูซับซ้อนอย่างไม่น่าเชื่อในเวลานั้นเมื่อฉันไม่เข้าใจแนวคิดเช่น currying, functors, monads, ฯลฯ Haskell นั้นคล้ายกับ Scalaz เพราะมันมีฟังก์ชั่นสั้น ๆ เป็นสัญลักษณ์เช่น>>=และ<$>ซึ่งไม่มีความหมายอะไรจนกระทั่งคุณ รู้ว่าพวกเขาทำอะไร หลังจากเรียนรู้สิ่งที่พวกเขาหมายถึง แต่พวกเขาอ่านอย่างเป็นธรรมชาติและรวดเร็วสำหรับฉันตอนนี้ ไม่ใช่คำตอบจริงๆแค่ประสบการณ์วัตถุประสงค์ของฉันกับสิ่งนี้ ฉันใช้ Scala ด้วย แต่ไม่มีประสบการณ์กับห้องสมุด Scalaz
KChaloux

3
คุณไม่คุ้นเคยกับสำนวน ตัวแปรสั้น @ user949300 ไม่ใช่ปัญหาสำหรับรหัสการทำงานจำนวนมาก (คิดเกี่ยวกับแบบแผนคณิตศาสตร์!) อ่านบล็อกของโทนี่มอร์ริสสำหรับการสนทนาในเชิงลึกเกี่ยวกับสิ่งที่สื่อความหมายประเภทหรือชื่อตัวแปร verbose ได้ดียิ่งขึ้น
Andres F.

3
@ user949300: ชื่อตัวแปรแบบสั้นเป็นที่ต้องการในท้องที่นั่นเป็นสิ่งเดียวกันในโลกที่ใช้งานได้และมีความจำเป็น (คุณจะไม่เขียนfor(i=0; i<7; ++i) { trivialOperation(i); }ด้วยtrivialOperationCountตัวแปรที่น่าอึดอัดใจไหม?) ตอนนี้ภาษาโปรแกรมการทำงานที่มีการจับคู่รูปแบบจะแนะนำตัวแปรเพิ่มเติม เพียงแค่เขียนการเรียกใช้เมธอด accessor ใน OO ผลลัพธ์โดยทั่วไปจะรัดกุมกว่า อาจอธิบายตัวเองน้อยลงเล็กน้อย แต่การค้นหาการประกาศข้อมูลตามปกติจะทำให้มันชัดเจนขึ้นอย่างรวดเร็ว การพิมพ์แบบสแตติกช่วยได้มากมันไม่เหมือนใน APL
leftaroundabout

คำตอบ:


37

นี้มีอะไรจะทำอย่างไรกับโปรแกรมการทำงาน - คุณสามารถหาชนิดของสถานการณ์นี้ในบริบทของการเขียนโปรแกรมภาษาอื่น ๆ - นักพัฒนาที่รักโครงสร้างขั้นสูงของภาษา "ของพวกเขา" มากว่าพวกเขาไม่สนใจความรู้สึกร่วมกันใด ๆ เกี่ยวกับการอ่านและการรักษาสิ่งที่เรียบง่าย ฉันพบสถานการณ์เช่นนี้ใน C, C ++, Perl, Java, C #, พื้นฐานและภาษาอื่น ๆ ไม่ใช่โปรแกรมที่ใช้งานได้ซึ่งเพิ่มความซับซ้อนให้กับโค้ด - โปรแกรมเมอร์ทำ

อย่าเข้าใจผิดฉันไม่แนะนำให้หลีกเลี่ยงคุณสมบัติทางภาษาขั้นสูง - แต่สิ่งสำคัญคือการหาสมดุลที่เหมาะสมในบริบทที่กำหนด เมื่อเขียนไลบรารี่ทั่วไปสำหรับการใช้งานของนักพัฒนามากกว่า 100,000 รายทั่วโลกมีมาตรการที่แตกต่างกันเมื่อคุณเขียนตัวสร้างรายงานเฉพาะสำหรับสำนักงานท้องถิ่นของคุณ


7
นอกจากนี้ยังมีหลายสิ่งที่ต้องทำกับชุมชน สำหรับนักพัฒนาที่มีพื้นหลัง Java หรือ C # รหัสนั้นแทบจะไม่สามารถเข้าใจได้ (และชุมชนของเขา / เธอจะไม่เข้าใจเหมือนกัน) แต่ถ้าคุณเขียน Haskell และคุณไม่ได้ใช้ monads, applicatives, functors และอื่น ๆ คุณกำลังยุ่งกับชุมชนภาษานั้น "ความเป็นธรรมชาติ" ของรหัสไม่ได้มีอยู่ในตัว แต่เกี่ยวข้องกับชุมชนและการปฏิบัติที่จัดตั้งขึ้น
Andres F.

1
นี่เป็นเรื่องยากที่จะเห็นเพราะส่วนใหญ่ของเรามาจากภูมิหลังที่จำเป็นซึ่งบางครั้งทำให้เราตั้งสมมติฐานที่ผิดเกี่ยวกับสิ่งที่เป็นธรรมชาติ
Andres F.

เพียงแค่ดูไลบรารี SLT C ++ ที่สามารถเขียนให้อ่านได้มากขึ้นสำหรับมือสมัครเล่น
ratchet freak

@ ratchetfreak: ฉันเดาว่าคุณหมายถึง STL ฉันคิดว่านี่เป็นตัวอย่างที่ดีมาก (และแน่นอนฉันมีสิ่งนี้ในใจในคำตอบของฉัน) การใช้การเขียนโปรแกรมเทมเพลต meta นั้นสมเหตุสมผลเมื่อคุณเป็นโปรแกรมเมอร์ STL เพราะทำให้ STL สามารถนำกลับมาใช้ใหม่ได้มากขึ้น และคนที่ต้องดูแลรหัสนั้นก็มักจะใช้กับเทมเพลต metaprogramming การใช้เทมเพลตการเขียนโปรแกรมในลักษณะคล้าย STL ตลอดแอปพลิเคชันธุรกิจมาตรฐานของคุณสามารถนำไปสู่การโค้ดที่ซับซ้อนและยากเกินความจำเป็น เราสามารถค้นหาผู้ป่วย (หายาก) ที่ TMP นั้นดีแม้ในการใช้งานทางธุรกิจ
Doc Brown

@DocBrown ใช่ dyslexia เตะในเวลาที่ไม่ถูกต้อง แต่โดยสุจริตถ้าฉันมีครึ่งใจที่จะ (และเวลามากขึ้นกว่าที่ฉันมีในขณะนี้) ฉันสามารถเขียนหลายฟังก์ชั่นของร่างกายที่จะอ่านได้มากขึ้น
วงล้อประหลาด

7

ฉันจะบอกว่าคุณไม่คุ้นเคยกับวิธีการที่รหัสเหล่านี้เป็นส่วนหนึ่งของภาพอย่างน้อย ฉันอยู่ในสถานการณ์ที่คล้ายกันในขณะที่คุณ (มาจาก C # เป็น F # และทำงานกับคนที่มีพื้นหลัง Haskell) และในขณะที่ฉันพบว่ามันเป็นประสบการณ์ที่น่าสนใจฉันมีช่วงเวลาที่ฉันกระแทกหัวกับกำแพง การจัดองค์ประกอบฟังก์ชั่นที่ปราศจากจุดที่ซับซ้อนโดยเฉพาะเพื่อให้รู้ว่าเกิดอะไรขึ้น มันเป็นเรื่องทางวัฒนธรรม

สำหรับรหัสเฉพาะนี้เพิ่มความซับซ้อนให้กับโปรแกรมหรือไม่ - ฉันไม่รู้ ตกลงกันว่ารหัสทั่วไปสามารถซับซ้อนได้ แต่เป็นอรรถประโยชน์ไม่ใช่ส่วนหนึ่งของตรรกะทางธุรกิจ ถ้าคุณต้องการทราบว่ามันทำให้โค้ดเบสมีความซับซ้อนมากขึ้นหรือง่ายขึ้นคุณจะต้องจินตนาการว่ามันจะต้องดูอย่างไรถ้าไม่มีโค้ดชิ้นนั้น มันมักจะเป็นกรณีที่มีโครงสร้างทั่วไปเช่นนั้นพวกมันซับซ้อน แต่มันเป็นความซับซ้อนที่คุณสามารถใส่ลงในหน้าจอเดียวได้ ในเวลาเดียวกันพวกเขาทำให้ codebase ทั้งหมดง่ายขึ้นเล็กน้อย โดยเฉพาะอย่างยิ่งในกรณีที่มีพระ

จากนั้นอีกครั้งมันอาจเป็นกรณีของ 'ศิลปะเพื่อประโยชน์ของงานศิลปะ' ตามที่ @Doc Brown แนะนำ ไม่สามารถออกกฎอย่างใดอย่างหนึ่ง


5

ฉันจะยืนยันว่าในการเขียนโปรแกรมการทำงานทั่วไปลดความซับซ้อนโดยการกำจัดสถานะที่ไม่แน่นอนซึ่งจะช่วยลดจำนวนกรณีที่ต้องพิจารณาเมื่อพยายามที่จะเข้าใจว่าส่วนของรหัสทำงานอย่างไร

อย่างไรก็ตามการเขียนโปรแกรมฟังก์ชั่นทำให้ระดับของ abstraction สูงขึ้นและในขณะที่โค้ดที่เป็นนามธรรมสูงนั้นมีประโยชน์อย่างมากมันก็ยากที่จะเข้าใจเพราะมันเป็นคำนิยามที่หย่าร้างจากบริบทที่คุณมักจะใช้เพื่อชี้นำความเข้าใจของคุณ ความคิดเห็นของคุณ "พวกเขาทุกคนมีความหมายและวัตถุประสงค์ที่ชัดเจน" เกี่ยวกับวัตถุทางธุรกิจเป็นความจริงอย่างไม่ต้องสงสัย แต่เป็นภาพสะท้อนของความจริงที่ว่าตรรกะนั้นมีความเฉพาะเจาะจงกับความต้องการและบริบทที่คุณเข้าใจอยู่แล้ว การมีโครงสร้างเช่น Monad ช่วยให้คุณทำสิ่งที่มีประโยชน์มากโดยใช้ความพยายามเพียงเล็กน้อย แต่เว็บก็เกลื่อนไปด้วยหน้าพยายามอธิบายว่า Monad คืออะไร นั่นเป็นสิ่งที่เป็นนามธรรมสำหรับคุณ

นอกจากนี้ Scalaz เขียนโดยคนที่เคยกินและหายใจ FP มาเป็นเวลานาน พวกเขาต้องการนำฟังก์ชั่นการใช้งานใน Haskell มาสู่ Scala ในการทำเช่นนั้นพวกเขาไม่ได้พยายามที่จะสอน Scalaz ใช้คำศัพท์และรูปแบบที่ดูชัดเจนและตรงไปตรงมากับผู้แต่ง แต่มนุษย์ต่างดาวไม่ได้ฝึกหัด วิธีการที่สร้างความสับสนให้กับพวกเราที่เหลือดูเหมือนจะชัดเจนต่อผู้เขียนเนื่องจากภูมิหลังของ Haskell ว่าพวกเขาไม่ได้รับประกันความคิดเห็น

นอกจากนี้ในฐานะที่เป็นภาษาโปรแกรมการทำงาน Scala มีข้อบกพร่องบางส่วน(ส่วนหนึ่งเป็นเพราะ JVM มีข้อบกพร่อง) ที่บังคับให้ผู้เขียน Scalaz เขียนรหัสที่ไม่ดีในบางกรณี ยกตัวอย่างเช่นการขาดการเรียกหางทั่วไปบังคับให้ใช้ trampolines ในบางรหัสและการขาด "ระบบชนิด" อาจทำให้ลายเซ็นประเภทซับซ้อน

และสุดท้าย Scalaz ใช้ประโยชน์จากตัวเองได้อย่างยอดเยี่ยม นั่นอาจเป็นสัญญาณของพลังของมัน แต่สำหรับผู้ที่ไม่ได้ฝึกหัดก็สามารถทำให้ปริศนาเป็นแหล่งกำเนิด - รหัสสุ่มใด ๆ ที่คุณดูมีแนวโน้มที่จะใช้ประโยชน์จากสิ่งอื่นที่ดูเหมือนกับมนุษย์ต่างดาว

อดทนหน่อย. และนี่อาจช่วยได้


-4

มันเพิ่มความซับซ้อนให้กับโปรแกรมหรือว่าคุณไม่คุ้นเคยกับวิธีการเขียนโปรแกรมนี้

ทำไมคุณคิดว่าความเป็นไปได้เหล่านี้ไม่เหมือนกัน

ผู้ที่ไม่คุ้นเคยกับภาษาการเขียนโปรแกรมสามารถอ่านโค้ดที่เขียนได้ดี บางภาษา (ภาษาเบสิค, ภาษาปาสคาล, ฯลฯ ) สามารถอ่านและเข้าใจโดยเด็กนักเรียนที่ไม่เคยเห็นภาษาการเขียนโปรแกรมมาก่อน

หากใครที่มีประสบการณ์เกี่ยวกับภาษาอื่นและมีประสบการณ์กับสกาล่า (และฉันคิดว่าได้ทำงานกับสคาลาซเป็นเวลาอย่างน้อยหนึ่งสัปดาห์และมีเพื่อนร่วมงานเพื่ออธิบายสิ่งที่มีเล่ห์เหลี่ยม) ก็ยังสับสนอยู่ นั่นเป็นข้อพิสูจน์ว่ามันเพิ่มความซับซ้อน


11
สิ่งนี้ไม่เป็นความจริง:"Well written code can be read by people who aren't familiar with the specific programming language."
Andres F.

@Andres: มันเป็นความจริง ... ถึงจุดหนึ่ง โค้ดที่เขียนได้ดีจะแยกตรรกะทางธุรกิจออกจากรายละเอียดการใช้งานและตรรกะทางธุรกิจควรอ่านได้เพราะสิ่งที่ทำส่วนใหญ่คือการโทรตรงไปยังฟังก์ชันตัวช่วยที่มีชื่อดี ผู้ช่วยเหล่านั้นอาจใช้คุณสมบัติทางภาษาทุกประเภทและต้องมีประสบการณ์อย่างหนักกับภาษาและห้องสมุดเพื่อให้เข้าใจ
Ben Voigt

4
ผมเชื่อว่าต่อไปนี้เป็นสำนวน x[⍋x←6?40]APL: คุณคิดว่ามันทำอะไร ฉันแน่ใจว่าจะไม่รู้จัก ...
bdesham

3
@Brendan เฉพาะภายในกระบวนทัศน์เดียวกัน (และบางครั้งก็ไม่ใช่) ตัวอย่างเช่น Prolog, Java และ APL นั้นแตกต่างกันอย่างมากซึ่งฉันจะโต้แย้งว่าหากคุณรู้จักหนึ่งในนั้น (และไม่มีภาษาอื่น) คุณจะไม่สามารถอ่านอีกสองภาษาได้ไม่ว่าคุณจะรู้จักคนแรกดีเพียงใด (ในตัวอย่างของ bdesham อย่างจริงจังคุณจะตีความปีศาจ "ต้นคริสต์มาส" ได้อย่างไรถ้าคุณไม่รู้จัก APL)
Izkata

1
เบรนแดนคำจำกัดความของคุณเกี่ยวกับการเขียนที่ดีนั้นไม่เป็นมาตรฐาน การเขียนที่ดีนั้นสัมพันธ์กับภาษาและชุมชนนั้นเสมอ โปรแกรมในภาษา X นั้นถูกเขียนขึ้นมาอย่างดีหากไม่เป็นรถมันมีประสิทธิภาพและชัดเจน ... สำหรับผู้ชมที่ได้รับ! สิ่งนี้ใช้กับภาษาเขียนโดยทั่วไป: รู้จักผู้ชมของคุณเสมอ สิ่งที่เหมาะสำหรับ (พูด) กระดาษทางวิทยาศาสตร์อาจไม่เหมาะสำหรับอีเมลถึงแม่ของคุณ
Andres F.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.