ไม่เคยใช้ Strings ใน Java ใช่ไหม [ปิด]


73

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

public void bookTicket(
  String name,
  String firstName,
  String film,
  int count,
  String cinema);

public void bookTicket(
  Name name,
  FirstName firstName,
  Film film,
  Count count,
  Cinema cinema);

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


การอภิปรายที่เกี่ยวข้องกับ Wiki ดั้งเดิม: "toString () ของอะไรคือ?"
Christoffer Hammarström

5
โอ้ว้าวการโพสต์บล็อกนั้นทำให้ฉันรู้สึกไม่สบายทางกายภาพ
Rob

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

9
คำสั่งที่ขึ้นต้นด้วย "ไม่เคย" คือ "เสมอ" เท็จ!
Florents Tselai

1
ผู้ชายคนนั้นเป็น CTO!
Hyangelo

คำตอบ:


88

Encapsulation จะมีการปกป้องโปรแกรมของคุณกับการเปลี่ยนแปลง การเป็นตัวแทนของชื่อจะมีการเปลี่ยนแปลงหรือไม่? ถ้าไม่เช่นนั้นคุณจะเสียเวลาและมีการใช้งาน YAGNI

แก้ไข: ฉันได้อ่านบทความในบล็อกและเขามีความคิดที่ดี ปัญหาคือเขาปรับขนาดมันไกลเกินไป สิ่งที่ต้องการString orderId คือไม่ดีจริงๆเพราะคงจะไม่ได้เป็นที่ถูกต้อง"!"£$%^&*())ADAFVF orderIdซึ่งหมายความว่าStringแทนค่าจำนวนมากที่เป็นไปได้มากขึ้นกว่าที่มีถูกต้องorderIds แต่สำหรับสิ่งที่ต้องการnameแล้วคุณไม่อาจคาดการณ์สิ่งที่อาจจะหรืออาจจะไม่ได้ชื่อที่ถูกต้องและใด ๆ ที่เป็นที่ถูกต้องStringname

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

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


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

13
@ Malcolm: แต่คุณไม่มีทางรู้ว่า Strings ใดที่ได้รับการตรวจสอบแล้วยกเว้นการตรวจสอบความถูกต้องอีกครั้ง
DeadMG

7
"[... ] คุณไม่สามารถทำนายได้ว่าชื่ออาจจะเป็นหรือไม่ถูกต้องและสตริงใด ๆ เป็นชื่อที่ถูกต้อง" ฉันเดาว่าจุดแข็งหนึ่งของเทคนิคนี้คือถ้าพารามิเตอร์ของคุณเป็นประเภทNameคุณจะไม่สามารถส่งผ่านค่าสตริงที่ไม่เกี่ยวข้องได้โดยไม่ตั้งใจ ในกรณีที่คุณคาดว่าจะมีNameเพียง a Nameจะรวบรวมและสตริง "ฉันเป็นหนี้คุณ $ 5" ไม่สามารถยอมรับได้โดยไม่ตั้งใจ (โปรดทราบว่าสิ่งนี้ไม่เกี่ยวข้องกับการตรวจสอบชื่อทุกประเภท!)
Andres F.

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

3
@DeadMG นั่นเป็นเหตุผลและไม่ใช่สิ่งที่เราสามารถแก้ไขได้ในความคิดเห็น ฉันจะบอกว่าการใส่ผิดประเภทของดึกดำบรรพ์เกิดขึ้นและการทำให้อินเทอร์เฟซของคุณแข็งขึ้นเป็นวิธีหนึ่งในการปรับปรุงสถานการณ์
Andres F.

46

มันบ้ามาก :)


2
นั่นเป็นความคิดเห็นของฉันเช่นกัน แต่สิ่งหนึ่งคือฉันจำข้อเสนอแนะนี้ได้ใน "Code Complete" แน่นอนว่าไม่ใช่ทุกอย่างในหนังสือเล่มนี้ที่เถียงไม่ได้ แต่อย่างน้อยก็ทำให้ฉันคิดว่าสองครั้งก่อนที่จะปฏิเสธความคิด
DPM

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

