มันเป็นรูปแบบการต่อต้านถ้าทรัพย์สินชั้นสร้างและส่งกลับตัวอย่างใหม่ของชั้นเรียนหรือไม่?


24

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

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

อย่างไรก็ตามหนึ่งในเพื่อนร่วมงานของฉันแนะนำให้ฉันเพียงแค่สร้างคุณสมบัติคลาสที่เรียกreciprocalว่าคืนค่าอินสแตนซ์ใหม่ของคลาสเองผ่านเมธอด getter

คำถามของฉันคือ: มันเป็นรูปแบบต่อต้านหรือไม่สำหรับคุณสมบัติของคลาสที่จะทำเช่นนั้น?

ฉันพบว่ามันใช้งานง่ายน้อยลงเพราะ:

  1. ในใจของฉันคุณสมบัติของคลาสไม่ควรส่งคืนอินสแตนซ์ใหม่ของคลาสและ
  2. ชื่อของคุณสมบัติซึ่งreciprocalไม่ได้ช่วยให้นักพัฒนาสามารถเข้าใจพฤติกรรมของมันได้อย่างสมบูรณ์โดยไม่ได้รับความช่วยเหลือจาก IDE หรือตรวจสอบลายเซ็นของ getter

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


6
ในฐานะที่เป็น @Ewan กล่าวในวรรคสุดท้ายของคำตอบของเขาห่างไกลจากการต่อต้านแบบมีHeadingชนิดที่ไม่เปลี่ยนรูปแบบและการreciprocalกลับมาใหม่Headingคือการปฏิบัติที่ดี "Pit of Success" (ด้วยข้อแม้ที่ทั้งสองสายreciprocalควรกลับ "สิ่งเดียวกัน" คือพวกเขาควรจะผ่านการทดสอบความเท่าเทียมกัน)
David Arno

20
"ชั้นเรียนของฉันไม่เปลี่ยนรูป" มีรูปแบบการต่อต้านที่แท้จริงของคุณอยู่ตรงนั้น ;)
David Arno

3
@DavidArno เอาละบางครั้งก็มีการลงโทษอย่างมากสำหรับการทำสิ่งที่ไม่เปลี่ยนรูปแบบโดยเฉพาะอย่างยิ่งหากภาษาไม่รองรับภาษานั้น ๆ แต่ฉันก็เห็นด้วยว่าการไม่เปลี่ยนรูปนั้นเป็นวิธีปฏิบัติที่ดีในหลายกรณี
53777A

2
@dcorking ชั้นเรียนมีการใช้งานทั้งใน C # และ TypeScript แต่ฉันค่อนข้างจะรักษาผู้ไม่เชื่อเรื่องภาษานี้
53777A

2
@Kaiserludi ฟังดูเหมือนคำตอบ (คำตอบที่ดี) - ความคิดเห็นสำหรับการขอความชัดเจน
dcorking

คำตอบ:


22

ไม่ทราบว่าจะมีสิ่งต่าง ๆ เช่น Copy () หรือ Clone () แต่ใช่ฉันคิดว่าคุณมีสิทธิ์ที่จะกังวลเกี่ยวกับสิ่งนี้

ยกตัวอย่าง:

h2 = h1.reciprocal
h2.Name = "hello world"
h1.reciprocal.Name = ?

มันจะดีถ้ามีคำเตือนว่าคุณสมบัตินั้นเป็นวัตถุใหม่ทุกครั้ง

คุณอาจคิดว่า:

h2.reciprocal == h1

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


1
เพิ่งทราบว่าCopy()และClone()เป็นวิธีการไม่ใช่คุณสมบัติ ฉันเชื่อว่า OP หมายถึงผู้ให้บริการทรัพย์สินที่ส่งคืนอินสแตนซ์ใหม่
ลินน์

6
ฉันรู้ว่า. แต่คุณสมบัติคือ (sort) วิธีการใน c #
Ewan

4
ในกรณีที่ C # มีมากขึ้นเพื่อเสนอ: String.Substring(), Array.Reverse(), Int32.GetHashCode()ฯลฯ
ลินน์

