ฟังก์ชั่นการอ่านโปรแกรมการทำงาน [ปิด]


13

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

นี่คือคำถามของฉันฉันมักจะได้ยินจากคน OOP ที่สไตล์การทำงานไม่สามารถอ่านได้มาก ฉันอยากรู้ว่าเป็นกรณีนี้หรือไม่และฉันหลอกตัวเองหรือถ้าพวกเขาใช้เวลาในการเรียนรู้ภาษาที่ใช้งานได้ทั้งสไตล์จะไม่สามารถอ่านได้มากกว่า OOP อีกต่อไป?

มีใครเคยเห็นหลักฐานหรือมีเกร็ดเล็กเกร็ดน้อยใด ๆ ที่พวกเขาเห็นสิ่งนี้ไม่ทางใดก็ทางหนึ่งโดยมีความถี่เพียงพอที่จะพูดได้หรือไม่? ถ้าการเขียนฟังก์ชั่นมีความสามารถในการอ่านต่ำกว่าจริง ๆ แล้วฉันไม่ต้องการใช้มันต่อไป แต่ฉันไม่รู้ว่ามันเป็นจริงหรือไม่ ..


1
ฉันจำได้ว่ากำลังดูรหัสสำหรับ "Super Nario Brothers" svn.coderepos.org/share/lang/haskell/narioเมื่อฉันแทบไม่รู้อะไรเกี่ยวกับการเขียนโปรแกรมที่ใช้งานได้และนึกถึงการคิด 'Wow ดูเหมือนว่าจะอ่านได้จริงๆ '
WuHoUnited



3
@ Blackack linq และ lambdas เป็นหนทางไกลจากการกำหนด "ฟังก์ชั่นการเขียนโปรแกรม" ฟังก์ชั่นการเขียนโปรแกรมที่เกี่ยวข้องกับระบบประเภทบ่อยกว่าไม่เพราะเมื่อคุณเริ่มตระหนักถึงฟังก์ชั่นเป็นประเภทมากกว่าวัตถุ / คลาส / บันทึกเป็นประเภทคุณจะจบลงด้วยความสามารถและเทคนิคใหม่ ๆ มากมาย การแสดงออกของ LINQ และแลมบ์ดา (หรือรายการลิสต์และฟังก์ชั่นการสั่งซื้อที่สูงขึ้น) เป็นเพียงเทคนิคสองผลลัพธ์เท่านั้นซึ่งมีอีกมากมาย
จิมมี่ฮอฟฟา

คำตอบ:


15

การอ่านรหัสเป็นอย่างมากอัตนัย ด้วยเหตุนี้ผู้คนต่างกันจึงพิจารณาว่ารหัสเดียวกันสามารถอ่านได้หรืออ่านไม่ได้

การบ้านนั้นx = x + 1ฟังดูแปลกสำหรับนักคณิตศาสตร์เพราะการบ้านนั้นดูคล้ายกับการเปรียบเทียบที่ทำให้เข้าใจผิด

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

เช่นเดียวกับรหัส FP หากคุณไม่ทราบรูปแบบทางตรรกะที่อยู่เบื้องหลังมันจะยากมากที่จะเข้าใจสิ่งที่เป็นพื้นฐานเช่นการส่งผ่านฟังก์ชั่นเป็นอาร์กิวเมนต์ไปยังอีกฟังก์ชันหนึ่ง

เมื่อพูดถึงสิ่งนี้แล้วเราควรเข้าใจว่า FP ไม่ใช่กระสุนเงิน มีแอปพลิเคชั่นมากมายที่ FP จะใช้งานได้ยากและจะทำให้รหัสที่อ่านง่ายขึ้น


ผู้คนควรสร้างสิ่งที่คล้ายกับตัวเอง (มนุษยชาติ) เช่นในสายตาคอมพิวเตอร์เรามีอวนประสาทในตอนนี้ ร่างกายของมนุษย์ประกอบด้วยวัตถุคุณลักษณะวิธีการและเราอธิบายสิ่งอื่น ๆ โดยใช้วัตถุคุณลักษณะวิธีการ ดังนั้นการเขียนโปรแกรมฟังก์ชั่นจึงไม่สมเหตุสมผล
user25

