คงเป็น "ความชั่วร้าย" ในระดับสากลสำหรับการทดสอบหน่วยและถ้าเป็นเช่นนั้นทำไม Resharper จึงแนะนำ [ปิด]


85

ฉันได้พบว่ามีเพียง 3 วิธีในการทดสอบหน่วยอ้างอิง (จำลอง / ต้นขั้ว) ที่คงที่ใน C # .NET:

เนื่องจากว่าสองสิ่งนี้ไม่ฟรีและไม่มีการปล่อยรุ่น 1.0 การเยาะเย้ยสิ่งคงไม่ง่ายเกินไป

นั่นทำให้วิธีการคงที่และ "ความชั่วร้าย" (ในแง่การทดสอบหน่วย) หรือไม่? และถ้าเป็นเช่นนั้นทำไม resharper จึงต้องการให้ฉันทำอะไรที่คงที่ (การสมมติว่า resharper ไม่ได้เป็น "ความชั่วร้าย" ด้วย)

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


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

26
โดยส่วนตัวฉันคิดว่าคุณกำลังนิยาม "หน่วย" มากเกินไป "หน่วย" ควรเป็น "หน่วยที่เล็กที่สุดที่เหมาะสมสำหรับการทดสอบแบบแยก" นั่นอาจเป็นวิธีหนึ่งที่อาจเป็นมากกว่านั้น หากวิธีการแบบสเตติกไม่มีสถานะและผ่านการทดสอบอย่างดีดังนั้นให้ทดสอบหน่วยที่สองเรียกว่า (IMO) ไม่ใช่ปัญหา
mlk

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

7
"ทำไม resharper ต้องการให้ฉันทำอะไรที่คงที่ Resharper ไม่ต้องการให้คุณทำอะไร เป็นเพียงการทำให้คุณทราบว่าการแก้ไขเป็นไปได้และอาจเป็นที่ต้องการจาก POV การวิเคราะห์รหัส Resharper ไม่ใช่สิ่งทดแทนคำพิพากษาของคุณ!
Adam Naylor

4
@ acidzombie24 วิธีการปกติสามารถปรับเปลี่ยนสถานะคงที่ด้วยดังนั้นพวกเขาก็จะเป็น "ไม่ดี" เป็นวิธีการคงที่ ความจริงที่ว่าพวกเขาสามารถปรับเปลี่ยนสถานะด้วยวงจรชีวิตที่สั้นลงทำให้พวกเขาอันตรายยิ่งขึ้น (ฉันไม่ชอบวิธีการแบบคงที่ แต่ประเด็นเกี่ยวกับการปรับเปลี่ยนสถานะก็เป็นวิธีการทั่วไปเช่นกัน)
mike30

คำตอบ:


105

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

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


44
วิธีสแตติกเป็นหน่วยที่ทดสอบได้ แต่วิธีใดที่เรียกเมธอดสแตติก? หากผู้โทรอยู่ในชั้นเรียนอื่นพวกเขามีการพึ่งพาที่ต้องแยกออกเพื่อทำการทดสอบหน่วย
Vaccano

22
@Vaccano: แต่ถ้าคุณเขียนวิธีการคงที่ที่ไม่ได้อยู่ในสถานะและไม่มีผลข้างเคียงพวกเขาจะทำงานได้มากขึ้นหรือน้อยลงเทียบเท่ากับต้นขั้ว
Robert Harvey

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

20
@Vaccano: วิธีการคงที่ที่มีผลลัพธ์หรือข้อยกเว้นแบบสุ่มมีผลข้างเคียง
Tikhon Jelvis

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

26

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

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

public static long Square(int x)
{
    return x * x;
}

จากนั้นจึงสามารถทดสอบได้อย่างชัดเจนและไม่มีผลข้างเคียง คุณแค่ตรวจสอบว่าเมื่อคุณผ่านพูด 20 คุณได้ 400 กลับไม่มีปัญหา


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

3
ไม่มีอะไรเกิดขึ้น. ทำไมมันจะ? . NET Framework เต็มไปด้วยวิธีการคงที่ คุณกำลังบอกว่าคุณไม่สามารถใช้สิ่งเหล่านี้ในวิธีใดก็ตามที่คุณต้องการทดสอบหน่วย?
Dan Diplo

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

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

