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 TẤT CẢ chúng.
Đị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 <[email protected]>") else: print("Emails are sent only on production") send_welcome_email("[email protected]", "development") # Emails are sent only on production send_welcome_email("[email protected]", "production") # Sending welcome email to [email protected] from Bob Builder <[email protected]>
Đúng
class ProductionEnvironment: FROM_EMAIL = "Bob Builder <[email protected]>" class DevelopmentEnvironment: FROM_EMAIL = "Bob Builder Development <[email protected]>" # 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("[email protected]", DevelopmentEnvironment()) # Sending welcome email to [email protected] from Bob Builder Development <[email protected]> send_welcome_email("[email protected]", ProductionEnvironment()) # Sending welcome email to [email protected] from Bob Builder <[email protected]>
Phát hiện
- [x] Hướng dẫn sử dụng
Đâ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ệ
Thêm thông tin
Tín dụng
Ảnh của Birmingham Museums Trust on Unsplash
Dòng tweet này được lấy cảm hứng từ @ Jan Giacomelli
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
- Phương pháp trích xuất để cô lập phạm vi
Đị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
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 khẳng địnhEquals () trên các khung thử nghiệm của mình để tránh kiểm tra float.
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
Tín dụng
Ảnh của Mika Baumeister trên 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
Đị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ệ
Code Smell 70 - Máy tạo mô hình thiếu máu
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
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ì vỏ và công tắc cũng là một mùi, chúng ta có thể tránh chúng.
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
- [x] Bán tự động
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
Tín dụng
Ảnh của Joshua Woroniecki trên 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é!