การฉีดพึ่งพาและวิธีการแบบคงที่


21

ฉันมีการสนทนาที่น่าสนใจในวันนี้กับผู้พัฒนารายอื่นเกี่ยวกับวิธีการเข้าเรียนด้วยวิธีการที่ยอมรับสตริงและเอาต์พุตสตริง

ลองนึกภาพบางสิ่งเช่นสิ่งต่อไปนี้ซึ่งสร้างขึ้นโดยสมบูรณ์เพื่อเป็นตัวอย่าง

public string GetStringPart(string input)
{ 
   //Some input validation which is removed for clarity

   if(input.Length > 5)
        return input.Substring(0,1);

   if(input.Substring(0,1) == "B")
        return input.Substring(0,3);

   return string.empty;
}

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


1
@Ewan สำหรับวิธีการช่วยเหลือที่ไม่มีประโยชน์สำหรับสิ่งที่เป็นนามธรรม ตัวอย่าง: Apache FileUtils
Walfrat

3
@Ewan: วิธีคงที่ไม่มีผลข้างเคียงเป็นวิธีที่ดีที่สุดเพราะง่ายต่อการเข้าใจและทดสอบง่าย
JacquesB

1
แต่พวกเขาทำให้มันเป็นไปไม่ได้ที่จะทดสอบสิ่งต่าง ๆ ที่ขึ้นอยู่กับพวกเขา
Ewan

3
@Ewan Eh ไม่ได้จริงๆ Math.Max ​​() ไม่ดีเพราะคงที่หรือไม่ หากคุณทดสอบวิธีการคงที่และใช้งานได้คุณสามารถใช้วิธีการอื่นอย่างปลอดภัยโดยไม่มีปัญหา หากแบบคงที่ล้มเหลวการทดสอบจะจับมัน
T. Sar - Reinstate Monica

1
หาก 'คงที่' รับประกันว่าไม่มีผลข้างเคียงฉันอาจจะสามารถเห็นการโต้แย้ง แต่มันก็ไม่ได้
Ewan

คำตอบ:


25

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

ไม่จำเป็นต้องแยกฟังก์ชั่นที่เป็นนามธรรมออกโดยไม่ต้องพึ่งพามันมากเกินไป

หากสิ่งนี้ซับซ้อนมากขึ้นอาจส่งผ่านอินเทอร์เฟซไปยังตัวสร้างหรือวิธีการรับประกัน แต่ฉันจะไม่ลงไปตามถนนนั้นเว้นแต่ฉันจะมีGetStringPartตรรกะที่ซับซ้อนตามสถานที่ ฯลฯ


2
นี่คือคำตอบที่ถูกต้อง! คำตอบของลัทธิคาร์โก้ได้รับการยอมรับ
JacquesB

3
ฟังก์ชั่นนั้นไม่มีการพึ่งพาไม่ใช่จุด ปัญหาคือเมื่อสิ่งอื่น ๆ ขึ้นอยู่กับฟังก์ชั่นและกลายเป็นคู่อย่างแน่นแฟ้นกับมัน
Ewan

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

1
โดยทั่วไปผู้คนที่พูดถึงการฉีดพึ่งพาเว็บไซต์นี้ไม่จำเป็นต้องฉีดพึ่งพา ดังนั้นอคติต่อความซับซ้อนที่ไม่จำเป็น
Frank Hileman

2
@James หากฟังก์ชั่นนั้นบริสุทธิ์น้อยลงแสดงว่าคุณกำลังทำอะไรผิดพลาดและฟังก์ชั่นนั้นอาจไม่ได้รับการนิยามอย่างชัดเจนตั้งแต่เริ่มต้น การคำนวณพื้นที่ของรูปสี่เหลี่ยมไม่ควรต้องมีการเรียกฐานข้อมูลหรือปรับใช้การปรับปรุงด้วยภาพสำหรับ UI คุณลองนึกภาพสถานการณ์ที่วิธีการ "ซับสตริง" แปลก ๆ เกิดขึ้นได้อย่างไร?
T. Sar - Reinstate Monica

12

นี่คือเหตุผล

class DOSClient {
    OrderParser orderParser;
    string orderCode;

    DOSClient(OrderParser orderParser, string ordercode) { 
        this.orderParser = orderParser; 
        this.ordercode = ordercode;
    }
    void DisplayOrderCode() {
        Console.Write( "Prefix: " + orderParser.GetStringPart(ordercode) ); 
        ...
    }
}

class GUIClient {
    OrderParser orderParser;
    string orderCode;
    GUI gui;

    GUIClient(OrderParser orderParser, string ordercode, GUI gui) { 
        this.orderParser = orderParser; 
        this.ordercode = ordercode;
        this.gui = gui;
    }

    void DisplayOrderCode() {
        gui.Prefix( orderParser.GetStringPart(ordercode) ); 
        ...
    }
}

 

class OrderParserUS : IOrderParser {

    public string GetStringPart(string input)
    { 
        //Some input validation which is removed for clarity

        if(input.Length > 5)
            return input.Substring(0,1);

        if(input.Substring(0,1) == "B")
            return input.Substring(0,3);

        return string.empty;
    }
}

class OrderParserEU : IOrderParser {

    public string GetStringPart(string input)
    { 
        //Some input validation which is removed for clarity

        if(input.Length > 6)
            return input.Substring(0,1);

        if(input.Substring(0,1) == "#")
            return input.Substring(0,3);

        return string.empty;
    }
}

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

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

ถ้านั่นไม่ได้มีความหมายอะไรกับคุณนั่นก็ไม่ใช่เหตุผลที่ดีสำหรับเรื่องนี้

BTW GetStringPartเป็นชื่อที่แย่มาก


* Cringe ในรูปแบบรหัสวงเล็บ * ฉันเดาว่าคุณเป็นโปรแกรมเมอร์ Java ที่พยายามเขียนโค้ด C # ใช่ไหม ทำให้คนอื่นรู้ว่าฉันคิด :)
Neil

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

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

คุณพูดstatic getStringPartEU()ไม่ได้เหรอ? ตัวอย่างของคุณเหมาะสมแล้วหากมีวิธีการอื่นในชั้นเรียนนั้นที่ต้องการการรักษาแบบพิเศษจากสหภาพยุโรปและต้องได้รับการปฏิบัติเป็นหน่วยเดียว
Robert Harvey

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