6
@Vaccano แล้ว Microsoft จะทดสอบ. NET Framework อย่างไรใช่มั้ย หลายคลาสใน Framework อ้างอิงวิธีการคงที่ในคลาสอื่น ๆ (เช่นSystem.Math) ไม่ต้องพูดถึงความอุดมสมบูรณ์ของวิธีการคงที่จากโรงงานเป็นต้นนอกจากนี้คุณจะไม่สามารถใช้วิธีการขยายใด ๆ ได้ ฯลฯ ความจริงก็คือฟังก์ชั่นง่าย ๆ เช่นนี้ ภาษาเบื้องต้น คุณสามารถทดสอบสิ่งเหล่านี้แยกได้ (เนื่องจากโดยทั่วไปจะถูกกำหนดไว้แล้ว) จากนั้นใช้ในชั้นเรียนของคุณโดยไม่ต้องกังวล มันไม่ใช่ปัญหา!
Dan Diplo

18

หากคำถามจริงที่นี่คือ "ฉันจะทดสอบรหัสนี้ได้อย่างไร":

public class MyClass
{
   public void MethodToTest()
   {
       //... do something
       MyStaticClass.StaticMethod();
       //...more
   }
}

จากนั้นเพียงแค่ refactor รหัสและฉีดตามปกติการเรียกคลาสแบบคงที่เช่นนี้:

public class MyClass
{
   private readonly IExecutor _externalExecutor;
   public MyClass(_IExecutor executor)
   {
       _exeternalExecutor = executor;
   }

   public void MethodToTest()
   {
       //... do something
       _exetrnalExecutor.DoWork();
       //...more
   }
}

public class MyStaticClassExecutor : IExecutor
{
    public void DoWork()
    {
        MyStaticClass.StaticMethod();
    }
}

9
โชคดีที่เรามีคำถามเกี่ยวกับการอ่านโค้ดและ KISS บน SO ด้วยเช่นกัน :)
gbjbaanb

ผู้รับมอบสิทธิ์จะไม่ง่ายขึ้นและทำสิ่งเดียวกันหรือไม่
jk

@jk อาจเป็น แต่มันยากที่จะใช้คอนเทนเนอร์ IoC แล้ว
ซันนี่

15

สถิตไม่จำเป็นต้องชั่ว แต่พวกเขาสามารถ จำกัด ตัวเลือกของคุณเมื่อมันมาถึงการทดสอบหน่วยกับปลอม / mocks / ต้นขั้ว

มีวิธีการทั่วไปสองวิธีในการเยาะเย้ย

คนแรก (แบบดั้งเดิม - ดำเนินการโดย RhinoMocks, Moq, NMock2; mocks และตอไม้ด้วยตนเองอยู่ในค่ายนี้ด้วย) อาศัยการทดสอบตะเข็บและการฉีดพึ่งพา สมมติว่าคุณกำลังทดสอบโค้ดคงที่บางหน่วยและมีการอ้างอิง สิ่งที่มักจะเกิดขึ้นในรหัสที่ได้รับการออกแบบด้วยวิธีนี้เป็นที่สถิตสร้างการพึ่งพาตัวเอง inverting ผกผันพึ่งพา ในไม่ช้าคุณจะค้นพบว่าคุณไม่สามารถฉีดอินเทอร์เฟซที่เยาะเย้ยลงในรหัสภายใต้การทดสอบที่ออกแบบมาด้วยวิธีนี้

คนที่สอง (เยาะเย้ยอะไร - ดำเนินการโดย TypeMock, JustMock และโมล) อาศัย .NET ของProfiling API มันสามารถดักคำสั่ง CIL ใด ๆ ของคุณและแทนที่โค้ดของคุณด้วยปลอม สิ่งนี้ทำให้ TypeMock และผลิตภัณฑ์อื่น ๆ ในค่ายนี้เยาะเย้ยอะไรก็ได้: สถิตยศาสตร์ชั้นเรียนที่ปิดสนิทวิธีส่วนตัว - สิ่งที่ไม่ได้ออกแบบมาให้ทดสอบได้

มีการถกเถียงกันอย่างต่อเนื่องระหว่างโรงเรียนแห่งความคิดสองแห่ง หนึ่งกล่าวว่าปฏิบัติตามหลักการและการออกแบบเพื่อการทดสอบความทนทาน (ซึ่งมักจะรวมถึงสถิตยศาสตร์) อีกอันหนึ่งบอกว่าซื้อ TypeMock และไม่ต้องกังวล