12

คำตอบสั้น ๆ :

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

คำตอบยาว:

ฟังก์ชั่นการเขียนโปรแกรมเองไม่สามารถอ่านหรืออ่านไม่ได้เนื่องจากเป็นกระบวนทัศน์ไม่ใช่รูปแบบการเขียนโค้ด ตัวอย่างเช่นใน C # การเขียนโปรแกรมที่ใช้งานได้ดูเหมือนว่า:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

และบุคคลนั้นจะสามารถอ่านได้ซึ่งมีประสบการณ์เพียงพอใน Java, C # หรือภาษาที่คล้ายกัน

ในทางตรงกันข้ามไวยากรณ์ภาษานั้นมีขนาดเล็กกว่าสำหรับภาษาที่ใช้งานได้หลายภาษา (รวมถึง Haskell และ F #) เมื่อเทียบกับภาษา OOP ที่เป็นที่นิยม

สิ่งนี้ใช้กับภาษานอก FP ด้วยเช่นกัน หากคุณเปรียบเทียบภาษา OOP ที่เป็นที่นิยมกับภาษาที่ได้รับความนิยมน้อยกว่าซึ่งมักใช้คำภาษาอังกฤษมากกว่าคนสุดท้ายจะเข้าใจง่ายขึ้นสำหรับผู้ที่ไม่มีประสบการณ์การเขียนโปรแกรม

เปรียบเทียบ:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

ถึง:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

ในทางเดียวกัน:

var a = ((b - c) in 1..n) ? d : 0;

อาจแสดงเป็นภาษาจินตนาการได้ใน:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

เมื่อไวยากรณ์สั้นกว่าดีกว่า

ในขณะที่ไวยากรณ์ที่ละเอียดมากขึ้นนั้นง่ายต่อการเข้าใจสำหรับผู้เริ่มต้น รหัสตัวย่อหมายถึงตัวอักษรที่ต้องการพิมพ์น้อยลง

โดยเฉพาะอย่างยิ่งมันไม่สมเหตุสมผลเลยที่จะบังคับให้คนพิมพ์คำสำคัญเพื่อระบุสิ่งที่อาจอนุมานได้จากไวยากรณ์

ตัวอย่าง:

  • ใน PHP คุณต้องพิมพ์functionก่อนทุกฟังก์ชั่นหรือวิธีการโดยไม่มีเหตุผลเฉพาะที่จะทำ

  • Ada ทำให้ฉันตกใจเสมอที่บังคับให้ผู้พัฒนาพิมพ์คำภาษาอังกฤษจำนวนมากโดยเฉพาะอย่างยิ่งเนื่องจากไม่มี IDE ที่ถูกต้องพร้อมการเติมคำอัตโนมัติ ฉันไม่ได้ใช้ Ada เมื่อเร็ว ๆ นี้และบทแนะนำอย่างเป็นทางการของพวกเขาไม่ทำงานดังนั้นฉันจึงไม่สามารถยกตัวอย่างได้ หากใครมีตัวอย่างอย่าลังเลที่จะแก้ไขคำตอบของฉัน

  • ไวยากรณ์1..nที่ใช้ในหลาย FP (และ Matlab) จะถูกแทนที่ด้วยbetween 1, nหรือหรือbetween 1 and n คำหลักที่ทำให้มันง่ายมากที่จะเข้าใจสำหรับผู้ที่ไม่คุ้นเคยกับไวยากรณ์ภาษา แต่ยังคงจุดสองจุดจะเร็วชนิดbetween (1, n)between


8
ฉันเห็นด้วยกับความเชื่อมั่น แต่ด้วยเหตุผลที่แตกต่าง มันไม่ได้เกี่ยวกับความง่ายของผู้เชี่ยวชาญในการเขียนโค้ดเนื่องจากรหัสมักอ่านบ่อยกว่าที่เขียน รหัสสั้นสามารถยังความช่วยเหลือให้สามารถอ่านได้โดยไม่เสียเวลาอันมีค่า, พื้นที่หน้าจอและกำลังจิตถ้าสิ่งที่จะอยู่แล้วจะเห็นได้ชัดจากตัวบ่งชี้ที่สั้นลง (เช่นการขึ้นบรรทัดใหม่แทนอัฒภาคทั้งสองบังเอิญอยู่แล้ว) นอกจากนี้ยังสามารถเจ็บเมื่อมันกลายเป็นความลับเกินไป (เช่นฉันชอบfor x in xsมากกว่าfor x xsเพราะมันช่วยให้ฉันแยกความแตกต่างของตัวแปรห่วงและภาชนะ)

หลายคนที่ฉันพบว่าบ่นเกี่ยวกับ FP ก็บ่นเกี่ยวกับตัวอย่างข้อมูล C # ที่คุณระบุไว้ตามที่คุณพูดมันเป็นตัวอย่างของ FP ด้วย บางทีนี่อาจเป็นปัญหาของเพื่อนร่วมงานของฉันมากกว่าความสามารถในการอ่านถ้าคน OOP ส่วนใหญ่พบว่าตัวอย่างที่อ่านได้แม้ว่าฉันจะไม่เชื่ออย่างสมบูรณ์ว่าคนส่วนใหญ่ของ OOP ทำจากประสบการณ์ของฉัน .. ดังนั้นเหตุใดฉันจึงไม่แน่ใจเกี่ยวกับหัวข้อนี้
จิมมี่ฮอฟฟา

@Jimmy Hoffa: ดูprogrammers.stackexchange.com/a/158721/6605ที่ฉันพูดถึงตัวอย่างข้อมูล C # และวิธีการรับรู้โดยโปรแกรมเมอร์มือใหม่
Arseni Mourzenko

1
@Sergiy: ใน Java หรือ C # ลายเซ็นเมธอดไม่มีmethodคำหลัก ตัวอย่าง: public int ComputePrice(Product product). การเพิ่มคำหลักเช่นเดียวกับที่ PHP ทำก็เพียงเพิ่มความยุ่งเหยิงแทนที่จะทำให้อ่านง่ายขึ้น หากโปรแกรมเมอร์ไม่สามารถเข้าใจได้ว่าฟังก์ชั่นเป็นฟังก์ชั่นจากลายเซ็นไม่ว่าโปรแกรมเมอร์นี้จะไม่มีประสบการณ์ใด ๆ หรือรหัสนั้นอ่านไม่ได้มากกว่าโค้ดชิ้นที่แย่ที่สุดที่ฉันเคยเห็น
Arseni Mourzenko

1
@Sergiy: มีหลายกรณีที่การใช้คำฟุ่มเฟื่อยสามารถช่วย (มิฉะนั้นเราจะเห็นภาษาและรหัสเช่นp i ComputePrice(product): _.unitPrice * ~.cart[_]) แต่บางภาษาผลักเกินไป ตัวอย่างของfunctionคำหลักที่ซ้ำซ้อนใน PHP เป็นตัวอย่างที่ดี
Arseni Mourzenko

6

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

ตัวอย่างเช่นสำหรับโปรแกรมเมอร์ที่ใช้งานได้มันเป็นเรื่องธรรมดาที่จะเขียนโค้ดที่สามารถล้มเหลวในจุดต่าง ๆ ภายในMaybemonad หรือEithermonad หรือเพื่อเขียนการคำนวณแบบรัฐด้วยความช่วยเหลือของStatemonad แต่สำหรับคนที่ไม่เข้าใจแนวคิดของพระสงฆ์สิ่งนี้ดูเหมือนจะเป็นเวทมนตร์คาถาดำ

ดังนั้นผมจึงคิดว่ามันจะเป็นเหตุผลที่จะใช้บิตของการเขียนโปรแกรมการทำงานแม้จะอยู่ในทีมงานของคน OOP ให้นานที่สุดเท่าที่ใช้แนวความคิดหนึ่งที่ง่ายต่อการเข้าใจหรือเรียนรู้เช่นการทำแผนที่กว่าคอลเลกชันที่มีฟังก์ชั่นหรือการปิด

(และแน่นอนขึ้นอยู่กับโปรแกรมเมอร์ที่เขียนโค้ดบางส่วนคุณสามารถเขียนโค้ดที่อ่านไม่ได้อย่างน่ากลัวในภาษาใด ๆ รวมทั้งคุณสามารถเขียนในรูปแบบที่ดีและสะอาด)


2

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

นี่คือเหตุผลที่รหัส OOP นั้นไม่สามารถอ่านได้เลย: ไม่ใช่ว่าปัญหาในโลกแห่งความจริงหลายอย่างจะแสดงออกมาในรูปของอนุกรมวิธานแบบอนุกรม วัตถุที่ส่งข้อความถึงกันนั้นเป็นแนวคิดที่แปลกและมันก็ห่างไกลจากสิ่งใด "ของจริง" น่าแปลกที่มีแนวคิดในโลกแห่งความเป็นจริงที่สามารถแมปกับสำนวนที่ใช้งานได้ตามธรรมชาติ ปัญหามีแนวโน้มที่จะถูกกำหนดอย่างชัดเจนดังนั้นการแก้ปัญหาการประกาศเป็นธรรมชาติมากขึ้น

แม้ว่าจะมีความหมายอื่น ๆ อีกมากมายที่สามารถใกล้ชิดกับโลกแห่งความเป็นจริงมากกว่าฟังก์ชั่นที่บริสุทธิ์ OOP บริสุทธิ์ดาตาโฟลว์ที่บริสุทธิ์หรือบริสุทธิ์ไม่ว่าจะเป็นอะไรก็ตาม และเนื่องจากความจริงข้อนี้แนวทางเชิงภาษาในการแก้ปัญหาจึงสร้างรหัสที่อ่านได้มากที่สุดซึ่งจะตีกรอบกระบวนทัศน์ที่ "บริสุทธิ์" ทั้งหมดที่มีอยู่ ด้วยภาษาเฉพาะโดเมนทุกปัญหาจะแสดงในคำศัพท์ตามธรรมชาติของตัวเอง และภาษาที่ใช้งานได้ดีกว่า OOP หลักเล็กน้อยในการอำนวยความสะดวกในการติดตั้ง DSL (แม้ว่าจะมีวิธีการที่ดีกว่า)


1

การอ่านรหัสเป็นเรื่องส่วนตัว ฉันแน่ใจว่าบางคนวิจารณ์ว่าขาดความเข้าใจ มีสำนวนที่แตกต่างกันตามธรรมชาติในวิธีการใช้รูปแบบทั่วไป ยกตัวอย่างเช่นรูปแบบของผู้เข้าชมไม่ได้ทำให้รู้สึกจริงๆในภาษาที่มีรูปแบบการจับคู่

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

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

การพัฒนาเชิงพาณิชย์ในภาษาหน้าที่ยังค่อนข้างไม่สมบูรณ์ ฉันเคยเห็นข้อผิดพลาดจำนวนมากที่ทำให้รูปแบบไม่ดีในภาษาใด ๆ เช่น:

  1. การเปลี่ยนสไตล์ในขณะที่คุณเรียนรู้ภาษา (และไม่ปรับโครงสร้าง) นำไปสู่ความไม่สอดคล้องกัน
  2. มากเกินไปในไฟล์เดียว
  3. มีคำสั่งมากเกินไปในหนึ่งบรรทัด

ข้อผิดพลาดเกี่ยวกับฉันยังเพิ่ม: 4. ใช้สัญลักษณ์มากเกินไปเช่น: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. คุณสมบัติโดยนัย: การประกาศทางเลือก / คำหลัก / ข้อความ, การแปลงโดยนัย ฯลฯ ;
Sergiy Sokolenko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.