12
สามัญสำนึกคือทุกสิ่ง แต่เป็นเรื่องธรรมดา
Kaz Dragon

1
+1, สำหรับสิ่งนี้ฉันจะเพิ่มว่าเมื่อภาษารองรับพารามิเตอร์ที่มีชื่อและ IDE นั้นดีเช่นในกรณีที่มี C # และ VS2010 ดังนั้นจึงไม่ต้องชดเชยการขาดคุณสมบัติในภาษาที่มีรูปแบบบ้า . ไม่จำเป็นต้องมีคลาสที่ชื่อ X และคลาสที่ชื่อว่า Y ถ้าใครสามารถเขียนได้var p = new Point(x: 10, y:20);นอกจากนี้มันไม่เหมือน Cinema ที่แตกต่างจากสตริง ฉันจะเข้าใจว่าหากต้องจัดการกับปริมาณทางกายภาพเช่นความดันอุณหภูมิพลังงานที่หน่วยแตกต่างกันและบางส่วนไม่สามารถลบได้ ผู้เขียนบล็อกต้องลองใช้งานได้
งาน

1
+1 สำหรับ "อย่าทำมากเกินไป!"
Ivan

23

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


2
สามารถแสดงความคิดเห็น downvoter?
วินไคลน์

ราคาที่เราจ่ายสูงสำหรับการพิมพ์แบบคงที่คืออะไร
Richard Tingle

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

ฉันไม่เคยประสบปัญหากับแอปพลิเคชัน Java (สิ่งที่มีการรวบรวมอย่างต่อเนื่องโดยปกติแล้วจะรวบรวมในเวลาที่ฉันกดรัน) แต่มันเป็นจุดที่เหมาะสมกับ web WARs ซึ่งการปรับใช้ซ้ำดูเหมือนช้ากว่าเล็กน้อย
Richard Tingle

16

อย่าทำมัน มันจะมีเนื้อหาที่ซับซ้อนและคุณจะไม่ต้องการมัน

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


ประโยชน์ที่ได้รับ

ประโยชน์หลักคือความสามารถในการแก้ไขและขยายรหัส ถ้าคุณใช้

class Point {
    int x,y;
    // other point operations
}

แทนที่จะส่งผ่านจำนวนเต็มสองสามรอบ - ซึ่งเป็นสิ่งที่น่าเสียดายที่อินเทอร์เฟซจำนวนมากทำแล้วมันจะกลายเป็นเรื่องง่ายกว่าที่จะเพิ่มมิติอื่นในภายหลัง doubleหรือเปลี่ยนชนิดไป ถ้าคุณใช้List<Author> authorsหรือList<Person> authorsแทนList<String> authorsหลังจากนั้นมันก็กลายเป็นเรื่องง่ายที่จะเพิ่มข้อมูลเพิ่มเติมกับสิ่งที่ผู้เขียนหมายถึง การเขียนมันลงแบบนี้มันรู้สึกเหมือนฉันกำลังพูดให้ชัดเจน แต่ในทางปฏิบัติฉันมีความผิดในการใช้สตริงด้วยวิธีนี้หลาย ๆ ครั้งตัวฉันเองโดยเฉพาะอย่างยิ่งในกรณีที่ไม่ชัดเจนในตอนเริ่มต้นแล้วฉันต้องการมากกว่า สตริง.

ขณะนี้ฉันกำลังพยายาม refactor รายการสตริงบางรายการซึ่งพันกันตลอดรหัสของฉันเพราะฉันต้องการข้อมูลเพิ่มเติมที่นั่นและฉันรู้สึกเจ็บปวด: \

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

ประโยชน์สุดท้ายคือความปลอดภัยประเภทด้วยเหตุผลที่ชัดเจน แต่ในสายตาของฉันมันเป็นเรื่องเล็กน้อยที่นี่

