JavaRush /จาวาบล็อก /Random-TH /ข้อผิดพลาดทั่วไปในโค้ด Java
Sdu
ระดับ

ข้อผิดพลาดทั่วไปในโค้ด Java

เผยแพร่ในกลุ่ม
เนื้อหานี้มีข้อผิดพลาดทั่วไปส่วนใหญ่ที่ฉันเคยเห็นในโค้ด Java ของบุคคลที่ทำงานกับฉัน การวิเคราะห์แบบคงที่ (เราใช้qulice ) ด้วยเหตุผลที่ชัดเจน ไม่สามารถตรวจพบข้อผิดพลาดดังกล่าวทั้งหมดได้ ซึ่งเป็นสาเหตุที่ฉันตัดสินใจแสดงรายการไว้ที่นี่ ข้อผิดพลาดทั้งหมดนี้เกี่ยวข้องกับการเขียนโปรแกรมเชิงวัตถุโดยทั่วไปและโดยเฉพาะ Java
ชื่อชั้นเรียน
ชั้นเรียนของคุณควรเป็นสิ่ง ที่ เป็นนามธรรมของวัตถุในชีวิตจริงโดยไม่มี " validators " , " controllers " , " managers "ฯลฯ หากชื่อชั้นเรียนของคุณลงท้ายด้วย "-er" แสดงว่าการออกแบบไม่ดี และแน่นอนว่าคลาสตัวช่วยต่อต้านรูปแบบเช่น StringUtils , FileUtilsและ IOUtils ของ Apache เป็นตัวอย่างที่ดีของรูปแบบการออกแบบที่แย่มาก อย่าเพิ่มส่วนต่อท้ายหรือคำนำหน้าเพื่อแยกความแตกต่างระหว่างอินเทอร์เฟซและคลาส ตัวอย่างเช่น ชื่อทั้งหมดนี้แย่มาก: IRecord , IfaceEmployeeหรือ RecordInterface โดยทั่วไป ชื่ออินเทอร์เฟซคือชื่อของออบเจ็กต์ในชีวิตจริง ในขณะที่ชื่อคลาสควรอธิบายรายละเอียดการใช้งาน หากไม่มีสิ่งใดเฉพาะเจาะจงเกี่ยวกับการนำไปใช้งาน ชื่อ " Default ", " Simple " หรืออะไรทำนองนั้นก็จะมีผล ตัวอย่างเช่น: class SimpleUser implements User {}; class DefaultRecord implements Record {}; class Suffixed implements Name {}; class Validated implements Content {};
ชื่อวิธีการ
วิธีการสามารถส่งคืน " บางสิ่ง " หรือส่งคืน " เป็นโมฆะ " หากเมธอดส่งคืนบางสิ่ง ชื่อของมันควรจะอธิบายสิ่งที่จะถูกส่งคืน ตัวอย่างเช่น (อย่าใช้คำนำหน้า " get "): boolean isValid(String name); String content(); int ageOf(File file); หากส่งคืน " void " ชื่อควรชี้แจงว่าเมธอดนี้ทำอะไร ตัวอย่างเช่น: void save(File file); void process(Work work); void append(File file, String line); มีข้อยกเว้นเพียงข้อเดียวสำหรับกฎนี้ - วิธี ทดสอบ JUnit มีการอธิบายไว้ด้านล่าง
ชื่อวิธีทดสอบ
ชื่อวิธีการในการทดสอบ JUnit ต้องสร้างเป็นประโยคภาษาอังกฤษโดยไม่มีช่องว่าง วิธีนี้อธิบายได้ง่ายกว่าด้วยตัวอย่าง: สิ่ง /** * HttpRequest can return its content in Unicode. * @throws Exception If test fails */ public void returnsItsContentInUnicode() throws Exception { } สำคัญคือต้องเริ่มประโยคแรกของ JavaDoc ของคุณด้วยชื่อของคลาสที่คุณกำลังทดสอบตามด้วย “ can ” ดังนั้น ประโยคแรกควรเป็นเหมือนวลี " someone can do something " เสมอ ชื่อวิธีจะระบุสิ่งเดียวกัน แต่ไม่มีหัวข้อการทดสอบ ถ้าฉันเพิ่มไว้ที่ตอนต้นของชื่อเมธอด ฉันจะได้ประโยคภาษาอังกฤษที่สมบูรณ์ ดังตัวอย่างด้านบน: “ HttpRequest ส่งคืนเนื้อหาในรูปแบบ unicode ” โปรดทราบว่าชื่อวิธีทดสอบไม่ได้ขึ้นต้นด้วย " can " เฉพาะความคิดเห็น JavaDoc ที่ขึ้นต้นด้วย " can " นอกจากนี้ ชื่อวิธีการไม่ควรขึ้นต้นด้วยกริยา ( จากผู้แปล: เห็นได้ชัดว่าผู้เขียนหมายถึงอารมณ์ที่จำเป็นของกริยา ) แนวทางปฏิบัติที่ดีคือการระบุว่ามีข้อยกเว้นเกิดขึ้นเมื่อประกาศวิธีทดสอบ
ชื่อตัวแปร
หลีก เลี่ยงชื่อตัวแปรแบบผสม เช่น timeOfDay , firstItemหรือ httpRequest ฉันหมายถึงทั้งตัวแปรคลาสและตัวแปรวิธีการ ชื่อตัวแปรควรยาวพอที่จะหลีกเลี่ยงความคลุมเครือในขอบเขต แต่อย่ายาวเกินไปหากเป็นไปได้ ชื่อต้องเป็นคำนามเอกพจน์หรือพหูพจน์ ตัวอย่างเช่น: บางครั้งอาจมีการขัดแย้งกันระหว่างพารามิเตอร์ตัวสร้างและฟิลด์คลาสหากตัวสร้างเก็บข้อมูลอินพุตไว้ในวัตถุที่สร้างขึ้น ในกรณีนี้ แนะนำให้สร้างคำย่อโดยลบสระออก ตัวอย่าง: ในกรณีส่วนใหญ่ ชื่อตัวแปรที่ดีที่สุดจะเป็นชื่อของคลาสที่เกี่ยวข้อง เพียงแค่ ใช้อักษรตัวพิมพ์ใหญ่แล้วคุณจะไม่เป็นไร อย่างไรก็ตาม อย่าทำเช่นเดียวกันกับประเภทดั้งเดิมเช่นหรือ คุณยังสามารถใช้คำคุณศัพท์ได้เมื่อมีตัวแปรหลายตัวที่มีลักษณะแตกต่างกัน ตัวอย่างเช่น: List names; void sendThroughProxy(File file, Protocol proto); private File content; public HttpRequest request; public class Message { private String recipient; public Message(String rcpt) { this.recipient = rcpt; } } File file; User user; Branch branch; Integer number String string String contact(String left, String right);
คอนสตรัคเตอร์
โดยไม่มีข้อยกเว้น ควรมีตัวสร้างเพียงตัวเดียวเท่านั้นที่เก็บข้อมูลลงในตัวแปรอ็อบเจ็กต์ ตัวสร้างอื่นๆ ทั้งหมดจะต้องเรียกอันนี้ด้วยพารามิเตอร์ที่แตกต่างกัน: public class Server { private String address; public Server(String uri) { this.address = uri; } public Server(URI uri) { this(uri.toString()); } }
ตัวแปรแบบครั้งเดียว
หลีกเลี่ยงตัวแปรที่เกิดครั้งเดียวโดยเสียค่าใช้จ่ายทั้งหมด โดย “ทิ้ง” ฉันหมายถึงตัวแปรที่ใช้ครั้งเดียว เช่นเดียวกับในตัวอย่างนี้: String name = "data.txt"; return new File(name); ตัวแปรถูกใช้เพียงครั้งเดียว และโค้ดสามารถทำให้ง่ายขึ้นเป็น: return new File("data.txt"); บางครั้ง ในกรณีที่หายากมาก ซึ่งส่วนใหญ่เนื่องมาจากการจัดรูปแบบที่ดีกว่า - สามารถใช้ตัวแปรแบบครั้งเดียวได้ อย่างไรก็ตาม พยายามหลีกเลี่ยงสถานการณ์ดังกล่าว
ข้อยกเว้น
แน่นอนคุณไม่ควร "กลืน" ข้อยกเว้น ควรโยนให้สูงที่สุด ข้อยกเว้นจากวิธีการส่วนตัวจะต้องได้รับการจัดการจากภายนอก ห้ามใช้ข้อยกเว้นเพื่อควบคุมโฟลว์ รหัสในตัวอย่างไม่ถูกต้อง: int size; try { size = this.fileSize(); } catch (IOException ex) { size = 0; } จริงๆ แล้วถ้า IOException แจ้งว่า "ดิสก์เต็ม" คุณจะถือว่าขนาดไฟล์เป็นศูนย์แล้วดำเนินการต่อหรือไม่
การเยื้อง
สำหรับการเยื้อง กฎทั่วไปคือวงเล็บต้องสิ้นสุดบรรทัดหรือปิดบนบรรทัดเดียวกัน (ใช้กฎตรงกันข้ามสำหรับวงเล็บปิด) ในตัวอย่างด้านล่าง รหัสไม่ถูกต้องเนื่องจากวงเล็บแรกไม่ได้ปิดอยู่ในบรรทัดเดียวกันและมีอักขระอยู่ข้างหลัง วงเล็บเหลี่ยมที่สองมีปัญหาเดียวกันเนื่องจากมีอักขระอยู่ข้างหน้า และไม่มีวงเล็บเปิดในบรรทัดปัจจุบัน final File file = new File(directory, "file.txt"); การเยื้องที่ถูกต้องควรมีลักษณะดังนี้: StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join( Arrays.asList("a", "b") ) ), "separator" ); กฎสำคัญประการที่สองของการเยื้องคือ คุณควรวางให้มากที่สุดเท่าที่จะเป็นไปได้ในหนึ่งบรรทัด - ภายใน 80 อักขระ ตัวอย่างข้างต้นไม่ถูกต้องเนื่องจากสามารถบีบอัดได้: StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join(Arrays.asList("a", "b")) ), "separator" );
ค่าคงที่ซ้ำซ้อน
ค่าคงที่คลาสควรใช้เมื่อคุณต้องการแบ่งปันการเข้าถึงข้อมูลระหว่างวิธีการเรียน และข้อมูลนี้เป็นคุณลักษณะ( ! ) ของชั้นเรียนของคุณ อย่าใช้ค่าคงที่แทนสตริงหรือตัวอักษรตัวเลข - การปฏิบัติที่แย่มาก จะทำให้โค้ดเสียหาย ค่าคงที่ (เช่นเดียวกับวัตถุ OOP อื่นๆ) จะต้องมีความหมายในโลกแห่งความเป็นจริง ความหมายของค่าคงที่เหล่านี้ในโลกแห่งความเป็นจริงคืออะไร: class Document { private static final String D_LETTER = "D"; // bad practice private static final String EXTENSION = ".doc"; // good practice } ข้อผิดพลาดทั่วไปอีกประการหนึ่งคือการใช้ค่าคงที่ในการทดสอบหน่วยเพื่อหลีกเลี่ยงการทำซ้ำค่าสตริง/ตัวเลขในวิธีทดสอบ อย่าทำอย่างนั้น! วิธีการทดสอบแต่ละวิธีจะต้องดำเนินการกับชุดค่าอินพุตของตัวเอง ใช้ข้อความและตัวเลขใหม่ในแต่ละวิธีทดสอบใหม่ การทดสอบมีความเป็นอิสระ เหตุใดพวกเขาจึงควรแบ่งปันค่าคงที่อินพุตเดียวกัน
ทดสอบการเชื่อมต่อข้อมูล
นี่คือตัวอย่างของ hooking ในวิธีทดสอบ: User user = new User("Jeff"); // maybe some other code here MatcherAssert.assertThat(user.name(), Matchers.equalTo("Jeff")); ในบรรทัดสุดท้าย เราเชื่อม " Jeff " ด้วยสตริงลิเทอรัลเดียวกันกับที่ระบุไว้ในบรรทัดแรก ไม่กี่เดือนต่อมา ถ้ามีคนต้องการเปลี่ยนค่าในบรรทัดที่สาม เขา/เธอจะต้องใช้เวลาเพิ่มเติมในการค้นหาว่ามีที่ไหนใช้ " Jeff " ในวิธีนี้ เพื่อหลีกเลี่ยงไม่ให้ข้อมูลติดขัด คุณควรแนะนำตัวแปร
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION