เหตุใดคลาสข้อมูลจึงถูกพิจารณาว่าเป็นกลิ่นรหัส


18

นี้บทความอ้างว่าชั้นข้อมูลเป็น "กลิ่นรหัส" เหตุผล:

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

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


1
สิ่งนี้จะขึ้นอยู่กับคุณสมบัติของภาษาเป็นอย่างมาก ในหลามตัวอย่างเช่นมีความแตกต่างระหว่าง "ข้อมูล" และ accessors ของมันไม่เว้นแต่คุณจะออกไปจากทางของคุณที่จะเขียน Java ในหลาม
jscs

1
ฉันคิดว่าการมีข้อมูลบางคลาสเท่านั้นไม่ใช่กลิ่นรหัส แต่ถ้าคลาสส่วนใหญ่เป็นแบบนั้นเรากำลังพูดถึง antipattern "anemic domain" en.wikipedia.org/wiki/Anemic_domain_model
Tulains Córdova

1
ฉันไม่เห็นว่าคำถามนี้ซ้ำซ้อนอย่างไร คำถามอื่น ๆ เกี่ยวกับการใช้คลาสข้อมูลใน OO ในขณะที่คำถามนี้เกี่ยวกับการลดลงของคลาสข้อมูล - วิชาที่แตกต่างกันโดยสิ้นเชิง
Milos Mrdovic

คุณอาจต้องการอ่านคำตอบนี้ใน stackoverflow ซึ่งแตกต่างจากคำตอบที่ได้รับการโหวตมากที่สุดที่นี่ซึ่งเป็นการอนุมานถึงความด้อยกว่าของโมเดลโดเมนที่หลากหลายและนำเสนอเหมือนข้อเท็จจริงที่พิสูจน์แล้ว stackoverflow.com/questions/23314330/...
McLovin

คำตอบ:


31

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

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

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


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

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

7
หากฟังก์ชันรับอาร์กิวเมนต์ของชนิดข้อมูลนั้นจะมีการเชื่อมโยงกับข้อมูลแล้ว
RemcoGerlich

4
Downvoting เพราะสิ่งนี้ไม่ถูกต้องหรือเป็นเรื่องที่ดีที่สุด ในภาษา OO มันมักจะทำให้รู้สึกว่ามีวัตถุที่มีทั้งข้อมูล (ซึ่งยังคงไม่เปลี่ยนรูป!) และวิธีการที่กระทำกับมัน ฟังก์ชั่นที่บริสุทธิ์และข้อมูลแยกต่างหากนั้นยอดเยี่ยมในกระบวนทัศน์ทางภาษาอื่น ๆ แต่ถ้าคุณทำ OO ให้ทำ OO อย่างเต็มที่
Marnen Laibow-Koser

3
ความจริงได้แสดงให้เราเห็นหลายสิ่งหลายอย่าง -1 สำหรับความรู้ที่ไม่เป็นทางการทั้งหมด "ความคิดเห็นอื่น ๆ ล้มเหลว" นอกจากนี้ผู้เขียนไม่ได้บอกว่าวัตถุข้อมูลบริสุทธิ์เป็น "ผิด" เพียงว่าพวกเขาเป็น "กลิ่นรหัส" และสมควรที่จะถาม ฉันเสียใจที่ฉันมีหนึ่ง downvote เพื่อมอบให้กับประเทศของฉัน :-)
user949300

7

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

โดยเฉพาะอย่างยิ่งสำหรับการแมปฐานข้อมูลคุณโดยทั่วไปมีคลาสเอนทิตีซึ่งประกอบด้วยฟิลด์ที่เก็บไว้ในฐานข้อมูลและ getters และ setters เท่านั้น Wikipedia Hibernate (เฟรมเวิร์ก)

แนวคิดรูของ Java beans ที่ใช้โดยเครื่องมือ / กรอบจำนวนมากขึ้นอยู่กับคลาสของข้อมูลที่เรียกว่า beans ที่มีเฉพาะฟิลด์และ getters และ setters ที่เกี่ยวข้องเท่านั้น Wikipdia JavaBeans

