CodeGym /จาวาบล็อก /สุ่ม /กฎการเข้ารหัส: ตั้งแต่การสร้างระบบไปจนถึงการทำงานกับอ็อบเ...
John Squirrels
ระดับ
San Francisco

กฎการเข้ารหัส: ตั้งแต่การสร้างระบบไปจนถึงการทำงานกับอ็อบเจกต์

เผยแพร่ในกลุ่ม
สวัสดีทุกคน! วันนี้เราอยากจะบอกคุณเกี่ยวกับการเขียนโค้ดที่ดี แน่นอนว่าไม่ใช่ทุกคนที่ต้องการเคี้ยวหนังสืออย่าง Clean Code ในทันที เนื่องจากหนังสือเหล่านี้มีข้อมูลจำนวนมาก แต่ไม่ค่อยมีความชัดเจนในตอนแรก และเมื่อคุณอ่านจบ คุณอาจฆ่าความปรารถนาที่จะเขียนโค้ดทั้งหมดของคุณ เมื่อพิจารณาจากทั้งหมดแล้ว วันนี้ฉันต้องการให้คำแนะนำเล็กๆ น้อยๆ (คำแนะนำชุดเล็กๆ) สำหรับการเขียนโค้ดที่ดีขึ้น ในบทความนี้ เราจะพูดถึงกฎพื้นฐานและแนวคิดที่เกี่ยวข้องกับการสร้างระบบและการทำงานกับอินเทอร์เฟซ คลาส และออบเจกต์ การอ่านบทความนี้จะใช้เวลาไม่นาน และหวังว่าคงจะไม่ทำให้คุณเบื่อ ฉันจะทำงานจากบนลงล่าง เช่น จากโครงสร้างทั่วไปของแอปพลิเคชันไปจนถึงรายละเอียดที่แคบลง กฎการเข้ารหัส: ตั้งแต่การสร้างระบบไปจนถึงการทำงานกับอ็อบเจกต์ - 1

ระบบ

ต่อไปนี้เป็นคุณลักษณะทั่วไปที่พึงประสงค์ของระบบ:
  • ความซับซ้อนน้อยที่สุด ต้องหลีกเลี่ยงโครงการที่ซับซ้อนมากเกินไป สิ่งที่สำคัญที่สุดคือความเรียบง่ายและชัดเจน (ง่ายกว่า = ดีกว่า)
  • ง่ายต่อการบำรุงรักษา เมื่อสร้างแอปพลิเคชัน คุณต้องจำไว้ว่าจะต้องมีการบำรุงรักษา (แม้ว่าคุณจะไม่ต้องรับผิดชอบในการบำรุงรักษาเป็นการส่วนตัวก็ตาม) ซึ่งหมายความว่ารหัสจะต้องชัดเจนและชัดเจน
  • ข้อต่อหลวม ซึ่งหมายความว่าเราลดจำนวนการพึ่งพาระหว่างส่วนต่างๆ ของโปรแกรมให้น้อยที่สุด (เพิ่มการปฏิบัติตามหลักการ OOP ให้มากที่สุด)
  • นำมาใช้ใหม่ เราออกแบบระบบของเราให้สามารถนำส่วนประกอบกลับมาใช้ใหม่ได้ในแอปพลิเคชันอื่นๆ
  • พกพาสะดวก ควรปรับระบบให้เข้ากับสภาพแวดล้อมอื่นได้ง่าย
  • สไตล์เครื่องแบบ เราออกแบบระบบของเราโดยใช้รูปแบบที่เหมือนกันในส่วนประกอบต่างๆ
  • ความสามารถในการขยาย (scalability) เราสามารถปรับปรุงระบบโดยไม่ละเมิดโครงสร้างพื้นฐาน (การเพิ่มหรือเปลี่ยนแปลงส่วนประกอบไม่ควรส่งผลกระทบต่อส่วนประกอบอื่นๆ ทั้งหมด)
