ฉันจะลดความพยายามของผู้ใช้ในการห่อไลบรารี่ของบุคคลที่สามด้วยโมเดลวัตถุที่ใหญ่กว่าได้อย่างไร


16

เช่นเดียวกับผู้เขียนคำถามนี้ตั้งแต่ปี 2012 และอันนี้จากปี 2013ฉันมีห้องสมุดบุคคลที่สามที่ฉันต้องห่อเพื่อทดสอบใบสมัครของฉันอย่างถูกต้อง สถานะคำตอบยอดนิยม:

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

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

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


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


ภาษาโปรแกรมอะไรและห้องสมุดแบบไหนที่คุณพูดถึง?
Doc Brown

@DocBrown C # และไลบรารีการจัดการ PDF
Tom Wright

2
ฉันเริ่มโพสต์บนเมตาเพื่อค้นหาการสนับสนุนสำหรับการเปิดคำถามของคุณอีกครั้ง
Doc Brown

ขอบคุณ @DocBrown - ฉันหวังว่าจะมีมุมมองที่น่าสนใจออกมา
Tom Wright

1
เมื่อเราไม่ได้คำตอบที่ดีกว่าใน 48 ชั่วโมงข้างหน้าฉันจะวางรางวัลนี้
Doc Brown

คำตอบ:


4

สมมติว่าคุณไม่ได้มองหากรอบการเยาะเย้ยเพราะพวกมันมีความแพร่หลายและหาง่ายมีบางสิ่งที่ควรค่าแก่การสังเกต:

  1. มีสิ่งที่ "ไม่เคย" ที่คุณควร "เสมอ" ทำ
    การห่อห้องสมุดบุคคลที่สามนั้นไม่ใช่วิธีที่ดีที่สุดเสมอไป หากแอปพลิเคชันของคุณขึ้นอยู่กับไลบรารีหรือถ้ามันถูกสร้างขึ้นรอบ ๆ ไลบรารีหลักหนึ่งหรือสองไลบรารีอย่าเสียเวลาไปกับมัน หากห้องสมุดมีการเปลี่ยนแปลงใบสมัครของคุณจะต้องมีการเปลี่ยนแปลงต่อไป
  2. มันก็โอเคที่จะใช้การทดสอบการรวม
    นี่เป็นความจริงโดยเฉพาะอย่างยิ่งเกี่ยวกับขอบเขตที่มีความเสถียรเป็นธรรมชาติในแอปพลิเคชันของคุณหรือไม่สามารถเยาะเย้ยได้อย่างง่ายดาย หากพบเงื่อนไขเหล่านั้นการห่อและการเยาะเย้ยจะซับซ้อนและน่าเบื่อ ในกรณีนั้นฉันจะหลีกเลี่ยงทั้งสอง: อย่าห่อและไม่ล้อเลียน; เพียงแค่เขียนการทดสอบการรวม (หากการทดสอบอัตโนมัติเป็นเป้าหมาย)
  3. เครื่องมือและกรอบงานไม่สามารถกำจัดความซับซ้อนเชิงตรรกะได้
    โดยหลักการแล้วเครื่องมือสามารถตัดลงบนแผ่นความร้อน แต่ไม่มีอัลกอริธึมที่สามารถทำได้โดยอัตโนมัติสำหรับการใช้อินเทอร์เฟซที่ซับซ้อนและทำให้เป็นเรื่องง่าย - ให้ใช้อินเทอร์เฟซ X อย่างเดียวและปรับให้เหมาะกับความต้องการของคุณ (เพียงคุณเท่านั้นที่รู้ว่าอัลกอริทึม!) ดังนั้นในขณะที่มีอย่างไม่ต้องสงสัยเครื่องมือที่สามารถสร้างห่อบางผมขอแนะนำว่าพวกเขาไม่ได้อยู่แพร่หลายเพราะในท้ายที่สุดแล้วคุณยังคงต้องรหัสเพียงอย่างชาญฉลาดและดังนั้นจึงตนเอง กับอินเทอร์เฟซแม้ว่าจะซ่อนอยู่ด้านหลัง wrapper

ที่กล่าวว่ามีกลยุทธ์ที่คุณสามารถใช้ในหลายภาษาเพื่อหลีกเลี่ยงการอ้างอิงโดยตรงกับชั้นเรียน และในบางกรณีคุณสามารถ "ปลอมแปลง" อินเทอร์เฟซหรือเสื้อคลุมบาง ๆ ที่ไม่มีอยู่จริง ตัวอย่างเช่นใน C # ฉันจะไปหนึ่งในสองเส้นทาง:

  1. ใช้โรงงานและการพิมพ์โดยปริยาย

คุณสามารถหลีกเลี่ยงความพยายามในการห่อคลาสที่ซับซ้อนด้วยคอมโบเล็ก ๆ น้อย ๆ นี้:

// "factory"
class PdfDocumentFactory {
  public static ExternalPDFLibraryDocument Build() {
    return new ExternalPDFLibraryDocument();
  }
}

// code that uses the factory.
class CoreBusinessEntity {
  public void DoImportantThings() {
    var doc = PdfDocumentFactory.Build();

    // ... i have no idea what your lib does, so, I'm making stuff but.
    // but, you can do whatever you want here without explicitly
    // referring to the library's actual types.
    doc.addHeader("Wee");
    doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
    return doc.exportBinaryStreamOrSomething();
  }
}

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

สิ่งที่จำเป็นต้องมีก็คือในเวลารวบรวมคลาสที่โรงงานของคุณส่งคืนมีวิธีการที่วัตถุทางธุรกิจของคุณใช้

  1. ใช้พิมพ์แบบไดนามิก

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

class CoreBusinessEntity {
  dynamic Doc;

  public void InjectDoc(dynamic Doc) {
    Doc = doc;
  }

  public void DoImortantThings() {
    Doc.addHeader("Wee");
    Doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
    return Doc.exportBinaryStreamOrSomething();
  }
}

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

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

  1. ไลบรารีเฉพาะไม่ได้อยู่ภายในแอปพลิเคชัน
  2. มันจะมีราคาแพงมากในการสลับโดยไม่ต้องปิด
  3. ฉันไม่ชอบ API เอง

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

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

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

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

คิดแบบนี้

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

TLDR

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

และถ้าเป็นอย่างนั้นอย่ากลัวการทดสอบบูรณาการ พวกมันช่างคลุมเครือเล็กน้อย แต่พวกเขายังคงมีหลักฐานของรหัสการทำงานและพวกเขาก็ยังสามารถสร้างขึ้นเพื่อรักษาความถดถอยได้อย่างง่ายดาย


2
นี่เป็นอีกโพสต์ที่ไม่ตอบคำถาม - ซึ่งไม่ชัดเจน"เมื่อต้องการปิด" แต่ "วิธีลดความพยายามด้วยตนเอง"
Doc Brown

1
ขออภัยฉันคิดว่าคุณพลาดจุดสำคัญของคำถาม ผมไม่เห็นว่าคำแนะนำของคุณสามารถลดใด ๆคู่มือความพยายามในการตัด สมมติว่า lib in เสามีรูปแบบวัตถุที่ซับซ้อนเป็น API กับชั้นเรียนหลายสิบและหลายร้อยวิธี API ของมันใช้ได้ดีสำหรับการใช้งานมาตรฐาน แต่จะห่อมันสำหรับการทดสอบหน่วยด้วยความเจ็บปวด / ความพยายามน้อยลงได้อย่างไร
Doc Brown

1
TLDR; หากคุณต้องการคะแนนโบนัสบอกสิ่งที่เรายังไม่ทราบ ;-)
Doc Brown

1
@DocBrown ฉันไม่ได้พลาดจุด แต่ฉันคิดว่าคุณพลาดจุดที่จะตอบ การลงทุนความพยายามที่ถูกต้องช่วยให้คุณประหยัดเวลาได้มาก มีผลการทดสอบ - แต่นั่นเป็นเพียงผลข้างเคียง การใช้เครื่องมือในการสร้างเสื้อคลุมบาง ๆ โดยอัตโนมัติยังคงทำให้คุณสร้างไลบรารี่หลักของคุณกับ API ของคนอื่นและสร้าง mocks - ซึ่งเป็นความพยายามอย่างมากที่ไม่สามารถหลีกเลี่ยงได้หากคุณยืนกรานที่จะออกจากไลบรารี่ จากการทดสอบของคุณ
svidgen

1
@DocBrown นี่เป็นเรื่องไร้สาระ "ปัญหาระดับนี้มีระดับของเครื่องมือหรือวิธีการหรือไม่" ใช่. แน่นอนมันไม่ การเข้ารหัสป้องกันและไม่ได้รับความเชื่อเกี่ยวกับการทดสอบหน่วย ... เหมือนคำตอบของฉันพูดว่า หากคุณไม่ได้มีเสื้อคลุมบาง ๆ ที่สร้างขึ้นโดยอัตโนมัติ, สิ่งที่มีค่าก็จะให้ !? ... มันไม่อนุญาตให้คุณฉีดการอ้างอิงเพื่อทดสอบคุณยังต้องทำด้วยตนเอง และมันจะไม่อนุญาตให้คุณสลับไลบรารีออกเพราะคุณยังคงเขียนโค้ดกับ API ของไลบรารี ... ตอนนี้เป็นเพียงทางอ้อม
svidgen