If your heading class was an immutable value type- ฉันคิดว่าคุณควรเพิ่ม setters คุณสมบัติบนอ็อบเจกต์ที่ไม่เปลี่ยนรูปควรส่งคืนอินสแตนซ์ใหม่เสมอ (หรืออย่างน้อยถ้าค่าใหม่ไม่เหมือนกับค่าเก่า) เพราะนั่นคือคำจำกัดความของออบเจกต์ที่ไม่เปลี่ยนรูป :)
Ivan Kolmychek

17

อินเทอร์เฟซของคลาสนำผู้ใช้ของคลาสเพื่อตั้งสมมติฐานเกี่ยวกับวิธีการทำงาน

หากข้อสันนิษฐานเหล่านี้หลายข้อถูกต้องและมีไม่กี่คนที่ผิดอินเตอร์เฟซก็ดี

หากข้อสันนิษฐานเหล่านี้หลายอย่างไม่ถูกต้องและมีน้อย

ข้อสันนิษฐานทั่วไปเกี่ยวกับคุณสมบัติคือการเรียกใช้ฟังก์ชัน get นั้นราคาถูก ข้อสันนิษฐานทั่วไปอีกประการเกี่ยวกับคุณสมบัติคือการเรียกใช้ฟังก์ชัน get สองครั้งในแถวจะส่งคืนสิ่งเดียวกัน


คุณสามารถหลีกเลี่ยงปัญหานี้ได้โดยใช้ความสอดคล้องเพื่อเปลี่ยนความคาดหวัง ตัวอย่างเช่นสำหรับห้องสมุด 3D ขนาดเล็กที่คุณต้องการVector, Ray Matrixฯลฯ คุณสามารถทำให้มันดังกล่าวว่า getters เช่นVector.normalและMatrix.inverseจะสวยมากมักจะมีราคาแพง น่าเสียดายที่แม้ว่าอินเทอร์เฟซของคุณจะใช้คุณสมบัติที่มีราคาแพงอย่างต่อเนื่อง แต่อินเทอร์เฟซจะใช้งานได้ง่ายเหมือนกับที่ใช้Vector.create_normal()และ Matrix.create_inverse()- แต่ฉันรู้ว่าไม่มีข้อโต้แย้งที่แข็งแกร่งที่สามารถทำให้การใช้คุณสมบัติสร้างอินเตอร์เฟสที่ใช้งานง่ายขึ้น


10

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

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

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


1
DateTime.Nowคุณสมบัติเป็นที่นิยมใช้และหมายถึงวัตถุใหม่ ฉันคิดว่าชื่อของสถานที่ให้บริการสามารถช่วยลบความกำกวมเกี่ยวกับว่าวัตถุเดียวกันจะถูกส่งกลับในแต่ละครั้ง ทุกอย่างอยู่ในชื่อและวิธีการใช้งาน
เกร็ก Burghardt

3
DateTime ขณะนี้ถือเป็นความผิดพลาด ดูstackoverflow.com/questions/5437972/…
Brad Thomas

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

1
@GregBurghardt DateTime.Newเป็นแบบคงที่และดังนั้นคุณไม่สามารถคาดหวังให้มันเป็นตัวแทนของสถานะของวัตถุ
Tsahi Asher

5

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

ใน C # คุณสมบัติมีความโดดเด่นในสิ่งที่พวกเขาเป็น (ตามอัตภาพ) ตัวพิมพ์ใหญ่ (เช่นวิธีการ) แต่ขาดวงเล็บ (เช่นตัวแปรอินสแตนซ์สาธารณะ) หากคุณเห็นรหัสต่อไปนี้เอกสารที่หายไปคุณคาดหวังอะไร

var reciprocalHeading = myHeading.Reciprocal;