Fazit:
ถ้ามีคนอ้างว่ามีบางอย่าง 'ไม่ดี' หรือ 'กลิ่นรหัส' คุณควรมองหาเหตุผลที่ได้รับ หากเหตุผลไม่โน้มน้าวให้คุณถามคนอื่นด้วยเหตุผลที่ดีกว่าหรือแสดงความเห็นที่แตกต่าง (เหมือนที่คุณทำในฟอรัมนี้)


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

1
@ user949300 คุณดูสับสน หากผู้เขียนอ้างถึงพวกเขาเป็นกลิ่นรหัสแล้วเขาก็แสดงว่าอาจมีบางอย่างผิดปกติกับพวกเขา เนื่องจากพวกเขาได้รับการยอมรับอย่างกว้างขวางในทุกวันนี้ว่าเป็นวิธีปฏิบัติที่ดีมากพวกเขาจึงไม่ได้กลิ่นรหัสอย่างชัดเจน ดังนั้น MrSmith42 จึงถูกต้อง: ไม่มีอะไรผิดปกติกับพวกเขา
David Arno

4

เหตุผลที่ดีโดย Martin Fowler:

"Tell-Don't-Ask เป็นหลักการที่ช่วยให้ผู้คนจำได้ว่าการวางวัตถุเป็นเรื่องเกี่ยวกับการรวมข้อมูลกับฟังก์ชั่นที่ทำงานกับข้อมูลนั้นมันเตือนเราว่าแทนที่จะถามวัตถุสำหรับข้อมูลและดำเนินการกับข้อมูลนั้นเรา ควรบอกวัตถุว่าจะทำอย่างไรแทนที่จะส่งเสริมสิ่งนี้ให้ย้ายพฤติกรรมไปยังวัตถุเพื่อไปกับข้อมูล "

https://martinfowler.com/bliki/TellDontAsk.html


1
ปัญหาที่นี่คือฟาวเลอร์ จำกัด การปลอม "บอกอย่าถาม" โดยการเปลี่ยนฟังก์ชั่นจากการถามขอบเขตที่กว้างขึ้นเป็นเพียงแค่ถามขอบเขตของวัตถุ พวกเขายังคงถาม ในความเป็นจริง "บอกไม่ต้องถาม" สามารถก้าวไปอีกขั้นด้วยการบอกฟังก์ชั่นเหล่านั้นผ่านรายการอาร์กิวเมนต์ของพวกเขา ดังนั้นเราจึงมาถึงวัตถุข้อมูลและฟังก์ชั่น (data wise) ที่แยกต่างหากซึ่งเป็นการใช้งานจริงของ "tell Don't ask" ดังนั้นแทนที่จะเป็นอาร์กิวเมนต์ที่ดีสำหรับการอ้างว่าคลาสของข้อมูลมีกลิ่นของรหัสจริง ๆ แล้วมันพิสูจน์ได้ตรงกันข้าม
David Arno

2
@DavidArno คุณลืมเกี่ยวกับการห่อหุ้มและซ่อน คุณบอกให้อ็อบเจกต์เรียกใช้เมธอดสมาชิกและเมธอดสมาชิกไปที่กล่องดำของวัตถุและทำทุกอย่างที่จำเป็นเพื่อให้ได้คำตอบ ถ้าคุณถามวัตถุจากภายนอกคุณไม่สามารถเข้าถึงสถานะส่วนตัวของมันและดังนั้นวัตถุนั้นจะเปิดเผยสถานะมากกว่าฉลาดหรือผู้ถามต้องกระโดดผ่านห่วงมากกว่าที่จำเป็น ฉันไม่เห็นว่าทำไมคุณ "ถาม" วัตถุในสภาพแวดล้อม OO (กระบวนทัศน์การเขียนโปรแกรมอื่น ๆ อาจต้องใช้แนวทางที่แตกต่างกันแน่นอน)
Marnen Laibow-Koser