14

ตรวจสอบนี้: "วิธีการคงเป็นความตายที่จะตรวจสอบได้" สรุปสั้น ๆ ของการโต้แย้ง:

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


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

4
@ Robert Harvey - คุณจะทดสอบวิธีที่ใช้วิธี static จากคลาสอื่นได้อย่างไร (เช่นมีการพึ่งพา method แบบคงที่) หากคุณเพียงแค่ปล่อยให้มันเรียกว่าคุณไม่ได้เป็น "การทดสอบหน่วย" คุณเป็น "การทดสอบการรวม"
Vaccano

10
อย่าเพิ่งอ่านบทความบล็อกอ่านความคิดเห็นมากมายที่ไม่เห็นด้วย บล็อกเป็นเพียงความเห็นไม่ใช่ความจริง
Dan Diplo

8
@Vaccano: วิธีคงที่ไม่มีผลข้างเคียงหรือสถานะภายนอกเทียบเท่ากับค่า รู้ว่ามันไม่แตกต่างจากหน่วยทดสอบวิธีการที่สร้างจำนวนเต็ม นี่เป็นหนึ่งในข้อมูลเชิงลึกที่สำคัญที่การเขียนโปรแกรมการทำงานให้เรา
Steven Evers

3
ข้อ จำกัด ของระบบฝังตัวทำงานหรือแอพที่มีข้อบกพร่องที่มีศักยภาพในการสร้างเหตุการณ์ระหว่างประเทศ IMO เมื่อ "testability" ผลักดันสถาปัตยกรรมคุณต้องบิดมันก่อนที่คุณจะนำวิธีการทดสอบทุกมุม - สุดท้ายมาใช้เป็นครั้งแรก นอกจากนี้ฉันเบื่อกับ XP ทุกอย่างที่ครอบครองทุกบทสนทนา XP ไม่ใช่ผู้มีอำนาจ แต่เป็นอุตสาหกรรม ต่อไปนี้เป็นคำจำกัดความดั้งเดิมที่สมเหตุสมผลของการทดสอบหน่วย: python.net/crew/tbryan/UnitTestTalk/slide2.html
Erik Reppen

5

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

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

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

ระบุว่ามีสามตัวเลือก:

  1. กำหนดการทดสอบหน่วยที่จะทดสอบหน่วยประกอบด้วยคลาสและเป็นการอ้างอิงแบบกำหนดค่าตายตัว วิธีนี้ใช้ได้ผลให้คุณหลีกเลี่ยงการพึ่งพาแบบวนซ้ำ

  2. อย่าสร้างการพึ่งพาเวลารวบรวมระหว่างคลาสที่คุณรับผิดชอบการทดสอบ วิธีนี้ใช้ได้ผลโดยที่คุณไม่ต้องสนใจรูปแบบโค้ดที่ได้

  3. อย่าทดสอบหน่วยรวมการทดสอบการรวมแทน ใช้งานได้จริงหากไม่ขัดแย้งกับสิ่งอื่นที่คุณต้องใช้ในการทดสอบการรวมระบบ


3
ไม่มีอะไรที่บอกว่าการทดสอบหน่วยเป็นการทดสอบในชั้นเรียนเดียว มันคือการทดสอบของหน่วยเดียว คุณสมบัติการกำหนดของการทดสอบหน่วยคือมีความรวดเร็วทำซ้ำและเป็นอิสระ การอ้างอิงMath.Piในเมธอดไม่ได้เป็นการทดสอบการรวมโดยนิยามที่สมเหตุสมผล
sara

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

4

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

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

ก่อน:

    public static DBConnection ConnectToDB( string dbName, string connectionInfo ) {
    }

หลังจาก:

    public static Func<string, string, DBConnection> ConnectToDB (dbName, connectionInfo ) {
    };

ทั้งสองเข้ากันได้กับการโทร ผู้โทรไม่จำเป็นต้องเปลี่ยน ร่างกายของฟังก์ชั่นยังคงเหมือนเดิม

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

        Database.ConnectToDB = (dbName, connectionInfo) => { return null|whatever; }

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

    [TestCleanup]
    public void Cleanup()
    {
        typeof(Database).TypeInitializer.Invoke(null, null);
    }

ซึ่งจะเรียกใช้ initializer คงที่ของคลาสของคุณอีกครั้ง

แลมบ์ดาฟันซ์ไม่ได้รับการสนับสนุนมากมายเหมือนวิธีการคงที่ทั่วไปดังนั้นวิธีนี้จึงมีผลข้างเคียงที่ไม่พึงประสงค์ดังต่อไปนี้:

  1. หากวิธีสแตติกเป็นวิธีส่วนขยายคุณต้องเปลี่ยนเป็นวิธีที่ไม่ใช่ส่วนขยายก่อน Resharper สามารถทำสิ่งนี้ให้คุณโดยอัตโนมัติ
  2. ถ้าชนิดข้อมูลใด ๆ ของวิธีการแบบคงที่มีแอสเซมบลีที่ฝังตัว interop เช่นสำหรับ Office คุณต้องตัดวิธีการตัดคำชนิดหรือเปลี่ยนเป็นชนิด 'วัตถุ'
  3. คุณไม่สามารถใช้เครื่องมือการเปลี่ยนโครงสร้างการเปลี่ยนลายเซ็นของ Resharper ได้อีกต่อไป

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

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

เหตุใด C # จึงมีวิธีคงที่ ทำไมจึงอนุญาตให้ใช้วิธีการที่ไม่ใช่เสมือนได้

หากคุณใช้ "ฟีเจอร์" เหล่านี้คุณจะไม่สามารถสร้างวิธีแยกได้

แล้วคุณจะใช้มันเมื่อไหร่?

ใช้รหัสดังกล่าวที่คุณไม่ต้องการให้ใครออกไป ตัวอย่าง: เมธอด Format () ของคลาส String วิธี WriteLine () ของคลาส Console เมธอด Cosh () ของคลาส Math

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


3
  1. ฉันเชื่อว่าส่วนหนึ่งเป็นเพราะวิธีการคงที่ "เร็วขึ้น" ในการโทรกว่าวิธีการแบบอินสแตนซ์ (ในเครื่องหมายคำพูดเนื่องจากกลิ่นของการเพิ่มประสิทธิภาพขนาดเล็ก) ดูที่http://dotnetperls.com/static-method
  2. กำลังบอกคุณว่าไม่จำเป็นต้องมีรัฐดังนั้นจึงสามารถโทรจากที่ใดก็ได้ลบค่าใช้จ่ายในการติดตั้งถ้านั่นเป็นสิ่งเดียวที่ใครบางคนต้องการ
  3. หากฉันต้องการเยาะเย้ยฉันก็คิดว่าโดยทั่วไปแล้วมันเป็นแนวปฏิบัติที่ประกาศไว้บนอินเทอร์เฟซ
  4. ถ้ามันถูกประกาศในอินเทอร์เฟซแล้ว R # จะไม่แนะนำให้คุณทำให้มันคงที่
  5. ถ้ามันถูกประกาศว่าเป็นเสมือนดังนั้น R # จะไม่แนะนำให้คุณทำให้มันคงที่เช่นกัน
  6. โฮลดิ้งของรัฐ (เขต) คงเป็นสิ่งที่ควรได้รับการพิจารณาอย่างรอบคอบ สถานะคงที่และหัวข้อผสมเช่นลิเธียมและน้ำ

R # ไม่ใช่เครื่องมือเดียวที่จะทำให้ข้อเสนอแนะนี้ การวิเคราะห์รหัส FxCop / MS ก็จะทำเช่นเดียวกัน

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


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

1
ไม่คุณไม่สามารถประกาศสแตติกบนอินเทอร์เฟซ มันจะไม่มีความหมาย
MIA

3

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


2
ฉันไม่เห็นด้วย. เวลาส่วนใหญ่เมื่อ Resharper บอกว่าฉันสามารถทำบางสิ่งบางอย่างคงที่มันเป็นรหัสเล็กน้อยที่ใช้ร่วมกันกับวิธีการอย่างน้อยสองวิธีในชั้นเรียนและทำให้ฉันแยกมันออกเป็นกระบวนการของตัวเอง การย้ายไปยังผู้ช่วยเหลือจะมีความซับซ้อนไร้ความหมาย
Loren Pechtel

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

1
ไม่เกี่ยวข้องกับคำถาม
Igby Largeman

2

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

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


0

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

ตอนนี้สำหรับเรื่องความเป็นไปได้ของสถานการณ์นี้ไม่ควรเป็นปัญหาเพราะคุณไม่ควรทดสอบวิธีการส่วนตัว

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


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

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