ปัญหาเกี่ยวกับความเข้าใจคำว่า "ตะเข็บ"


20

ฉันกำลังอ่าน "การพึ่งพาการฉีดใน. NET" โดย Mark Seemann (มันยอดเยี่ยมและต้องมี) และผู้เขียนมักใช้คำว่า "ตะเข็บ" แต่ฉันไม่เข้าใจความหมาย นี่คือตัวอย่างของการใช้คำนี้:

บทที่ 7 อธิบายวิธีการเขียนวัตถุในเฟรมเวิร์กที่หลากหลายเช่น ASP.NET MVC, WPF, WCF และอื่น ๆ ไม่ใช่ทุกเฟรมเวิร์คที่สนับสนุน DI อย่างเท่าเทียมกันและแม้แต่ในบรรดาที่ทำวิธีที่พวกเขาทำแตกต่างกันมาก สำหรับแต่ละเฟรมเวิร์กอาจเป็นการยากที่จะระบุ SEAM ที่เปิดใช้ DI ในเฟรมเวิร์กนั้น อย่างไรก็ตามเมื่อพบว่า SEAM คุณมีทางออกสำหรับแอปพลิเคชันทั้งหมดที่ใช้กรอบงานนี้โดยเฉพาะ ในบทที่ 7 ฉันได้ทำงานนี้สำหรับกรอบงานแอพพลิเคชัน NET ที่ใช้กันทั่วไปมากที่สุดแล้ว คิดว่ามันเป็นแคตตาล็อกของกรอบ SEAMS

ฉันจะขอบคุณมากที่ช่วยฉันทำความเข้าใจกับคำนี้


3
มีคำแนะนำกับสิ่งที่หมายถึงคำที่มีบล็อกของผู้เขียน และเนื่องจากเขาเป็นสมาชิกที่นี่ : @MarkSeemann อันนี้เหมาะสำหรับคุณ :)
yannis

คำตอบ:


25

ฉันคิดว่าคำนี้มาจาก Michael Feathers ทำงานอย่างมีประสิทธิภาพด้วย Legacy Codeซึ่งเขาอธิบายตะเข็บในซอฟต์แวร์เป็นสถานที่ซึ่งซอฟต์แวร์สองส่วนมาบรรจบกันและที่อื่น ๆ ที่สามารถฉีดได้ การเปรียบเทียบเป็นรอยตะเข็บในเสื้อผ้า: สถานที่ที่เย็บสองส่วนเข้าด้วยกัน ชิ้นส่วนในแต่ละด้านเพียงสัมผัสอีกด้านขวาที่ตะเข็บ กลับไปที่ซอฟต์แวร์: หากคุณระบุตะเข็บคุณได้ระบุสถานที่ที่มีอินเตอร์เฟซที่กำหนดไว้อย่างดี นั่นคือสิ่งที่คุณสามารถใช้ประโยชน์ได้ใน DI เนื่องจากอินเตอร์เฟสดังกล่าวช่วยให้คุณสามารถแทนที่การใช้งานโดยไม่ต้องใช้ซอฟต์แวร์ที่เหลือสามารถบอกได้ (โดยไม่ต้องโกง)


7
c2.com/cgi/wiki?SoftwareSeam - เป็นข้อมูลอ้างอิงสำหรับผู้ที่ไม่มีหนังสือ
yannis

ฉันกำลังอ่านหนังสือเล่มนี้ตอนนี้!
Malfist

10
+1 FWIW ฉันแนะนำแนวคิดในหัวข้อ 1.3.1 ในหน้า 22
Mark Seemann

13

อาคารในคำตอบของคริสเตียนที่ดีที่สุดของความรู้ของฉันตะเข็บระยะไม่มาจากหนังสือ Feathers' การทำงานอย่างมีประสิทธิภาพกับรหัสมรดก คำจำกัดความอยู่ในหน้า 31:

ตะเข็บเป็นสถานที่ที่คุณสามารถเปลี่ยนพฤติกรรมในโปรแกรมของคุณโดยไม่ต้องแก้ไขในสถานที่นั้น

เพื่อให้ตัวอย่างของสิ่งที่ตะเข็บและมันคืออะไรไม่พิจารณารหัส Java ต่อไปนี้:

public class MyClass {
  private final Foo foo;

  public MyClass(Foo foo) {
    this.foo = foo;
  }

  public void doBunchOfStuff(BarFactory barFactory) {
    // foo.doStuff() is a seam because I can inject a mock instance of Foo
    this.foo.doStuff();

    // barFactory.makeBars() is a seam because I can replace the default
    // BarFactory instance with something else during testing
    List<Bar> bars = barFactory.makeBars();
    for(Bar bar : bars) {
      // bar.cut() is also a seam because if I can mock out BarFactory, then
      // I can get the mocked BarFactory to return mocked Bars.
      bar.cut();
    }

    // MyStaticClass.staticCall() is not a seam because I cannot replace
    // staticCall() with different behavior without calling a class besides
    // MyStaticClass, or changing the code in MyStaticClass.
    MyStaticClass.staticCall();

    // This is not a seam either because I can't change the behavior of what
    // happens when instanceCall() occurs with out changing this method or
    // the code in instanceCall().
    (new MyInstanceClass()).instanceCall();
  }
}

ตะเข็บแบบสุดขั้วด้านบนจะเป็นตะเข็บเว้นแต่:

  1. คลาสที่ถูกฉีดถือเป็นที่สิ้นสุด
  2. วิธีการที่ถูกเรียกนั้นถือเป็นที่สุด

โดยทั่วไปตะเข็บช่วยในการทดสอบหน่วย ฉันไม่สามารถเขียนการทดสอบหน่วยสำหรับMyClassเนื่องจากสายไปและMyStaticClass.staticCall() (new MyInstanceClass()).instanceCall()ทดสอบหน่วยใด ๆ สำหรับMyClass's doBunchOfStuff()วิธีการจะต้องมีการทดสอบMyStaticClass.staticCall()และ(new MyInstanceClass()).instanceCall()และทุกการอ้างอิงของพวกเขาที่ได้รับการเรียก ในทางกลับกันโดยการใช้คลาสที่ไม่เป็นขั้นสุดท้ายด้วยวิธีที่ไม่เป็นขั้นสุดท้าย (หรือดีกว่า - อินเทอร์เฟซ) อินสแตนซ์ที่ถูกฉีดของFooและBarFactoryทำการทดสอบหน่วยเพื่อMyClassให้สามารถเขียนได้โดยการเยาะเย้ย

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