แทบจะเป็นไปไม่ได้เลยที่จะสร้างแอปพลิเคชันที่ไม่ต้องการการปรับเปลี่ยนหรือเพิ่มฟังก์ชันการทำงานใหม่ เราจะต้องเพิ่มส่วนใหม่ๆ อยู่เสมอเพื่อช่วยให้ผลิตผลของเราทันกับเวลา นี่คือที่มาของความสามารถในการปรับขนาด ความสามารถในการปรับขนาดโดยพื้นฐานแล้วคือการขยายแอปพลิเคชัน เพิ่มฟังก์ชันการทำงานใหม่ และการทำงานกับทรัพยากรที่มากขึ้น (หรืออีกนัยหนึ่งคือ การโหลดที่มากขึ้น) กล่าวอีกนัยหนึ่ง เพื่อให้ง่ายต่อการเพิ่มตรรกะใหม่ เรายึดกฎบางอย่าง เช่น การลดการเชื่อมต่อของระบบโดยการเพิ่มโมดูลาร์กฎการเข้ารหัส: ตั้งแต่การสร้างระบบไปจนถึงการทำงานกับอ็อบเจกต์ - 2

ที่มาของภาพ

ขั้นตอนของการออกแบบระบบ

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

หลักการและแนวคิดทั่วไปในการออกแบบระบบ

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

อปท

ฉันต้องการทราบการเขียนโปรแกรมเชิงแง่มุมด้วย กระบวนทัศน์การเขียนโปรแกรมนี้เกี่ยวกับการแนะนำตรรกะที่โปร่งใส นั่นคือรหัสซ้ำ ๆ จะถูกใส่ในคลาส (ลักษณะ) และถูกเรียกใช้เมื่อตรงตามเงื่อนไขบางประการ ตัวอย่างเช่น เมื่อเรียกใช้เมธอดด้วยชื่อเฉพาะหรือเข้าถึงตัวแปรประเภทเฉพาะ บางครั้งแง่มุมต่างๆ อาจทำให้เกิดความสับสน เนื่องจากไม่ชัดเจนในทันทีว่าโค้ดถูกเรียกใช้จากที่ใด แต่นี่ยังคงเป็นฟังก์ชันที่มีประโยชน์มาก โดยเฉพาะอย่างยิ่งเมื่อแคชหรือเข้าสู่ระบบ เราเพิ่มฟังก์ชันนี้โดยไม่ต้องเพิ่มตรรกะเพิ่มเติมให้กับคลาสทั่วไป กฎสี่ข้อของ Kent Beck สำหรับสถาปัตยกรรมที่เรียบง่าย:
  1. การแสดงออก — ควรแสดงเจตนาของชั้นเรียนอย่างชัดเจน สิ่งนี้เกิดขึ้นได้จากการตั้งชื่อที่เหมาะสม ขนาดที่เล็ก และการยึดมั่นในหลักการความรับผิดชอบเดียว (ซึ่งเราจะพิจารณาในรายละเอียดเพิ่มเติมด้านล่าง)
  2. จำนวนคลาสและวิธีการขั้นต่ำ — ถ้าคุณต้องการสร้างคลาสให้มีขนาดเล็กและเน้นแคบที่สุดเท่าที่จะเป็นไปได้ คุณอาจไปไกลเกินไป (ส่งผลให้เกิดการต่อต้านรูปแบบการผ่าตัดด้วยปืนลูกซอง) หลักการนี้เรียกร้องให้รักษาระบบให้มีขนาดกะทัดรัดและไม่มากเกินไป โดยสร้างคลาสแยกต่างหากสำหรับทุกการกระทำที่เป็นไปได้
  3. ไม่มีการทำซ้ำ — โค้ดที่ซ้ำกันซึ่งสร้างความสับสนและเป็นตัวบ่งชี้ถึงการออกแบบระบบที่ไม่เหมาะสมจะถูกแยกและย้ายไปยังตำแหน่งอื่น
  4. รันการทดสอบทั้งหมด — ระบบที่ผ่านการทดสอบทั้งหมดสามารถจัดการได้ การเปลี่ยนแปลงใด ๆ อาจทำให้การทดสอบล้มเหลว เผยให้เห็นว่าการเปลี่ยนแปลงของเราในตรรกะภายในของเมธอดยังเปลี่ยนพฤติกรรมของระบบด้วยวิธีการที่ไม่คาดคิด

แข็ง

เมื่อออกแบบระบบ หลักการ SOLID ที่รู้จักกันดีนั้นควรค่าแก่การพิจารณา:

S (ความรับผิดชอบเดียว), O (เปิด-ปิด), L (การแทนที่ Liskov), I (การแยกส่วนต่อประสาน), D (การผกผันการพึ่งพา)

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

อินเตอร์เฟซ

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

ระดับ

กฎการเข้ารหัส: ตั้งแต่การสร้างระบบไปจนถึงการทำงานกับอ็อบเจกต์ - 3

ที่มาของภาพ

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

ขนาดชั้นเรียน

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

วัตถุ