ข้อเสีย

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

มันสามารถเกี่ยวข้องกับ setters ซ้ำซ้อน (หรือการก่อสร้าง) และ getters จำนวนมาก ผู้เขียนบล็อกให้เป็นตัวอย่างที่น่าเกลียดอย่างแท้จริงของnew Point(x(10), y(10))แทนnew Point(10, 10)และผมต้องการที่จะเพิ่มที่ใช้งานนอกจากนี้ยังอาจเกี่ยวข้องกับสิ่งที่ชอบแทนMath.max(p.x.get(), p.y.get()) Math.max(p.x, p.y)และโค้ดขนาดยาวมักจะอ่านยากกว่าและเหมาะสมกว่า แต่ในความซื่อสัตย์ทั้งหมดฉันมีความรู้สึกว่ามีโค้ดจำนวนมากเคลื่อนย้ายวัตถุไปรอบ ๆ และมีเพียงวิธีการสร้างเท่านั้น

เป็นที่ถกเถียงกัน

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


เช่นเดียวกับโรงเรียนสอนความคิดอื่น ๆ ส่วนใหญ่ฉันคิดว่ามันไม่ดีต่อสุขภาพที่จะนำสิ่งนี้ไปสู่จุดสูงสุด ฉันไม่เห็นว่าตัวเองเคยแยกพิกัด x และ y เป็นประเภทที่แตกต่างกัน ฉันไม่คิดว่าCountจำเป็นเมื่อintควรจะพอเพียง ฉันไม่ชอบการunsigned intใช้งานใน C - ในขณะที่ดีในทางทฤษฎีมันก็ไม่ได้ให้ข้อมูลที่เพียงพอและห้ามการขยายรหัสของคุณในภายหลังเพื่อสนับสนุนเวทมนตร์ -1 บางครั้งคุณต้องการความเรียบง่าย

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

ฉันมีความเกลียดชังอย่างลึกซึ้งต่อโค้ดที่มีการออกแบบมากเกินไป ฉันทำอย่างแท้จริง แต่ถูกต้องแล้วฉันไม่คิดว่ามันจะเป็นไปได้


5

แม้ว่ามันจะเกินความจริงฉันก็มักจะคิดว่าสิ่งที่ฉันเห็นส่วนใหญ่อยู่ภายใต้การออกแบบแทน

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

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

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

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

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

ฉันสนใจที่จะเห็นโปรเจ็กต์ Java ที่เขียนได้ดีซึ่งมีคลาสที่กำหนดไว้มากเกินไป (ซึ่งทำให้โปรแกรมยากขึ้น) ฉันเริ่มคิดว่ามันเป็นไปไม่ได้ที่จะมีคลาสมากเกินไป


3

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

public void bookTicket(
  String name,
  String firstName,
  String film,
  int count,
  String cinema);

จำเป็นต้องใช้พารามิเตอร์สองตัวเพื่อระบุผู้มีพระคุณที่แท้จริงที่จองตั๋วคุณอาจมีภาพยนตร์สองเรื่องที่มีชื่อเหมือนกัน (เช่น remakes) คุณอาจมีภาพยนตร์เรื่องเดียวกันที่มีชื่อต่างกัน (เช่นการแปล) โซ่โรงภาพยนตร์บางแห่งอาจมีสำนักงานสาขาที่แตกต่างกันดังนั้นคุณจะจัดการกับมันอย่างไรในสายและในวิธีที่สอดคล้องกัน (เช่นคุณกำลังใช้$chain ($city)หรือ$chain in $cityหรืออย่างอื่นและคุณจะแน่ใจได้อย่างไรว่านี่คือ ใช้อย่างสม่ำเสมอสิ่งที่แย่ที่สุดคือการระบุผู้มีพระคุณของคุณด้วยพารามิเตอร์สองตัวความจริงที่ว่าทั้งชื่อและนามสกุลนั้นไม่ได้รับประกันลูกค้าที่ถูกต้อง (และคุณไม่สามารถแยกแยะความแตกต่างได้สองประการJohn Doe)

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

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

ทางเลือกที่เสนอจะดีกว่า:

public void bookTicket(
  Name name,
  FirstName firstName,
  Film film,
  Count count,
  Cinema cinema);

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

สำหรับสิ่งที่คุ้มค่าฉันควรเขียนอะไรบางอย่างเช่น

public Ticket bookTicket(
  Person patron,
  Film film,
  int numberOfTickets,
  Cinema cinema);

เรื่องสั้นสั้น ๆ : คุณไม่ควรส่งตัวแปรไร้สาระ; ครั้งเดียวที่คุณจะระบุวัตถุด้วยค่าที่ไม่ได้ระบุวัตถุจริงคือเมื่อคุณเรียกใช้แบบสอบถาม (เช่นpublic Collection<Film> findFilmsWithTitle(String title)) หรือเมื่อคุณรวบรวมหลักฐานการพิสูจน์แนวคิด รักษาระบบการพิมพ์ของคุณให้สะอาดดังนั้นอย่าใช้ประเภทที่กว้างเกินไป (เช่นภาพยนตร์ที่แสดงโดย a String) หรือ จำกัด / เจาะจง / ประดิษฐ์เกินไป (เช่นCountแทนที่จะเป็นint) ใช้ประเภทที่กำหนดวัตถุของคุณไม่ซ้ำกันและไม่น่าสงสัยเมื่อใดก็ตามที่เป็นไปได้และทำงานได้

แก้ไข : สรุปสั้นลง สำหรับการใช้งานขนาดเล็ก (เช่นการพิสูจน์แนวคิด): ทำไมต้องกังวลกับการออกแบบที่ซับซ้อน? เพียงแค่ใช้Stringหรือintไปกับมัน

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

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


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

@Jubbat: แน่นอนฉันคิดมากกว่าสิ่งที่ผู้เขียนระบุ แต่ประเด็นของฉันคือคุณมีแอปพลิเคชั่นที่เรียบง่ายซึ่งในกรณีใดวิธีหนึ่งนั้นซับซ้อนเกินไป สำหรับขนาดนั้นการบำรุงรักษาไม่ใช่ปัญหาและความแตกต่างทางความหมายขัดขวางความเร็วการเข้ารหัสของคุณ หากในทางกลับกันแอปพลิเคชันของคุณมีขนาดใหญ่มันจะคุ้มค่าที่จะกำหนดประเภทของคุณอย่างถูกต้อง (แต่มันไม่น่าจะเป็นแบบห่อหุ้มง่าย) IMHO ตัวอย่างของเขาไม่น่าเชื่อหรือมีข้อบกพร่องในการออกแบบที่สำคัญเกินกว่าที่เขาพยายามทำ
Egon

2

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


2
+1 หมายถึงการรักษาอาการมากกว่าสาเหตุ
งาน

2

ฉันจะบอกว่ามันเป็นความคิดที่ดีจริงๆในภาษาที่มีตัวพิมพ์ที่มีคุณสมบัติคล้ายกันมาก

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


0

มันจะดี IF String (end Integer และ ... การพูดเกี่ยวกับ String เท่านั้น) ยังไม่เป็นที่สิ้นสุดดังนั้นคลาสเหล่านี้อาจมีบางอย่าง (ถูก จำกัด ) สตริงที่มีความหมายและยังสามารถส่งไปยังวัตถุบางอย่างที่ไม่มีการจัดการที่รู้วิธีจัดการ ประเภทฐาน (ไม่มีการสนทนาไปมา)

และ "goodnes" ของมันเพิ่มขึ้นเมื่อมีเช่น ข้อ จำกัด เกี่ยวกับชื่อทั้งหมด

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


0

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


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