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ó.)
Tiếp tục đi...
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
Đô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.
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]>
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]>
Đâ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.
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.
Ả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
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
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.
// 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
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 ); }
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.
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.
Code Smell 03 - Các hàm quá dài
Tái cấu trúc 002 - Phương pháp giải nén
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
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
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.
Assert.assertEquals(0.0012f, 0.0012f); // Deprecated Assert.assertTrue(0.0012f == 0.0012f); // Not JUnit - Smell
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
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.
Chúng ta nên luôn tránh so sánh thả nổi.
Code Smell 71 - Magic Floats ngụy trang dưới dạng số thập phân
Ả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
Đ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.
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.
class Person { public string name { get; set; } }
class Person { private string name public Person(string personName) { name = personName; //imutable //no getters, no setters } //... more protocol, probably accessing private variable name }
Đâ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.
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.
Code Smell 70 - Máy tạo mô hình thiếu máu
Code Smell 01 - Mô hình thiếu máu
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
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.
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.
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; }
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; }
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ệ.
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.
Code Smell 36 - Câu lệnh switch / case / elseif / else / if
Ả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é!