ในฐานะที่เป็น C # สามเณร แต่ผู้ที่อ่านแนวทางการใช้งานคุณสมบัติของ Microsoft ฉันคาดว่าReciprocalจะมีสิ่งอื่น ๆ :

  1. เป็นสมาชิกข้อมูลเชิงตรรกะของHeadingชั้นเรียน
  2. มีราคาถูกที่จะโทรหาไม่จำเป็นต้องให้ฉันแคชค่า
  3. ขาดผลข้างเคียงที่สังเกตได้
  4. สร้างผลลัพธ์เดียวกันหากเรียกสองครั้งติดต่อกัน
  5. (อาจ) เสนอReciprocalChangedกิจกรรม

จากสมมติฐานเหล่านี้ (3) และ (4) อาจถูกต้อง (สมมติว่าHeadingเป็นประเภทค่าที่ไม่เปลี่ยนรูปเช่นเดียวกับคำตอบของ Ewan ), (1) เป็นที่ถกเถียงกัน (2) ไม่เป็นที่รู้จัก แต่ยังถกเถียงกันและ (5) ใช้ความหมาย (แม้ว่าสิ่งใดก็ตามที่มีหัวเรื่องควรจะมีHeadingChangedเหตุการณ์) สิ่งนี้ชี้ให้เห็นว่าใน C # API“ ไม่ได้รับหรือคำนวณส่วนกลับ” ไม่ควรนำมาใช้เป็นคุณสมบัติ แต่โดยเฉพาะอย่างยิ่งหากการคำนวณของราคาถูกและHeadingไม่เปลี่ยนรูปมันเป็นกรณีของเขตแดน

(โปรดทราบว่าไม่มีข้อกังวลใด ๆ ที่เกี่ยวข้องกับว่าการเรียกคุณสมบัติสร้างอินสแตนซ์ใหม่ไม่ใช่แม้แต่ (2) การสร้างวัตถุใน CLR ทั้งในตัวของมันเองนั้นค่อนข้างถูก)

ใน Java คุณสมบัติเป็นระเบียบวิธีการตั้งชื่อ ถ้าฉันเห็น

Heading reciprocalHeading = myHeading.getReciprocal();

ความคาดหวังของฉันคล้ายกับที่กล่าวมาข้างต้น (หากกำหนดไว้ชัดเจนน้อยกว่า): ฉันคาดว่าการโทรนั้นจะถูก idempotent และไม่มีผลข้างเคียง อย่างไรก็ตามนอกกรอบ JavaBeans แนวคิดของ“ คุณสมบัติ” นั้นไม่ใช่สิ่งที่มีความหมายใน Java และโดยเฉพาะอย่างยิ่งเมื่อพิจารณาคุณสมบัติที่ไม่เปลี่ยนรูปแบบซึ่งไม่สอดคล้องกันตอนนี้setReciprocal()การgetXXX()ประชุมค่อนข้างล้าสมัย จากจาวาที่มีประสิทธิภาพรุ่นที่สอง (อายุมากกว่าแปดปีแล้ว):

เมธอดที่ส่งคืนbooleanฟังก์ชันที่ไม่ใช่ฟังก์ชันหรือคุณลักษณะของวัตถุที่พวกมันถูกเรียกมักจะถูกตั้งชื่อด้วยวลีนามคำนามหรือวลีกริยาที่ขึ้นต้นด้วยกริยาget… มีแกนนำเสียงร้องที่อ้างว่ามีเพียงรูปแบบที่สาม (เริ่มต้นด้วยget) เป็นที่ยอมรับ แต่มีพื้นฐานเล็กน้อยสำหรับการเรียกร้องนี้ โดยทั่วไปสองรูปแบบแรกจะนำไปสู่รหัสที่อ่านง่ายขึ้น (หน้า 239)

ใน API ร่วมสมัยที่คล่องแคล่วมากขึ้นฉันคาดว่าจะเห็น

Heading reciprocalHeading = myHeading.reciprocal();

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

ใน Ruby ไม่มีสิ่งใดเป็นสมบัติ มี "คุณสมบัติ" แต่ถ้าฉันเห็น

reciprocalHeading = my_heading.reciprocal

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