การห่อหุ้ม

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

กฎของดีมีเตอร์

นอกจากนี้ เรายังสามารถพิจารณากฎของดีมีเตอร์ ซึ่งเป็นกฎชุดเล็กๆ ที่ช่วยในการจัดการความซับซ้อนในระดับคลาสและเมธอด สมมติว่าเรามี วัตถุ Carและมีเมธอดmove(Object arg1, Object arg2) ตามกฎของ Demeter วิธีนี้จำกัดเฉพาะการโทร:
  • วิธีการของ วัตถุ รถยนต์เอง (กล่าวอีกนัยหนึ่งคือวัตถุ "นี้");
  • วิธีการของวัตถุที่สร้างขึ้นภายในวิธีการย้าย
  • วิธีการของวัตถุที่ส่งผ่านเป็นอาร์กิวเมนต์ ( arg1 , arg2 );
  • วิธีการของวัตถุภายในรถยนต์ (อีกครั้ง "สิ่งนี้")
กล่าวอีกนัยหนึ่ง กฎของดีมีเตอร์เป็นเหมือนสิ่งที่พ่อแม่อาจพูดกับลูก: "คุณคุยกับเพื่อนได้ แต่คุยกับคนแปลกหน้าไม่ได้"

โครงสร้างข้อมูล

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

@Setter
@Getter
@NoArgsConstructor
public class UserDto {
    private long id;
    private String firstName;
    private String lastName;
    private String email;
    private String password;
}
ทุกอย่างดูชัดเจนเพียงพอ แต่ที่นี่เราเรียนรู้เกี่ยวกับการมีอยู่ของลูกผสม ไฮบริดคือวัตถุที่มีเมธอดสำหรับจัดการลอจิกที่สำคัญ จัดเก็บอิลิเมนต์ภายใน และยังรวมถึงเมธอด accessor (get/set) วัตถุดังกล่าวยุ่งเหยิงและทำให้ยากต่อการเพิ่มวิธีการใหม่ คุณควรหลีกเลี่ยงสิ่งเหล่านี้ เนื่องจากยังไม่ชัดเจนว่ามีไว้เพื่ออะไร — จัดเก็บองค์ประกอบหรือดำเนินการตรรกะ?

หลักการสร้างตัวแปร

ลองไตร่ตรองเล็กน้อยเกี่ยวกับตัวแปร โดยเฉพาะอย่างยิ่ง ลองนึกถึงหลักการที่ใช้เมื่อสร้าง:
  1. ตามหลักการแล้ว คุณควรประกาศและเริ่มต้นตัวแปรก่อนที่จะใช้งาน (อย่าสร้างตัวแปรขึ้นมาแล้วลืมมันไปซะ)
  2. เมื่อใดก็ตามที่เป็นไปได้ ให้ประกาศตัวแปรเป็นขั้นสุดท้ายเพื่อป้องกันไม่ให้ค่าเปลี่ยนแปลงหลังจากเริ่มต้น
  3. อย่าลืมเกี่ยวกับตัวแปรตัวนับ ซึ่งเรามักจะใช้ในforวนซ้ำ บางประเภท นั่นคืออย่าลืมทำให้เป็นศูนย์ มิฉะนั้นตรรกะทั้งหมดของเราอาจพัง
  4. คุณควรพยายามเริ่มต้นตัวแปรในตัวสร้าง
  5. หากมีตัวเลือกระหว่างการใช้อ็อบเจ็กต์ที่มีการอ้างอิงหรือไม่มี ( new SomeObject() ) ให้เลือกไม่ใช้ เนื่องจากหลังจากใช้อ็อบเจ็กต์แล้ว วัตถุนั้นจะถูกลบในรอบการรวบรวมขยะรอบถัดไป และทรัพยากรของวัตถุนั้นจะไม่สูญเปล่า
  6. รักษาอายุการใช้งานของตัวแปร (ระยะห่างระหว่างการสร้างตัวแปรและครั้งสุดท้ายที่มีการอ้างอิง) ให้สั้นที่สุด
  7. เริ่มต้นตัวแปรที่ใช้ในลูปก่อนลูป ไม่ใช่ที่จุดเริ่มต้นของเมธอดที่มีลูป
  8. เริ่มต้นด้วยขอบเขตที่จำกัดที่สุดเสมอ และขยายเมื่อจำเป็นเท่านั้น (คุณควรพยายามสร้างตัวแปรให้อยู่ในท้องถิ่นมากที่สุด)
  9. ใช้แต่ละตัวแปรเพื่อจุดประสงค์เดียวเท่านั้น
  10. หลีกเลี่ยงตัวแปรที่มีจุดประสงค์แอบแฝง เช่น ตัวแปรที่แยกระหว่างสองงาน — หมายความว่าประเภทของตัวแปรนี้ไม่เหมาะสำหรับการแก้งานใดงานหนึ่ง

