Mùi mã là một cổ điển. Nó có mùi vì có thể có nhiều trường hợp có thể được chỉnh sửa hoặc cải thiện. Hầu hết những mùi này chỉ là dấu hiệu của điều gì đó có thể không ổn. Chúng không được yêu cầu cố định mỗi ngày… (Tuy nhiên, bạn nên xem xét nó.) Mã trước có mùi Phần I Phần II Phần III Phần IV Phần V Phần VI Phần VII Phần VIII Phần IX Phần X Phần XI Phần XII Phần XIII Phần XIV Phần XV Phần XVI Phần XVII Phần XVIII Phần XIX Phần XX Phần XXI Tiếp tục đi... Mã mùi 106 - Mã phụ thuộc sản xuất Không thêm IFs kiểm tra môi trường sản xuất. TL; DR: Tránh thêm các điều kiện liên quan đến sản xuất Các vấn đề Không vi phạm nguyên tắc nhanh Thiếu khả năng kiểm tra Các giải pháp Nếu hoàn toàn cần thiết, hãy mô hình hóa các môi trường và kiểm tra chúng. TẤT CẢ Định nghĩa bài văn Đôi khi, Chúng ta cần tạo ra các hành vi khác nhau trong phát triển và sản xuất. Ví dụ độ mạnh của mật khẩu. Trong trường hợp này, chúng ta cần định cấu hình môi trường với chiến lược sức mạnh và kiểm tra chiến lược chứ không phải bản thân môi trường. Mã mẫu Sai def send_welcome_email(email_address, environment): if ENVIRONMENT_NAME == "production": print(f"Sending welcome email to {email_address} from Bob Builder <bob@builder.com>") else: print("Emails are sent only on production") send_welcome_email("john@doe.com", "development") # Emails are sent only on production send_welcome_email("john@doe.com", "production") # Sending welcome email to john@doe.com from Bob Builder <bob@builder.com> Đúng class ProductionEnvironment: FROM_EMAIL = "Bob Builder <bob@builder.com>" class DevelopmentEnvironment: FROM_EMAIL = "Bob Builder Development <bob@builder.com>" # We can unit test environments # and even implement different sending mechanisms def send_welcome_email(email_address, environment): print(f"Sending welcome email to {email_address} from {environment.FROM_EMAIL}") # We can delegate into a fake sender (and possible logger) # and unit test it send_welcome_email("john@doe.com", DevelopmentEnvironment()) # Sending welcome email to john@doe.com from Bob Builder Development <bob@builder.com> send_welcome_email("john@doe.com", ProductionEnvironment()) # Sending welcome email to john@doe.com from Bob Builder <bob@builder.com> Phát hiện Hướng dẫn sử dụng [x] Đây là một mùi thiết kế. Chúng ta cần tạo các cấu hình phát triển / sản xuất trống và ủy quyền chúng bằng các đối tượng đa hình có thể tùy chỉnh. Thẻ Khớp nối Sự kết luận Tránh thêm các điều kiện không thể kiểm chứng. Tạo cấu hình ủy quyền các quy tắc kinh doanh. Sử dụng trừu tượng, giao thức và giao diện, tránh phân cấp cứng. Quan hệ Mã mùi 56 - Bộ tiền xử lý Thêm thông tin Làm thế nào để tránh những ifs gây phiền nhiễu Tín dụng Ảnh của on Birmingham Museums Trust Unsplash Dòng tweet này được lấy cảm hứng từ @ Jan Giacomelli Twitter Sự phức tạp là một dấu hiệu của sự non nớt về kỹ thuật. Tính đơn giản trong sử dụng là dấu hiệu thực sự của một sản phẩm thiết kế tốt cho dù đó là máy ATM hay tên lửa Patriot. Daniel T. Ling Trích dẫn tuyệt vời về kỹ thuật phần mềm Code Smell 107 - Sử dụng lại các biến Việc sử dụng lại các biến khiến phạm vi và ranh giới khó theo dõi hơn TL; DR: Không đọc và ghi cùng một biến cho các mục đích khác nhau Các vấn đề Khả năng đọc Vấn đề ẩn Các giải pháp Không sử dụng lại các biến để cô lập phạm vi Phương pháp trích xuất Định nghĩa bài văn Khi lập trình một kịch bản, người ta thường sử dụng lại các biến. Điều này dẫn đến sự nhầm lẫn và làm cho việc gỡ lỗi khó khăn hơn. Chúng ta nên thu hẹp phạm vi càng nhiều càng tốt. Mã mẫu Sai // print line total double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); // print amount total total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); // variable is reused Đúng function printLineTotal() { double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); } function printAmountTotal() { double total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); } Phát hiện Tự động [] Linters có thể sử dụng cây phân tích cú pháp để tìm định nghĩa và cách sử dụng biến. Thẻ Khả năng đọc Sự kết luận Tránh sử dụng lại tên biến. Sử dụng các tên cụ thể hơn và khác nhau. Quan hệ Code Smell 03 - Các hàm quá dài Thêm thông tin Tái cấu trúc 002 - Phương pháp giải nén Tín dụng Ảnh của trên Sigmund Unsplash Tính đơn giản trước tính tổng quát, sử dụng trước khi sử dụng lại. Kevlin Henney Trích dẫn tuyệt vời về kỹ thuật phần mềm Mã mùi 108 - Khẳng định nổi Việc khẳng định hai số thực là giống nhau là một bài toán rất khó TL; DR: Đừng so sánh phao Các vấn đề Kết quả kiểm tra sai Kiểm tra mong manh Không vi phạm nguyên tắc nhanh Các giải pháp Tránh thả nổi trừ khi bạn thực sự lo lắng về hiệu suất Sử dụng số chính xác tùy ý Nếu bạn cần so sánh phao so với dung sai. Định nghĩa bài văn So sánh số thực là một vấn đề khoa học máy tính cũ. Giải pháp thông thường là sử dụng so sánh ngưỡng. Chúng tôi khuyên bạn nên tránh thả nổi và cố gắng sử dụng số chính xác vô hạn. Mã mẫu Sai Assert.assertEquals(0.0012f, 0.0012f); // Deprecated Assert.assertTrue(0.0012f == 0.0012f); // Not JUnit - Smell Đúng Assert.assertEquals(0.0012f, 0.0014f, 0.0002); // true Assert.assertEquals(0.0012f, 0.0014f, 0.0001); // false // last parameter is the delta threshold Assert.assertEquals(12 / 10000, 12 / 10000); // true Assert.assertEquals(12 / 10000, 14 / 10000); // false Phát hiện Tự động [] Chúng ta có thể thêm check con trên các khung thử nghiệm của mình để tránh kiểm tra float. khẳng địnhEquals () Thẻ Kiểm tra mùi Sự kết luận Chúng ta nên luôn tránh so sánh thả nổi. Quan hệ Code Smell 71 - Magic Floats ngụy trang dưới dạng số thập phân Thêm thông tin Thất bại nhanh chóng Tín dụng Ảnh của trên Mika Baumeister Unsplash Chúa tạo ra các số tự nhiên; tất cả những thứ khác là công việc của con người. Leopold Kronecker Trích dẫn tuyệt vời về kỹ thuật phần mềm Code Smell 109 - Thuộc tính tự động Điều gì xảy ra nếu bạn kết hợp 4 mùi mã? TL; DR: Tránh Getters, Tránh Setters, Tránh Metaprogramming. Suy nghĩ về Hành vi. Các vấn đề Vi phạm che giấu thông tin Tính đột biến Lỗi vi phạm Nguyên tắc Nhanh Mã trùng lặp khi đặt thuộc tính Các giải pháp Loại bỏ bộ định vị tự động và bộ định vị Định nghĩa bài văn Người định cư và người thu tiền là một thói quen xấu trong ngành. Nhiều IDE thích mùi mã này. Một số ngôn ngữ cung cấp hỗ trợ rõ ràng để xây dựng các mô hình thiếu máu và DTO. Mã mẫu Sai class Person { public string name { get; set; } } Đúng class Person { private string name public Person(string personName) { name = personName; //imutable //no getters, no setters } //... more protocol, probably accessing private variable name } Phát hiện Tự động [] Đây là một tính năng ngôn ngữ. Chúng ta nên tránh các ngôn ngữ chưa trưởng thành hoặc cấm các phương pháp tồi tệ nhất của chúng. Thẻ Đóng gói Sự kết luận Chúng ta cần suy nghĩ kỹ trước khi phơi bày tài sản của mình. Bước đầu tiên là ngừng suy nghĩ về tài sản và chỉ tập trung vào hành vi. Quan hệ Mã Mùi 28 - Người định cư Mã Mùi 68 - Getters Code Smell 70 - Máy tạo mô hình thiếu máu Mã mùi 40 - DTOs Code Smell 01 - Mô hình thiếu máu Thêm thông tin Trường W3 Lười biếng I - Siêu lập trình Lười biếng II - Thuật sĩ mã Tái cấu trúc 001 - Xóa bộ định tuyến Sức mạnh tà ác của người đột biến Không nhanh Tín dụng Ảnh của trên Kony Unsplash Không có gì khó hơn là làm việc theo một thời hạn chặt chẽ và vẫn dành thời gian để dọn dẹp khi bạn đi. Kent Beck Trích dẫn tuyệt vời về kỹ thuật phần mềm Code Smell 110 - Chuyển đổi với mặc định Mặc định có nghĩa là 'mọi thứ chúng tôi chưa biết'. Chúng ta không thể nói trước được tương lai. TL; DR: Không thêm mệnh đề mặc định vào trường hợp của bạn. Thay đổi nó cho một ngoại lệ. Hãy rõ ràng. Các vấn đề Khớp nối Không thành công nhanh vi phạm nguyên tắc Mở đóng vi phạm nguyên tắc Các giải pháp Thay thế if và các trường hợp bằng tính đa hình Thay đổi mã Mặc định thành Ngoại lệ Định nghĩa bài văn Khi sử dụng các trường hợp, chúng tôi thường thêm một trường hợp mặc định để nó không bị lỗi. Thất bại luôn tốt hơn là đưa ra quyết định mà không có bằng chứng. Vì cũng là một mùi, chúng ta có thể tránh chúng. vỏ và công tắc Mã mẫu Sai switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; default: // if value does not presently match the above values // or future values // the following will be executed doSomethingSpecial(); break; } Đúng switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; case value3: case value4: // We currently know these options exist doSomethingSpecial(); break; default: // if value does not match the above values we need to take a decision throw new Exception('Unexpected case ' + value + ' we need to consider it'); break; } Phát hiện Bán tự động [x] Chúng tôi có thể nói với các linters của chúng tôi để cảnh báo chúng tôi về việc sử dụng mặc định trừ khi có một ngoại lệ. Thẻ Không nhanh Sự kết luận Viết mã mạnh mẽ không có nghĩa là chúng ta cần đưa ra quyết định mà không có bằng chứng. Quan hệ Code Smell 36 - Câu lệnh switch / case / elseif / else / if Thêm thông tin Không nhanh Tín dụng Ảnh của trên Joshua Woroniecki Unsplash Chi phí của việc thêm một tính năng không chỉ là thời gian để viết mã nó. Chi phí cũng bao gồm việc bổ sung một trở ngại cho việc mở rộng trong tương lai. Bí quyết là chọn các tính năng không chiến đấu với nhau. John Carmack Trích dẫn tuyệt vời về kỹ thuật phần mềm Và đó là tất cả cho bây giờ… Bài sau mình sẽ giải thích thêm về 5 mùi mã nhé!