ในสกาล่าการตั้งชื่อแบบแผนก็คือวิธีการที่มีผลข้างเคียงต้องใช้วงเล็บและวิธีการที่พวกมันทำไม่ได้ แต่

val reciprocal = heading.reciprocal

อาจเป็นใด ๆ ของ:

// immutable public value initialized at creation time
val reciprocal: Heading = … 

// immutable public value initialized on first use
lazy val reciprocal: Heading = … 

// public method, probably recalculating on each invocation
def reciprocal: Heading = …

// as above, with parentheses that, by convention, the caller
// should only omit if they know the method has no side effects
def reciprocal(): Heading = …

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

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

กล่าวโดยย่อ:รู้จักภาษาที่คุณใช้และรู้ว่าผู้เขียนคนอื่นจะคาดหวังอะไรจาก API ของคุณ ทุกอย่างอื่นคือรายละเอียดการใช้งาน


1
+1 หนึ่งในคำตอบที่ฉันชอบขอบคุณที่สละเวลาเขียนสิ่งนี้
53777A

2

อย่างที่คนอื่น ๆ พูดกันมันเป็นรูปแบบที่ใช้กันทั่วไปในการคืนอินสแตนซ์ของคลาสเดียวกัน

การตั้งชื่อควรดำเนินควบคู่ไปกับอนุสัญญาการตั้งชื่อภาษา

ตัวอย่างเช่นใน Java ฉันอาจคาดหวังให้เรียก getReciprocal();

ที่ถูกกล่าวว่าฉันจะพิจารณาไม่แน่นอนกับไม่เปลี่ยนรูปวัตถุที่

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

ด้วยสิ่งที่ไม่แน่นอนนี้จะได้รับที่น่ากลัวมาก

b = a.reciprocal
a += 1
b = what?

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

ในกรณีเหล่านั้นมองหาการตั้งชื่อที่ดีกว่าซึ่งสื่อสารสิ่งที่เกิดขึ้นตัวอย่างเช่นcreateReciprocal()อาจเป็นทางเลือกที่ดีกว่า

แต่มันก็ขึ้นอยู่กับบริบทด้วย


คุณหมายถึงไม่แน่นอนหรือไม่
Carsten S

@ CarstenS ใช่แน่นอนขอบคุณ ไม่รู้ว่าหัวฉันอยู่ที่ไหน :)
Eiko

ไม่เห็นด้วยบ้างgetReciprocal()เนื่องจากว่า "ฟังดู" เหมือนกับ JavaBeans สไตล์ "ปกติ" ชอบ "createXXX ()" หรืออาจจะเป็น "calculXXX ()" ซึ่งระบุหรือบอกใบ้ถึงโปรแกรมเมอร์อื่น ๆ ว่ามีบางสิ่งที่แตกต่างเกิดขึ้น
949300

@ user949300 ฉันเห็นด้วยค่อนข้างกังวลกับคุณ - และกล่าวถึงชื่อสร้าง ... เพิ่มเติม มีข้อเสียเช่นกัน สร้าง ... หมายถึงอินสแตนซ์ใหม่ซึ่งอาจไม่ใช่กรณี (คิดว่าเป็นวัตถุเฉพาะสำหรับกรณีพิเศษบางอย่าง) คำนวณ ... รายละเอียดการดำเนินการรั่วไหล - ซึ่งอาจกระตุ้นสมมติฐานที่ผิดในแท็กราคา
Eiko

1

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


1
+1 สำหรับชื่อที่ชัดเจน แต่เกิดอะไรขึ้นกับ SRP ในโซลูชันอื่น ๆ
53777A

3
ทำไมคุณถึงแนะนำคลาสโรงงานให้ใช้วิธีการแบบโรงงาน? (ในความคิดของความรับผิดชอบที่มีประโยชน์ของวัตถุที่มักจะให้วัตถุปล่อยที่เป็นเหมือนตัวเองเช่น iterator.next นี้ไม่ละเมิดรุนแรงของ SRP สาเหตุปัญหาทางวิศวกรรมซอฟแวร์อื่น ๆ .?)
dcorking