วิธีการ

กฎการเข้ารหัส: ตั้งแต่การสร้างระบบไปจนถึงการทำงานกับอ็อบเจกต์ - 4

จากภาพยนตร์เรื่อง "Star Wars: Episode III - Revenge of the Sith" (2548)

มาดำเนินการโดยตรงกับการนำตรรกะของเราไปใช้ เช่น วิธีการ
  1. กฎข้อที่ 1 – ความกระชับ ตามหลักการแล้ว วิธีการไม่ควรเกิน 20 บรรทัด ซึ่งหมายความว่าหากเมธอดสาธารณะ "ขยาย" อย่างมาก คุณต้องคิดถึงการแยกลอจิกออกจากกันและย้ายไปยังเมธอดส่วนตัวที่แยกจากกัน

  2. กฎข้อที่ 2 — if , else , whileและคำสั่งอื่นๆ ไม่ควรมีบล็อกที่ซ้อนกันอย่างหนาแน่น: การซ้อนกันจำนวนมากจะลดความสามารถในการอ่านโค้ดลงอย่างมาก ตามหลักการแล้ว คุณไม่ควรมี บล็อก{}ที่ซ้อนกันไม่เกินสองบล็อก

    และควรเก็บโค้ดไว้ในบล็อกเหล่านี้ให้กะทัดรัดและเรียบง่าย

  3. กฎ #3 — วิธีการควรดำเนินการเพียงครั้งเดียว นั่นคือ ถ้าเมธอดใช้ตรรกะที่ซับซ้อนทุกประเภท เราจะแบ่งเมธอดนั้นออกเป็นเมธอดย่อย เป็นผลให้วิธีการนี้จะเป็นซุ้มที่มีจุดประสงค์เพื่อเรียกการดำเนินการอื่น ๆ ทั้งหมดตามลำดับที่ถูกต้อง

    แต่จะเป็นอย่างไรหากการดำเนินการดูเหมือนง่ายเกินไปที่จะแยกเป็นวิธีการอื่น จริงอยู่ บางครั้งอาจรู้สึกเหมือนยิงปืนใหญ่ใส่นกกระจอก แต่วิธีการเล็กๆ น้อยๆ ก็มีข้อดีหลายประการ:

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

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

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

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

  7. หากเมธอดมีพารามิเตอร์อินพุตจำนวนมาก (ค่าสุดขีดคือ 7 แต่คุณควรเริ่มคิดจริงๆ หลังจาก 2-3 ค่า) อาร์กิวเมนต์บางส่วนควรจัดกลุ่มเป็นวัตถุแยกต่างหาก

  8. หากมีเมธอดที่คล้ายกัน (โอเวอร์โหลด) หลายวิธี จะต้องส่งพารามิเตอร์ที่คล้ายกันในลำดับเดียวกัน ซึ่งจะช่วยเพิ่มความสามารถในการอ่านและการใช้งาน

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

  10. try/catchดูไม่ค่อยดีนักในธรรมชาติ ดังนั้นจึงเป็นความคิดที่ดีที่จะย้ายไปใช้วิธีขั้นกลางแยกต่างหาก (วิธีสำหรับจัดการข้อยกเว้น):

    
    public void exceptionHandling(SomeObject obj) {
        try {  
            someMethod(obj);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

ฉันได้พูดถึงโค้ดที่ซ้ำกันข้างต้นแล้ว แต่ขอย้ำอีกครั้ง: หากเรามีเมธอด 2-3 วิธีที่มีโค้ดซ้ำ เราจำเป็นต้องย้ายไปยังเมธอดที่แยกต่างหาก สิ่งนี้จะทำให้ทั้งเมธอดและคลาสกระชับขึ้น อย่าลืมกฎที่ควบคุมชื่อ: รายละเอียดเกี่ยวกับวิธีตั้งชื่อคลาส อินเทอร์เฟซ เมธอด และตัวแปรอย่างเหมาะสมจะกล่าวถึงในส่วนถัดไปของบทความ แต่นั่นคือทั้งหมดที่ฉันมีให้คุณในวันนี้
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION