การจัดการการพึ่งพาเป็นปัญหาใหญ่ใน OOP ด้วยเหตุผลสองประการต่อไปนี้:
- การมีเพศสัมพันธ์อย่างแน่นหนาของข้อมูลและรหัส
- การใช้ผลข้างเคียงอย่างแพร่หลาย
โปรแกรมเมอร์ OO ส่วนใหญ่พิจารณาว่าการเชื่อมโยงข้อมูลและรหัสอย่างแน่นหนาจะเป็นประโยชน์อย่างเต็มที่ แต่ก็มาพร้อมกับค่าใช้จ่าย การจัดการการไหลของข้อมูลผ่านเลเยอร์เป็นส่วนที่หลีกเลี่ยงไม่ได้ของการเขียนโปรแกรมในกระบวนทัศน์ใด ๆ การรวมข้อมูลและรหัสของคุณจะเป็นการเพิ่มปัญหาเพิ่มเติมที่ถ้าคุณต้องการใช้ฟังก์ชั่นณ จุดหนึ่งคุณต้องหาวิธีที่จะทำให้วัตถุนั้นอยู่ในจุดนั้น
การใช้ผลข้างเคียงทำให้เกิดปัญหาที่คล้ายกัน หากคุณใช้ผลข้างเคียงสำหรับฟังก์ชั่นบางอย่าง แต่ต้องการที่จะสลับการใช้งานไปได้คุณแทบไม่มีทางเลือกอื่นนอกจากต้องพึ่งพาการใช้งานนั้น
พิจารณาเป็นตัวอย่างโปรแกรมสแปมเมอร์ที่ scrapes หน้าเว็บสำหรับที่อยู่อีเมลจากนั้นส่งอีเมลถึงพวกเขา หากคุณมีความคิด DI ตอนนี้คุณกำลังคิดถึงบริการที่คุณจะแค็ปซูลหลังส่วนต่อประสานและบริการใดจะถูกฉีดเข้าไปที่ใด ฉันจะปล่อยให้การออกแบบนั้นเป็นแบบฝึกหัดสำหรับผู้อ่าน หากคุณมีความคิด FP ตอนนี้คุณกำลังคิดถึงอินพุตและเอาต์พุตสำหรับเลเยอร์ที่ต่ำที่สุดของฟังก์ชันเช่น:
- ป้อนที่อยู่หน้าเว็บเอาท์พุทข้อความของหน้านั้น
- ป้อนข้อความของหน้าออกรายการลิงก์จากหน้านั้น
- ป้อนข้อความของหน้าออกรายการที่อยู่อีเมลในหน้านั้น
- ป้อนรายการที่อยู่อีเมลส่งออกรายการที่อยู่อีเมลโดยลบรายการที่ซ้ำกัน
- ป้อนที่อยู่อีเมลส่งอีเมลสแปมสำหรับที่อยู่นั้น
- ป้อนอีเมลสแปมออกคำสั่ง SMTP เพื่อส่งอีเมลนั้น
เมื่อคุณคิดในแง่ของอินพุตและเอาต์พุตไม่มีการขึ้นต่อกันของฟังก์ชันการพึ่งพาข้อมูลเท่านั้น นั่นคือสิ่งที่ทำให้ง่ายต่อการทดสอบหน่วย เลเยอร์ถัดไปของคุณจัดเรียงเอาท์พุทของฟังก์ชั่นหนึ่งที่จะป้อนเข้าของอินพุทถัดไปและสามารถสลับการใช้งานต่าง ๆ ตามที่ต้องการได้อย่างง่ายดาย
ในความเป็นจริงการเขียนโปรแกรมที่ใช้งานได้ตามธรรมชาติจะทำให้คุณคว่ำการพึ่งพาฟังก์ชั่นของคุณเสมอและดังนั้นโดยปกติคุณไม่จำเป็นต้องใช้มาตรการพิเศษใด ๆ เมื่อคุณทำเช่นนั้นเครื่องมือเช่นฟังก์ชั่นลำดับสูงกว่าการปิดและแอพพลิเคชั่นบางส่วนจะช่วยให้ทำสำเร็จได้ง่ายขึ้นโดยใช้แผ่นเหล็กที่น้อยกว่า
โปรดทราบว่าไม่ใช่การพึ่งพาตัวเองที่เป็นปัญหา มันเป็นการพึ่งพาที่ชี้ทางที่ผิด เลเยอร์ถัดไปขึ้นอาจมีฟังก์ชันดังนี้:
processText = spamToSMTP . emailAddressToSpam . removeEmailDups . textToEmailAddresses
มันก็โอเคอย่างสมบูรณ์แบบสำหรับเลเยอร์นี้ที่จะมีรหัสอ้างอิงที่ยากเช่นนี้เพราะจุดประสงค์เพียงอย่างเดียวก็เพื่อยึดฟังก์ชันชั้นล่างไว้ด้วยกัน การสลับการนำไปปฏิบัตินั้นง่ายเหมือนการสร้างองค์ประกอบที่แตกต่าง:
processTextFancy = spamToSMTP . emailAddressToFancySpam . removeEmailDups . textToEmailAddresses
การจัดระเบียบใหม่นี้ทำได้โดยไม่มีผลข้างเคียง ฟังก์ชั่นเลเยอร์ที่ต่ำกว่าเป็นอิสระจากกันอย่างสมบูรณ์ เลเยอร์ถัดไปอาจเลือกสิ่งที่processText
ใช้จริงตามการกำหนดค่าผู้ใช้บางอย่าง:
actuallyUsedProcessText = if (config == "Fancy") then processTextFancy else processText
ไม่ใช่ปัญหาเนื่องจากการอ้างอิงทั้งหมดชี้ทางเดียว เราไม่จำเป็นต้องสลับการพึ่งพาบางอย่างเพื่อให้พวกเขาชี้ไปในทางเดียวกันเพราะฟังก์ชั่นที่บริสุทธิ์ได้บังคับให้เราทำเช่นนั้น
โปรดทราบว่าคุณสามารถทำสิ่งนี้ได้มากขึ้นควบคู่ไปกับการส่งconfig
ผ่านไปยังเลเยอร์ต่ำสุดแทนที่จะตรวจสอบที่ด้านบน FP ไม่ได้ป้องกันไม่ให้คุณทำสิ่งนี้ แต่มีแนวโน้มที่จะทำให้มันน่ารำคาญมากขึ้นถ้าคุณลอง