9

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

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

บางครั้งการทดสอบการรวมกันนั้นดีกว่าการทดสอบหน่วยในบางส่วนของแอปพลิเคชันของคุณ ห่วงต้องผ่านเพื่อให้รหัส "ทดสอบ" บางครั้งอาจเป็นอันตราย


2
สิ่งแรกที่ฉันคิดว่าเมื่อฉันอ่านคำตอบของคุณคือ "ไม่สมจริงสำหรับ PDF เนื่องจากการเปรียบเทียบไฟล์ในระดับไบนารีไม่ได้บอกคุณว่ามีการเปลี่ยนแปลงหรือหากการเปลี่ยนแปลงมีปัญหา" จากนั้นฉันพบโพสต์ SO เก่ากว่านี้แสดงว่าจริง ๆ แล้วอาจใช้งานได้ (ดังนั้น +1)
Doc Brown

@DocBrown เครื่องมือในลิงก์ SO ไม่ได้เปรียบเทียบไฟล์ PDF ในระดับไบนารี มันเปรียบเทียบโครงสร้างและเนื้อหาของหน้า โครงสร้างภายใน Pdf: safaribooksonline.com/library/view/pdf-explained/9781449321581/…
linuxunil

1
@ linuxunil: ใช่ฉันรู้ว่าอย่างที่ฉันเขียนก่อนอื่นฉันคิดว่า ... แต่แล้วฉันก็พบวิธีการแก้ปัญหาดังกล่าวข้างต้น
Doc Brown

โอ้ .. ฉันเห็นแล้ว .. บางทีคำว่า 'อาจใช้งานได้จริง' ในตอนท้ายของคำตอบของคุณทำให้ฉันสับสน
linuxunil

1

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

ฉันเห็นว่าเรากำลังเล่นกับเทคโนโลยี. NET ดังนั้นเราจึงมีความสามารถในการสะท้อนที่มีประสิทธิภาพในมือของเรา คุณอาจพิจารณา:

  1. เครื่องมือเช่น.NET Wrapper ชั้นปั่นไฟ ฉันไม่ได้ใช้เครื่องมือนี้และฉันรู้ว่ามันทำงานบนเทคโนโลยีสแต็คแบบดั้งเดิม แต่อาจเหมาะกับกรณีของคุณ แน่นอนว่าคุณภาพของรหัสการสนับสนุนการแยกการพึ่งพาและการแยกอินเทอร์เฟซควรได้รับการตรวจสอบแยกต่างหาก อาจมีเครื่องมืออื่น ๆ เช่นนั้น แต่ฉันไม่ได้ค้นหามากนัก
  2. การเขียนเครื่องมือของคุณเองซึ่งจะค้นหาในแอสเซมบลีอ้างอิงสำหรับวิธีสาธารณะ / อินเทอร์เฟซและทำการแมปและสร้างรหัส การมีส่วนร่วมกับชุมชนจะเป็นมากกว่าการต้อนรับ!
  3. หาก .NET ไม่ได้เป็นกรณี ... อาจจะดูที่นี่

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

สร้างแอปพลิเคชันของคุณกับส่วนต่อประสานที่คุณต้องการ ไม่ใช่กับ API ของบุคคลที่สาม


ตกลงอย่างน้อยความคิดว่าปัญหาที่เกิดขึ้นอาจจะได้รับการจัดการ แต่ไม่ได้ขึ้นอยู่กับประสบการณ์ของตัวเองสำหรับกรณีการใช้งานนี้ฉันถือว่า?
Doc Brown

คำถามขึ้นอยู่กับประสบการณ์ของตัวเองเกี่ยวกับโดเมนวิศวกรรมซอฟต์แวร์ (wrapper, reflection, di)! เกี่ยวกับเครื่องมือ - ฉันไม่ได้ใช้สิ่งที่ระบุไว้ใน asnwer
tom3k

0

ทำตามคำแนะนำเหล่านี้เมื่อสร้างไลบรารี wrapper:

  • เปิดเผยเพียงส่วนย่อยของห้องสมุดบุคคลที่สามที่คุณต้องการในขณะนี้ (และขยายตามต้องการ)
  • เก็บเสื้อคลุมให้บางที่สุด (ไม่มีตรรกะอยู่ที่นั่น)

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