2
@dcorking คลาสโรงงานเมื่อเทียบกับวิธีการ (ในความคิดของฉัน) มักจะเป็นคำถามประเภทเดียวกันกับ "วัตถุนั้นเปรียบได้หรือฉันควรทำการเปรียบเทียบหรือไม่?" มันก็โอเคเสมอที่จะทำการเปรียบเทียบ แต่ก็โอเคที่จะทำให้พวกมันเปรียบได้ถ้ามันเป็นวิธีการเปรียบเทียบที่เป็นสากล (เช่นตัวเลขที่ใหญ่กว่าขนาดเล็กกว่านี่เป็นสิ่งที่ดีสำหรับการเปรียบเทียบ แต่คุณสามารถพูดได้ว่าสิ่งต่าง ๆ ยิ่งใหญ่กว่าอัตราต่อรองฉันจะทำให้มันกลายเป็นตัวเปรียบเทียบ) - สำหรับสิ่งนี้ฉันคิดว่ามีเพียงอันเดียว วิธีที่จะย้อนกลับส่วนหัวดังนั้นฉันจะเอนตัวไปทำวิธีการหลีกเลี่ยงชั้นพิเศษ
Captain Man

0

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

แต่ตัวอย่างเช่นคลาสสตริงสามารถมีคุณสมบัติ "firstWord", "lastWord" หรือถ้ามันจัดการ Unicode "firstLetter", "lastLetter" ซึ่งจะเป็นวัตถุสตริงเต็ม - มักจะเล็กกว่าวัตถุ


0

เนื่องจากคำตอบอื่น ๆ ครอบคลุมถึงส่วนของอสังหาริมทรัพย์ฉันจะพูดถึงข้อที่ 2 ของคุณ reciprocal :

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


0

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

ซึ่งกันและกันคือฟังก์ชั่นที่บริสุทธิ์ของส่วนหัวเช่นเดียวกับการลบของจำนวนเป็นฟังก์ชั่นที่บริสุทธิ์ของจำนวนที่

ตามกฎของหัวแม่มือหากการตั้งค่าไม่สมเหตุสมผลอาจเป็นทรัพย์สิน การตั้งค่ามันยังคงไม่ได้รับอนุญาต แต่การเพิ่มเซทเทอร์ควรเป็นไปได้ในทางทฤษฎีและมีความหมาย

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


แก้ไข: สำหรับ C # โดยเฉพาะฉันจะดูคลาสที่มีอยู่โดยเฉพาะคลาส Library

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

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


-1

คำถามที่น่าสนใจมากแน่นอน ฉันไม่เห็นการละเมิด SOLID + DRY + KISS ในสิ่งที่คุณเสนอ แต่ถึงกระนั้นก็มีกลิ่นไม่ดี

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

บวก: จะเกิดอะไรขึ้นถ้าคุณเรียกใช้getReciprocal()บนวัตถุที่ส่งคืน คุณได้รับอีกตัวอย่างหนึ่งของชั้นเรียนซึ่งอาจเป็นสำเนาที่แน่นอนของคนแรก! และถ้าคุณวิงวอนgetReciprocal()อันนั้น? วัตถุแผ่กิ่งก้านสาขาใคร?

อีกครั้ง: ถ้าผู้เรียกร้องต้องการค่าตอบแทนซึ่งกันและกัน(ในฐานะสเกลาร์ฉันหมายถึง)? getReciprocal()->getValue()? เรากำลังละเมิดกฎของ Demeterเพื่อผลประโยชน์เพียงเล็กน้อย


ฉันยินดีที่จะยอมรับข้อโต้แย้งในรูปแบบ downvoter ขอบคุณ!
ดร. Gianluigi Zane Zanettini

1
ฉันไม่ได้ลงคะแนน แต่ฉันสงสัยว่าอาจเป็นเพราะความจริงที่ว่ามันไม่ได้เพิ่มคำตอบที่เหลือลงไป แต่ฉันอาจผิด
53777A

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