Rich Hickey หมายความว่าอย่างไรเมื่อเขาพูดว่า“ ความพิเศษเฉพาะทั้งหมดของอินเทอร์เฟซ / คลาส / ประเภท] ฆ่าการใช้ซ้ำของคุณ!”


41

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

ในการค้นหาคำตอบของฉันฉันเจอ:

  • หลักการของความรู้น้อยที่สุด AKA กฎหมายของ Demeterซึ่งสนับสนุนการเชื่อมต่อ API แบบสุญญากาศ Wikipedia ยังแสดงข้อเสียบางประการ

  • วิกฤตเสื้อผ้าของ Kevlin Henney ซึ่งระบุว่าการใช้ไม่ใช่การใช้ซ้ำเป็นเป้าหมายที่เหมาะสม

  • การพูดคุยเรื่อง " Stop Writing Classes " ของ Jack Diederich ซึ่งขัดแย้งกับเรื่องวิศวกรรมโดยทั่วไป

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

ฉันกำลังมองหาหนึ่งตัวอย่างที่ดีของอินเทอร์เฟซที่ดีที่ป้องกันไม่ให้ใช้รหัสบางอย่างถูกต้อง มีอยู่จริงเหรอ? ฉันไม่สามารถจินตนาการได้


1
ยังไม่ได้ดู / อ่านสิ่งนี้ (ฉันได้เพิ่ม "หยุดการเขียนชั้นเรียน" ลงในรายการที่ต้องดูของฉัน :)) แต่บางทีพวกเขาอาจโต้เถียงจากมุมการพิมพ์แบบไดนามิกเทียบกับแบบคงที่? ... อีกครั้งหรือไม่
Andres F.

oO อินเตอร์เฟสการโปรแกรมมิงของโปรแกรมประยุกต์
Thomas Eding

ขอบคุณสำหรับลิงค์! ฉันไม่พบคำพูดของ Jack Diederich ที่ส่องแสงเป็นพิเศษ (ดูว่าเขาล้มเหลวในการตอบคำถามที่แท้จริงของผู้ชมอย่างน่าเชื่อถือ .. "เอ่อใช่บางทีในกรณีนี้ ... " ฉันไม่ชอบเขาดูเหมือนจะเถียงกับการเขียนโปรแกรมเชิงฟังก์ชั่น แม้จะสังเกตเห็นมัน;)) แต่"วิกฤตเสื้อผ้าของจักรวรรดิ"นั้นดีมากและลึกซึ้ง
Andres F.

1
MPO คือคนที่ไม่เชื่อในการใช้ซ้ำอย่าทำลายสิ่งเล็ก ๆ น้อย ๆ สิ่งที่ยิ่งใหญ่ที่สร้างขึ้นเพื่อวัตถุประสงค์เฉพาะไม่สามารถนำกลับมาใช้ใหม่ได้ อย่างไรก็ตามสิ่งเล็ก ๆ มักมีจุดประสงค์เล็ก ๆ น้อย ๆ ที่จุดประสงค์เล็ก ๆ นั้นมีประโยชน์ในบริบทมากกว่าหนึ่งบริบท
เอมี Blankenship

1
@ MyBlankenship ฉันพบว่า "Imperial Clothing Crisis" ที่เชื่อมโยงไว้ข้างต้นมีความเฉียบแหลม ผู้เขียนเห็นว่า "นำกลับมาใช้" เป็นไอดอลเท็จ (สิ่งที่ไม่ได้รับการพิสูจน์แล้วว่ามีประโยชน์ในทางปฏิบัติและคนส่วนใหญ่ก็ไม่เข้าใจแม้จะใช้คำนั้นก็ตาม) เขายังไม่พิจารณาห้องสมุด "นำมาใช้ใหม่"; คุณใช้ห้องสมุดคุณไม่ได้นำมาใช้มัน เขายังพิจารณาการออกแบบบางสิ่งเพื่อใช้ซ้ำ“ ดาบสองคม”; สิ่งที่ผู้คนมักจะพิจารณาสถานการณ์ที่ชนะ แต่ไม่จริง: เมื่อคุณออกแบบบางสิ่งเพื่อนำมาใช้ใหม่มันจะเป็นการประนีประนอมเสมอ (เช่นคุณอาจสูญเสียความเรียบง่าย)
Andres F.

คำตอบ:


32

ยังไม่ได้ดูงานนำเสนอ Rich Hickey เต็มรูปแบบ แต่ถ้าฉันเข้าใจเขาอย่างถูกต้องและตัดสินจากสิ่งที่เขาพูดเกี่ยวกับเครื่องหมาย 29 นาทีดูเหมือนว่าเขาจะเถียงกันเกี่ยวกับการฆ่าซ้ำประเภท เขาใช้คำว่า "interface" อย่างหลวม ๆ เป็นคำพ้องสำหรับ "named type" ซึ่งเหมาะสมแล้ว

หากคุณมี{ "name":"John" }ประเภทเอนทิตีสองประเภทPersonและ{ "name": "Rover" }ประเภทDogใน Java-land พวกเขาอาจไม่สามารถทำงานร่วมกันได้เว้นแต่พวกเขาจะแบ่งปันอินเทอร์เฟซหรือบรรพบุรุษร่วมกัน (เช่นMammalซึ่งหมายถึงการเขียนรหัสเพิ่มเติม) ดังนั้นการเชื่อมต่อ / ประเภทที่นี่จะ "ฆ่านำมาใช้ใหม่ของคุณ": แม้ว่าPersonและDogมีลักษณะเดียวกันหนึ่งไม่สามารถใช้สลับกันกับคนอื่น ๆ ถ้าคุณเขียนโค้ดเพิ่มเติมเพื่อสนับสนุนว่า หมายเหตุ Hickey ยังตลกเกี่ยวกับโปรเจ็กต์ใน Java ที่ต้องการคลาสจำนวนมาก ("ใครที่นี่เขียนแอปพลิเคชัน Java โดยใช้เพียง 20 คลาส?") ซึ่งดูเหมือนว่าเป็นผลมาจากข้างต้น

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

สรุปแล้วทั้งหมดนี้ดูเหมือนจะเป็นอะไรบางอย่างเกี่ยวกับความเสมอภาคของโครงสร้างเทียบกับความชัดเจนของประเภท / ส่วนต่อประสานที่ชัดเจน ถ้าฉันไม่ได้รับอะไรบางอย่างจากส่วนของวิดีโอที่ฉันยังไม่ได้ดู :)


2
BTW การพูดคุยของ Stop Desserich ของ Jack Diederich ดูเหมือนจะไม่เกี่ยวข้องกับหัวข้อนี้และเป็นเรื่องเกี่ยวกับ YAGNI และ "อย่าเขียนรหัสจนกว่าคุณจะต้องการมันและจากนั้นก็เขียนรหัสง่ายๆ"
Andres F.

9
ERROR: Object doesn't have a property called "name"มักจะเป็นผลมาจากvalue-orientedภาษาและปัญหาอื่น ๆ nameคือเมื่อคุณต้องการที่จะไม่เรียกทรัพย์สินที่ refactoring โชคดีเพราะมีแนวโน้มที่ร้อยของวัตถุที่มีคุณสมบัติnameแต่ไม่ทั้งหมดมีหรือPerson Dog
ซ้ำ

2
@ MathewFoscarini ใช่ฉันไม่จำเป็นต้องเห็นด้วยกับมันมันเป็นเพียงการตีความของฉันในสิ่งที่ฉันคิดว่า Hickey พูด :) ฉันชอบประเภทและการพิมพ์แบบคงที่; ฉันเพิ่งเริ่มไม่ชอบ Java และไม่ชอบของฉันไม่เกี่ยวข้องกับinterfaces แต่ระเบียบที่เป็นโครงการ Java ทั่วไป
Andres F.

1
Java เป็นภาษาการเขียนโปรแกรมสำหรับผู้ที่คิดมากเกินไป เป็นหนึ่งในไม่กี่ภาษาที่ช่วยให้นักพัฒนาซอฟต์แวร์สามารถซ่อนความพยายามของเขาในการควบคุมโครงการ
ซ้ำ

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

28

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

Java มีประวัติของการจัดเตรียมเฟรมเวิร์กของ API จำนวนมากที่ใช้อินเทอร์เฟซเป็นอาร์กิวเมนต์ แต่ทีมที่พัฒนา API ไม่เคยใช้คลาสที่หลากหลายเพื่อให้คุณนำมาใช้ใหม่กับอินเตอร์เฟสเหล่านั้น

เป็นเหมือนกรอบ GUI ที่มีIWindowส่วนต่อประสานกับกล่องโต้ตอบจากนั้นคุณสามารถเพิ่มIButtonส่วนต่อประสานสำหรับตัวควบคุมได้ ยกเว้นพวกเขาไม่เคยให้คุณดีคลาสที่ใช้Button IButtonดังนั้นคุณเหลือที่จะสร้างของคุณเอง

เฟรมเวิร์ก Abstracted ที่มีคลาสฐานที่หลากหลายซึ่งจัดเตรียมฟังก์ชันการทำงานหลักนั้นสามารถนำมาใช้ซ้ำได้มากขึ้นและทำงานได้ดีที่สุดเมื่อคลาส abstracted เหล่านั้นสามารถเข้าถึงได้โดยผู้ที่ใช้เฟรมเวิร์ก

นักพัฒนา Java เริ่มทำสิ่งนี้ที่ชั้น API interfacesของพวกเขาสัมผัสเท่านั้น คุณสามารถใช้อินเทอร์เฟซเหล่านั้นได้ แต่คุณไม่สามารถใช้คลาสซ้ำจากนักพัฒนาที่ใช้อินเทอร์เฟซเหล่านั้นได้ มันเหมือนกับการพัฒนา API แบบปิดบังและกริช


4
ขอบคุณสำหรับคำตอบนี้ ตอนนี้ฉันรู้สึกเหมือนฉันเข้าใจคำถามและคำตอบ :)
MetaFight

2
+1 ฉันขอขอบคุณคำตอบของคุณและมันเป็นการเพิ่มข้อมูลที่น่าสนใจให้กับคำถามนี้ แต่ฉันคิดว่าคำตอบของ Andreas F. น่าจะใกล้กับสิ่งที่นาย Hickey หมายถึงดังนั้นฉันจึงยอมรับเขาแทน
GlenPeterson

@GlenPeters โดยไม่มีปัญหาฉันคิดว่าเขาอาจจะทำเครื่องหมายเช่นกัน
ซ้ำ

1
อย่างนี้และคำตอบที่ยอมรับเน้นสองแตกต่างกันเล็กน้อย แต่น่าสนใจเท่ากันตีความ ฉันอยากรู้ว่านาย Hickey คนไหนที่อยู่ในใจเมื่อพูดถึงเรื่องนี้ ..
David Cowden

คุณไม่สามารถใช้อินเตอร์เฟสซ้ำได้ แต่คุณสามารถขยายได้ (และให้หมายเลขรุ่นที่มีค่า) โดยไม่ต้องเปลี่ยนคลาสเก่า คุณยังสามารถสืบทอดจากอินเทอร์เฟซมากมายเพื่อเพิ่มงานใหม่สำหรับคลาสใหม่หรือเพิ่มการสืบทอดใหม่ในคลาสที่คอมไพล์เก่า นอกจากนี้คุณยังสามารถขยายคลาสที่ใช้อินเทอร์เฟซนี้สำหรับงานใหม่
cl-r

14

ฉันคิดว่าสไลด์ 13 ในการนำเสนอของเขา ( ค่านิยม ) ช่วยให้เข้าใจสิ่งนี้:

http://i.stack.imgur.com/LVMne.png


ค่า

  • ไม่ต้องการวิธีการ
    • ฉันสามารถส่งค่าโดยไม่มีรหัส
      และคุณก็สบาย

ความเข้าใจของฉันคือ Hickey แนะนำว่าถ้าฉันต้องการพูดเพิ่มค่าที่คุณส่งมาให้ฉันเป็นสองเท่าฉันก็เขียนโค้ดที่ดูเหมือน

    MyValue = Double(YourValue)

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

ทีนี้มันจะเป็นอย่างไรในภาษาที่มีวัตถุและส่วนต่อประสาน?

    Doublable MyValue = YourValue.Double()

โอ้เดี๋ยวก่อน! สิ่งที่ถ้าYourValueไม่ใช้Doublable? ไม่ว่ามันจะไม่เป็นสองเท่า แต่มันอาจเป็นไปได้อย่างสมบูรณ์แบบ แต่ ... จะเกิดอะไรขึ้นถ้าไม่มีวิธี Double ? (เกิดอะไรขึ้นถ้ามีวิธีที่เรียกว่าพูดTwiceAsMuch?)

เอ่อโอ้เรามีปัญหา YourValue.Doubleจะไม่ทำงานมันไม่สามารถใช้ซ้ำได้อีก ตามที่ฉันได้อ่านสไลด์ด้านบนนี่เป็นสิ่งที่ Hickey หมายถึงเมื่อเขาพูดว่า

คุณจะเห็นว่าอินเทอร์เฟซสันนิษฐานว่าวัตถุถูกส่งผ่าน "พร้อมกับวิธีการ" พร้อมกับรหัสที่ทำงานกับสิ่งเหล่านี้ ในการใช้ออบเจกต์เราต้องเข้าใจวิธีการเรียกใช้โค้ดนั้นวิธีการเรียก

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


หมายเหตุด้าน: ความคิดในการส่งค่าที่ไม่ใช้โค้ดช่วยเตือนฉันถึงรูปแบบ Flyweightใน OOP

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

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

สิ่งนี้ให้ความรู้สึกเหมือนอยู่ที่สไลด์ "ค่าไม่ต้องการวิธีการฉันสามารถส่งค่าโดยไม่มีรหัสและคุณสบายดี"


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

1
สิ่งที่น่าสนใจ คำตอบที่ดี!
maple_shaft

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

5
MyValue = Double(YourValue)ไม่สมเหตุสมผลถ้า YourValue เป็นสตริงที่อยู่ผู้ใช้ฟังก์ชันหรือฐานข้อมูล มิฉะนั้นอาร์กิวเมนต์วิธีที่ขาดหายของคุณจะมีความแข็งแกร่ง OTOH วิธีการเข้าถึงช่วยให้คุณบังคับใช้ข้อ จำกัด ต่าง ๆ เพื่อให้ค่าของคุณใช้ได้และมีเพียงการดำเนินการที่สมเหตุสมผลเท่านั้นที่ใช้ในการสร้างค่าใหม่ หากคุณตัดสินใจที่จะแยกที่อยู่ออกจากผู้ใช้และ บริษัท ของคุณวิธีการเข้าถึงหมายความว่าคุณจะไม่ทำลายลูกค้าทั้งหมดของรหัสของคุณ ดังนั้นพวกเขาจึงสามารถช่วยนำมาใช้ซ้ำได้ในระยะยาวแม้ว่าบางครั้งพวกเขาจะขัดขวางมันในระยะสั้น
GlenPeterson

4
(ในทางกลับกันฉันยอมรับว่าใน Java-land การระเบิดของคลาสอินเทอร์เฟซและเฟรมเวิร์กเป็นฝันร้ายวิธีแก้ปัญหา "enterprisey" ที่ง่ายที่สุดใน Java คือโค้ดที่ยุ่งเหยิงดังนั้นฉันจึงใช้บทเรียนที่มีค่าจากนี้ คำถาม & คำตอบโดยไม่จำเป็นต้องเห็นด้วยกับสิ่งที่พิมพ์แบบไดนามิก)
Andres F.

2

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

ตอนนี้เป็นเวทีที่ Rich Hickey พอใจที่จะโยนลูกน้อยออกไปพร้อมกับอาบน้ำแล้วบอกว่าพวกเราทุกคนควรจะมีชีวิตอยู่ในดินแดนแห่งค่านิยม ฉันคิดว่าในมือที่ OOP สามารถและส่งเสริมการใช้ซ้ำ (และการค้นพบที่สำคัญซึ่งฉันพบว่าขาดในการเขียนโปรแกรมการทำงาน) เมื่อใช้อย่างรอบคอบ หากคุณกำลังมองหาหลักการ OOP ที่จับความตึงเครียดนี้ได้ดีที่สุดฉันคิดว่ามันอาจเป็นhttp://c2.com/cgi/wiki?TellDontAsk (ซึ่งแน่นอนว่าเป็นลูกพี่ลูกน้องของ Demeter)


คุณหมายถึงอะไรโดยการค้นพบ? มันคล้ายกับสิ่งนี้หรือไม่?

1
ใช่ฉันคิดว่ามันน่าประทับใจมาก มันเป็นจุดที่ลึกซึ้ง แต่การค้นพบเป็นการกระทำที่สมดุลทำให้สิ่งที่โปร่งใสเกินไปนั้นเป็นสิ่งที่ไม่พึงปรารถนาเช่นกันเพราะคุณจะได้อัตราส่วนสัญญาณต่อสัญญาณรบกวนที่ไม่ดี
CurtainDog
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.