2
@DavidArno แน่นอนคุณสามารถส่งผ่านbazเป็นพารามิเตอร์ไปยังวิธีการคงที่ แต่ต้องทำอย่างนั้นก่อนอื่นคุณต้องถามวัตถุสำหรับมัน บางทีในกระบวนทัศน์การเขียนโปรแกรมที่วิธีการเป็นหลัก (เช่นการพูดการเขียนโปรแกรมการทำงาน) สิ่งนี้ทำให้รู้สึก แต่ในสภาพแวดล้อม OO มันไม่ได้อย่างแน่นอนเพราะวัตถุเป็นหลักและควรมีทั้งข้อมูลและฟังก์ชั่นที่จะดำเนินการกับมัน การอ้างสิทธิ์ของคุณว่าการเอาวิธีการออกจากวัตถุนั้นมีการห่อหุ้มที่เพิ่มขึ้นนั้นก็ย้อนกลับไปตามที่ฉันบอกได้เพราะมันหมายความว่าตอนนี้คุณbazปรากฏตัวนอกวัตถุแล้ว
Marnen Laibow-Koser

1
@ MarnenLaibow-Koser ฉันไม่เรียกร้อง "ทำ OO" ฉันเขียนโค้ดและใช้เทคนิคที่ดีในการทำเช่นนั้น ไม่ว่าเทคนิคเหล่านั้นจะมาจากกระบวนทัศน์การทำงานหรือกระบวนทัศน์ของ OO หรือกระบวนทัศน์แบบใครก็ตามที่ให้กับเจ้ากรรมไม่น่าสนใจสำหรับฉัน การเลือกกระบวนทัศน์และยึดติดกับมันอย่างเต็มที่ที่สุดคือความเชื่อที่บริสุทธิ์ มันไม่ดี. มันไร้สาระ มันขัดขวางคุณและส่งผลให้โค้ดด้อยคุณภาพ อย่าทำมัน
David Arno

1
@DavidArno ในทางกลับกันถ้าคุณยอมรับอย่างเต็มที่ในกระบวนทัศน์ (กระบวนทัศน์ที่เหมาะสมไม่เพียงแค่ OO) คุณจะได้รับ abstractions ระดับสูงที่มีประสิทธิภาพและรหัสที่มีเหตุผลที่รักษาได้ ฉันไม่ได้พูดแบบนี้ว่าเป็นคนดื้อรั้น แต่ค่อนข้างจะเป็นประโยชน์ ฉันได้เห็นและดูแลรักษาโค้ดที่มากเกินไปซึ่งสร้างขึ้นโดยมีทัศนคติเช่นคุณซึ่งผู้เขียนไม่ได้ผูกพันกับความสอดคล้องเชิงตรรกะของระบบที่ใช้ มันยากที่จะเข้าใจยากที่จะรักษาและยากที่จะแก้ไข กระบวนทัศน์ไม่สมบูรณ์แบบ แต่โดยทั่วไปส่วนผสม (ยกเว้นว่ามีการพิจารณาอย่างรอบคอบ) นั้นยากที่จะเข้าใจ
Marnen Laibow-Koser

2

สิ่งที่คุณต้องเข้าใจคือมีวัตถุสองชนิด:

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

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

    คลาสส่วนใหญ่ที่ฉันเขียนอยู่ในประเภทนี้

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

    Point2Dตัวอย่างจะเป็นชั้นเรียน อย่างมีค่าคงที่ความต้องการที่จะมั่นใจสำหรับสมาชิกของชั้นนี้ไม่มีและผู้ใช้ควรจะสามารถเข้าถึงข้อมูลเพียงผ่านและmyPoint.xmyPoint.y

    โดยส่วนตัวแล้วฉันไม่ได้ใช้คลาสดังกล่าวมากนัก แต่ฉันคิดว่าไม่มีโค้ดขนาดใหญ่กว่าที่ฉันเขียนซึ่งไม่ได้ใช้คลาสดังกล่าวที่ไหนสักแห่ง

มีความเชี่ยวชาญในการวางแนวของวัตถุรวมถึงการตระหนักว่าความแตกต่างนี้มีอยู่และการเรียนรู้ที่จะจำแนกฟังก์ชั่นของชั้นเรียนเป็นหนึ่งในสองประเภทนี้


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


1
คำอธิบายสำหรับ downvote นั้นยอดเยี่ยม ...
cmaster - คืนสถานะโมนิ

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