Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Designing
Code

Làm thế nào để viết mã chấp nhận thay đổi

by
Length:LongLanguages:

Vietnamese (Tiếng Việt) translation by Andrea Ho (you can also view the original English article)

Viết mã, dễ thay đổi là Chén Thánh lập trình. Chào mừng bạn đến lập trình niết bàn! Nhưng thực tế mọi thứ khó khăn hơn nhiều: mã nguồn rất khó hiểu, sự phụ thuộc chỉ vào vô số hướng, khớp nối gây khó chịu và bạn sớm cảm nhận được sức nóng của địa ngục lập trình. Trong hướng dẫn này, chúng tôi sẽ thảo luận về một vài nguyên tắc, kỹ thuật và ý tưởng sẽ giúp bạn viết mã dễ thay đổi.


Một số khái niệm hướng đối tượng

Lập trình hướng đối tượng (OOP) trở nên phổ biến, do lời hứa của nó về tổ chức và tái sử dụng mã; nó hoàn toàn thất bại trong nỗ lực này. Chúng tôi đã sử dụng các khái niệm OOP trong nhiều năm nay, nhưng chúng tôi tiếp tục liên tục thực hiện logic tương tự trong các dự án của mình. OOP đã giới thiệu một tập hợp các nguyên tắc cơ bản tốt, nếu được sử dụng đúng cách, có thể dẫn đến mã tốt hơn, sạch hơn.

Sự gắn kết

Những thứ thuộc về nhau nên được giữ lại với nhau; nếu không, họ nên được chuyển đi nơi khác. Đây là những gì thuật ngữ, sự gắn kết, đề cập đến. Ví dụ tốt nhất về sự gắn kết có thể được chứng minh bằng một lớp:

Ví dụ này định nghĩa một lớp với các trường đại diện cho số lượng và kích thước. Những tính chất này, chỉ được đánh giá bằng tên của chúng, không thuộc về nhau. Sau đó chúng ta có hai phương thức, add () và sub trích (), chỉ hoạt động trên hai biến số. Chúng tôi tiếp tục có một phương thức area (), hoạt động trên các trường chiều dài và chiều rộng.

Rõ ràng là lớp này chịu trách nhiệm cho các nhóm thông tin riêng biệt. Nó có sự gắn kết rất thấp. Hãy cấu trúc lại nó.

Đây là một lớp học rất gắn kết. Tại sao? Bởi vì mỗi phần của lớp này thuộc về nhau. Bạn nên cố gắng để gắn kết, nhưng hãy cẩn thận, nó có thể khó đạt được.

Tính trực giao

Nói một cách đơn giản, tính trực giao đề cập đến sự cô lập hoặc loại bỏ các tác dụng phụ. Một phương thức, lớp hoặc mô-đun thay đổi trạng thái của các lớp hoặc mô-đun không liên quan khác không phải là trực giao. Ví dụ, hộp đen của máy bay là trực giao. Nó có chức năng bên trong, nguồn năng lượng bên trong, micro và cảm biến. Nó không có tác dụng đối với chiếc máy bay mà nó cư trú, hoặc trong thế giới bên ngoài. Nó chỉ cung cấp một cơ chế để ghi lại và lấy dữ liệu chuyến bay.

Một ví dụ về một hệ thống không trực giao như vậy là thiết bị điện tử của xe hơi của bạn. Tăng tốc độ xe của bạn có một số tác dụng phụ, chẳng hạn như tăng âm lượng radio (trong số những thứ khác). Tốc độ không trực giao với xe.

Trong ví dụ này, phương thức add () của lớp Máy tính thể hiện hành vi không mong muốn: nó tạo ra một đối tượng AlertMechanism và gọi một trong các phương thức của nó. Đây là hành vi bất ngờ và không mong muốn; người tiêu dùng thư viện sẽ không bao giờ mong đợi một tin nhắn được in ra màn hình. Thay vào đó, họ chỉ mong đợi tổng của các số được cung cấp.

Điều này tốt hơn. AlertMechanism không có hiệu lực trên Máy tính. Thay vào đó, AlertMechanism sử dụng bất cứ thứ gì nó cần để xác định xem có nên đưa ra cảnh báo hay không.

Phụ thuộc và khớp nối

Trong hầu hết các trường hợp, hai từ này có thể thay thế cho nhau; nhưng, trong một số trường hợp, một thuật ngữ được ưa thích hơn một thuật ngữ khác.

Vậy phụ thuộc là gì? Khi đối tượng A cần sử dụng đối tượng B, để thực hiện hành vi quy định của nó, chúng tôi nói rằng A phụ thuộc vào B. Trong OOP, sự phụ thuộc là cực kỳ phổ biến. Các đối tượng thường xuyên làm việc với và phụ thuộc vào nhau. Vì vậy, trong khi loại bỏ sự phụ thuộc là một sự theo đuổi cao quý, gần như không thể làm như vậy. Kiểm soát sự phụ thuộc và giảm chúng, tuy nhiên, tốt hơn là.

Các thuật ngữ, khớp nối nặng và khớp nối lỏng lẻo, thường đề cập đến mức độ một đối tượng phụ thuộc vào các đối tượng khác.

Trong một hệ thống kết hợp lỏng lẻo, những thay đổi trong một đối tượng có tác dụng giảm đối với các đối tượng khác phụ thuộc vào nó. Trong các hệ thống như vậy, các lớp phụ thuộc vào giao diện thay vì triển khai cụ thể (chúng ta sẽ nói nhiều hơn về điều đó sau). Đây là lý do tại sao các hệ thống kết hợp lỏng lẻo cởi mở hơn để sửa đổi.

Khớp nối trong một lĩnh vực

Hãy xem xét một ví dụ:

Rất phổ biến để xem loại mã này. Một lớp, Hiển thị trong trường hợp này, phụ thuộc vào lớp Máy tính bằng cách tham chiếu trực tiếp lớp đó. Trong đoạn mã trên, trường máy tính $ của Display là loại Máy tính. Đối tượng mà trường chứa là kết quả của việc gọi trực tiếp hàm tạo của Máy tính.

Ghép nối bằng cách truy cập các phương thức lớp khác

Xem lại đoạn mã sau để trình diễn loại khớp nối này:

Lớp Display hiển thị phương thức add () của đối tượng Máy tính. Đây là một hình thức ghép khác, bởi vì một lớp truy cập phương thức của lớp kia.

Khớp nối bằng phương pháp tham khảo

Bạn cũng có thể ghép các lớp với các tham chiếu phương thức. Ví dụ:

Điều quan trọng cần lưu ý là phương thức makeCalculator () trả về một đối tượng Máy tính. Đây là một sự phụ thuộc.

Khớp nối bằng đa hình

Kế thừa có lẽ là hình thức phụ thuộc mạnh nhất:

AdvancedCalculator không chỉ không thể thực hiện công việc của mình mà không có Máy tính, mà thậm chí còn không thể tồn tại mà không có nó.

Giảm khớp nối bằng cách tiêm phụ thuộc

Người ta có thể giảm khớp nối bằng cách tiêm một phụ thuộc. Đây là một ví dụ như vậy:

Bằng cách tiêm đối tượng Máy tính thông qua hàm tạo của Display, chúng tôi đã giảm sự phụ thuộc của Display vào lớp Máy tính. Nhưng đây chỉ là một nửa của giải pháp.

Giảm khớp nối với giao diện

Chúng ta có thể giảm hơn nữa việc ghép nối bằng cách sử dụng các giao diện. Ví dụ:

Bạn có thể nghĩ về ISP như một nguyên tắc gắn kết cấp cao hơn.

Mã này giới thiệu giao diện CanCompute. Một giao diện trừu tượng như bạn có thể nhận được trong OOP; nó định nghĩa các thành viên mà một lớp phải thực hiện. Trong trường hợp ví dụ trên, Máy tính thực hiện giao diện CanCompute.

Trình xây dựng của Display mong đợi một đối tượng thực hiện CanCompute. Tại thời điểm này, sự phụ thuộc của Display với Máy tính bị phá vỡ một cách hiệu quả. Bất cứ lúc nào, chúng ta có thể tạo một lớp khác thực hiện CanCompute và chuyển một đối tượng của lớp đó cho hàm tạo của Display. Hiển thị bây giờ chỉ phụ thuộc vào giao diện CanCompute, nhưng ngay cả sự phụ thuộc đó là tùy chọn. Nếu chúng ta không truyền đối số cho hàm tạo của Display, nó sẽ chỉ tạo một đối tượng Máy tính cổ điển bằng cách gọi makeCalculator (). Kỹ thuật này thường được sử dụng và cực kỳ hữu ích cho phát triển dựa trên thử nghiệm (TDD).


Các nguyên tắc RẮN

RẮN là một tập hợp các nguyên tắc để viết mã sạch, sau đó giúp dễ dàng thay đổi, duy trì và mở rộng hơn trong tương lai. Chúng là các khuyến nghị rằng, khi áp dụng cho mã nguồn, có tác động tích cực đến khả năng bảo trì.

Một ít lịch sử

Các nguyên tắc RẮN, còn được gọi là các nguyên tắc Agile, ban đầu được định nghĩa bởi Robert C. Martin. Mặc dù anh ta không phát minh ra tất cả những nguyên tắc này, anh ta là người kết hợp chúng lại với nhau. Bạn có thể đọc thêm về chúng trong cuốn sách của mình: Phát triển phần mềm, nguyên tắc, mô hình và thực tiễn. Các nguyên tắc của RẮN bao gồm một loạt các chủ đề, nhưng tôi sẽ trình bày chúng theo cách đơn giản nhất mà tôi có khả năng. Hãy hỏi để biết thêm chi tiết trong các ý kiến, nếu cần.

Nguyên tắc trách nhiệm duy nhất (SRP)

Một lớp học có một trách nhiệm duy nhất. Điều này nghe có vẻ đơn giản, nhưng đôi khi có thể khó hiểu và đưa vào thực tế.

Bạn nghĩ ai được lợi từ hành vi của lớp này? Chà, bộ phận kế toán là một lựa chọn (đối với số dư), bộ phận tài chính có thể là một bộ phận khác (đối với báo cáo thu nhập / thanh toán) và thậm chí bộ phận lưu trữ có thể in và lưu trữ các báo cáo.

Có bốn lý do tại sao bạn có thể phải thay đổi lớp này; mỗi bộ phận có thể muốn các phương thức tương ứng của họ được tùy chỉnh cho nhu cầu của họ.

SRP khuyến nghị nên chia các lớp như vậy thành các lớp nhỏ hơn, cụ thể hơn, mỗi lớp chỉ có một lý do để thay đổi. Các lớp như vậy có xu hướng gắn kết cao và liên kết lỏng lẻo. Theo một nghĩa nào đó, SRP là sự gắn kết được xác định theo quan điểm của người dùng.

Nguyên tắc đóng mở (OCP)

Các lớp (và mô-đun) nên hoan nghênh việc mở rộng chức năng của chúng, cũng như chống lại các sửa đổi của chức năng hiện tại của chúng. Hãy chơi với ví dụ cổ điển của quạt điện. Bạn có một công tắc và bạn muốn điều khiển quạt. Vì vậy, bạn có thể viết một cái gì đó dọc theo dòng:

Kế thừa có lẽ là hình thức phụ thuộc mạnh nhất.

Mã này xác định lớp Switch_ tạo và điều khiển đối tượng Quạt. Vui lòng lưu ý dấu gạch dưới sau "Switch_". PHP không cho phép bạn định nghĩa một lớp có tên "Switch".

Sếp của bạn quyết định rằng anh ta muốn điều khiển ánh sáng với cùng một công tắc. Đây là một vấn đề, bởi vì bạn phải thay đổi Switch_.

Bất kỳ sửa đổi nào đối với mã hiện tại là một rủi ro; các bộ phận khác của hệ thống có thể bị ảnh hưởng và yêu cầu sửa đổi hơn nữa. Luôn luôn tốt hơn là để chức năng hiện có một mình, khi thêm chức năng mới.

Trong thuật ngữ OOP, bạn có thể thấy Switch_ có sự phụ thuộc mạnh mẽ vào Fan. Đây là nơi vấn đề của chúng ta nằm và là nơi chúng ta nên thực hiện những thay đổi của mình.

Giải pháp này giới thiệu giao diện Switchable. Nó định nghĩa các phương thức mà tất cả các đối tượng kích hoạt chuyển đổi cần thực hiện. Quạt thực hiện Switchable và Switch_ chấp nhận tham chiếu đến đối tượng Switchable trong hàm tạo của nó.

Điều này giúp chúng ta như thế nào?

Đầu tiên, giải pháp này phá vỡ sự phụ thuộc giữa Switch_ và Fan. Switch_ không biết rằng nó khởi động một cái quạt, và nó cũng không quan tâm. Thứ hai, giới thiệu một lớp Light sẽ không ảnh hưởng đến Switch_ hoặc Switchable. Bạn có muốn điều khiển một đối tượng Light bằng lớp Switch_ của mình không? Chỉ cần tạo một đối tượng Light và chuyển nó tới Switch_, như thế này:

Nguyên tắc thay thế Liskov (LSP)

LSP tuyên bố rằng một lớp con không bao giờ nên phá vỡ chức năng của lớp cha. Điều này là vô cùng quan trọng bởi vì người tiêu dùng của một lớp cha mẹ mong muốn lớp đó cư xử theo một cách nhất định. Truyền một lớp con cho người tiêu dùng chỉ nên hoạt động và không ảnh hưởng đến chức năng ban đầu.

Điều này gây nhầm lẫn từ cái nhìn đầu tiên, vì vậy hãy xem xét một ví dụ cổ điển khác:

Ví dụ này định nghĩa một lớp Hình chữ nhật đơn giản. Chúng ta có thể đặt chiều cao và chiều rộng của nó và phương thức area () của nó cung cấp diện tích của hình chữ nhật. Sử dụng lớp Hình chữ nhật có thể trông như sau:

Phương thức orthArea () chấp nhận một đối tượng Hình chữ nhật làm đối số, đặt chiều cao và chiều rộng của nó và trả về diện tích của hình dạng.

Ở trường, chúng tôi được dạy rằng hình vuông là hình chữ nhật. Điều này gợi ý rằng nếu chúng ta mô hình hóa chương trình của mình thành đối tượng hình học, một lớp Square sẽ mở rộng một lớp Hình chữ nhật. Làm thế nào một lớp như vậy sẽ trông như thế nào?

Tôi có một thời gian khó khăn để tìm ra những gì để viết trong lớp Square. Chúng tôi có một số lựa chọn. Chúng ta có thể ghi đè phương thức area () và trả về bình phương $ width:

Lưu ý rằng tôi đã thay đổi các trường của Hình chữ nhật thành được bảo vệ, cho phép Square truy cập vào các trường đó. Điều này có vẻ hợp lý từ quan điểm hình học. Một hình vuông có cạnh bằng nhau; Trả lại bình phương chiều rộng là hợp lý.

Tuy nhiên, chúng tôi có một vấn đề từ quan điểm lập trình. Nếu Square là hình chữ nhật, chúng ta sẽ không gặp vấn đề gì khi đưa nó vào lớp Hình học. Nhưng, bằng cách đó, bạn có thể thấy rằng mã của Hình học không có nhiều ý nghĩa; nó đặt hai giá trị khác nhau cho chiều cao và chiều rộng. Đây là lý do tại sao hình vuông không phải là hình chữ nhật trong lập trình. LSP đã vi phạm.

Nguyên tắc phân chia giao diện (ISP)

Kiểm tra đơn vị nên chạy nhanh - rất nhanh.

Nguyên tắc này tập trung vào việc phá vỡ các giao diện lớn thành các giao diện nhỏ, chuyên biệt. Ý tưởng cơ bản là những người tiêu dùng khác nhau của cùng một lớp không nên biết về các giao diện khác nhau - chỉ những giao diện mà người tiêu dùng cần sử dụng. Ngay cả khi người tiêu dùng không trực tiếp sử dụng tất cả các phương thức công khai trên một đối tượng, nó vẫn phụ thuộc vào tất cả các phương thức. Vậy tại sao không cung cấp giao diện mà chỉ khai báo các phương thức mà mỗi người dùng cần?

Điều này phù hợp chặt chẽ rằng các giao diện nên thuộc về khách hàng và không thuộc về việc thực hiện. Nếu bạn điều chỉnh giao diện của mình theo các lớp tiêu thụ, chúng sẽ tôn trọng ISP. Việc thực hiện chính nó có thể là duy nhất, vì một lớp có thể thực hiện một số giao diện.

Hãy tưởng tượng rằng chúng tôi thực hiện một ứng dụng thị trường chứng khoán. Chúng tôi có một nhà môi giới mua và bán cổ phiếu, và nó có thể báo cáo thu nhập và thua lỗ hàng ngày. Việc triển khai rất đơn giản sẽ bao gồm một cái gì đó như giao diện Nhà môi giới, lớp NYSEBroker triển khai Nhà môi giới và một vài lớp giao diện người dùng: một để tạo giao dịch (TransitionsUI) và một để báo cáo (DailyReporter). Mã cho một hệ thống như vậy có thể tương tự như sau:

Trong khi mã này có thể hoạt động, nó vi phạm ISP. Cả DailyReporter và TransactionUI đều phụ thuộc vào giao diện Nhà môi giới. Tuy nhiên, mỗi người chỉ sử dụng một phần nhỏ của giao diện. TransactionUI sử dụng các phương thức buy () và sell (), trong khi DailyReporter sử dụng các phương thức DailyEarnings () và DailyLoss ().

Bạn có thể lập luận rằng Nhà môi giới không gắn kết vì nó có các phương thức không liên quan và do đó không thuộc về nhau.

Điều này có thể đúng, nhưng câu trả lời phụ thuộc vào việc triển khai của Nhà môi giới; bán và mua có thể liên quan mạnh mẽ đến các khoản lỗ và thu nhập hiện tại. Ví dụ, bạn có thể không được phép mua cổ phiếu nếu bạn đang mất tiền.

Bạn cũng có thể lập luận rằng Nhà môi giới cũng vi phạm SRP. Bởi vì chúng tôi có hai lớp sử dụng nó theo những cách khác nhau, có thể có hai người dùng khác nhau. Vâng, tôi nói không. Người dùng duy nhất có lẽ là nhà môi giới thực tế. Anh ấy / cô ấy muốn mua, bán và xem tiền hiện tại của họ. Nhưng một lần nữa, câu trả lời thực tế phụ thuộc vào toàn bộ hệ thống và doanh nghiệp.

ISP chắc chắn bị vi phạm. Cả hai lớp UI đều phụ thuộc vào toàn bộ Nhà môi giới. Đây là một vấn đề phổ biến, nếu bạn nghĩ các giao diện thuộc về việc triển khai chúng. Tuy nhiên, việc thay đổi quan điểm của bạn có thể gợi ý thiết kế sau:

Điều này thực sự có ý nghĩa và tôn trọng ISP. DailyReporter chỉ phụ thuộc vào BrokerStatistic; nó không quan tâm và không phải biết về bất kỳ hoạt động mua và bán nào. Mặt khác, giao dịchUI chỉ biết về mua và bán. NYSEBroker giống hệt với lớp trước của chúng tôi, ngoại trừ giờ đây nó thực hiện các giao diện BrokerTransilities và BrokerStatistic.

Bạn có thể nghĩ về ISP như một nguyên tắc gắn kết cấp cao hơn.

Khi cả hai lớp UI phụ thuộc vào giao diện Nhà môi giới, chúng tương tự như hai lớp, mỗi lớp có bốn trường, trong đó hai lớp được sử dụng trong một phương thức và hai lớp còn lại trong một phương thức khác. Các lớp học sẽ không được gắn kết.

Một ví dụ phức tạp hơn về nguyên tắc này có thể được tìm thấy trong một trong những bài viết đầu tiên của Robert C. Martin về chủ đề: Nguyên tắc phân chia giao diện.

Nguyên tắc đảo ngược phụ thuộc (DIP)

Nguyên tắc này nói rằng các mô-đun cấp cao không nên phụ thuộc vào các mô-đun cấp thấp; cả hai nên phụ thuộc vào trừu tượng. Trừu tượng không nên phụ thuộc vào chi tiết; chi tiết nên phụ thuộc vào trừu tượng. Nói một cách đơn giản, bạn nên phụ thuộc vào sự trừu tượng càng nhiều càng tốt và không bao giờ phụ thuộc vào việc triển khai cụ thể.

Thủ thuật với DIP là bạn muốn đảo ngược sự phụ thuộc, nhưng luôn muốn giữ luồng kiểm soát. Hãy xem xét ví dụ của chúng tôi từ OCP (các lớp Chuyển đổi và Ánh sáng). Trong triển khai ban đầu, chúng tôi đã có một công tắc trực tiếp điều khiển đèn.

Như bạn có thể thấy, cả phụ thuộc và luồng điều khiển từ Chuyển sang Ánh sáng. Mặc dù đây là những gì chúng tôi muốn, chúng tôi không muốn phụ thuộc trực tiếp vào Ánh sáng. Vì vậy, chúng tôi đã giới thiệu một giao diện.

Thật đáng ngạc nhiên khi chỉ cần giới thiệu một giao diện làm cho mã của chúng tôi tôn trọng cả DIP và OCP. Như bạn có thể thấy không, lớp phụ thuộc vào việc triển khai cụ thể của Ánh sáng và cả Ánh sáng và Chuyển đổi đều phụ thuộc vào giao diện Có thể chuyển đổi. Chúng tôi đã đảo ngược sự phụ thuộc và dòng kiểm soát không thay đổi.


Thiết kế cấp cao

Một khía cạnh quan trọng khác của mã của bạn là thiết kế cấp cao và kiến trúc chung. Một kiến trúc vướng víu tạo ra mã khó sửa đổi. Giữ một kiến trúc sạch sẽ là điều cần thiết và bước đầu tiên là hiểu cách phân tách các mối quan tâm khác nhau của mã của bạn.

Trong hình ảnh này, tôi đã cố gắng tóm tắt những mối quan tâm chính. Ở trung tâm của lược đồ là logic kinh doanh của chúng tôi. Nó nên được cách ly tốt với phần còn lại của thế giới, và có thể làm việc và hành xử như mong đợi mà không có sự tồn tại của bất kỳ phần nào khác. Xem nó như tính trực giao ở cấp độ cao hơn.

Bắt đầu từ bên phải, bạn có "chính" - điểm vào ứng dụng - và các nhà máy tạo đối tượng. Một giải pháp lý tưởng sẽ lấy các đối tượng của nó từ các nhà máy chuyên dụng, nhưng điều đó hầu như không thể hoặc không thực tế. Tuy nhiên, bạn nên sử dụng các nhà máy khi bạn có cơ hội để làm như vậy và giữ chúng bên ngoài logic kinh doanh của bạn.

Sau đó, ở phía dưới (màu cam), chúng tôi có sự kiên trì (cơ sở dữ liệu, truy cập tệp, truyền thông mạng) cho mục đích lưu giữ thông tin. Không có đối tượng trong logic kinh doanh của chúng tôi nên biết làm thế nào kiên trì hoạt động.

Bên trái là cơ chế giao hàng.

Một MVC, như Laravel hoặc CakePHP, chỉ nên là cơ chế phân phối, không có gì hơn.

Điều này cho phép bạn trao đổi một cơ chế với cơ chế khác mà không cần chạm vào logic kinh doanh của bạn. Điều này nghe có vẻ thái quá đối với một số bạn. Chúng tôi đã nói rằng logic kinh doanh của chúng tôi nên được đặt trong các mô hình của chúng tôi. Vâng, tôi không đồng ý. Các mô hình của chúng tôi phải là "mô hình yêu cầu", tức là các đối tượng dữ liệu câm được sử dụng để truyền thông tin từ MVC sang logic nghiệp vụ. Tùy chọn, tôi thấy không có vấn đề bao gồm xác nhận đầu vào trong các mô hình, nhưng không có gì hơn. Logic kinh doanh không nên có trong các mô hình.

Khi bạn nhìn vào kiến trúc hoặc cấu trúc thư mục của ứng dụng, bạn sẽ thấy một cấu trúc gợi ý những gì chương trình làm trái ngược với khung hoặc cơ sở dữ liệu bạn đã sử dụng.

Cuối cùng, hãy chắc chắn rằng tất cả các phụ thuộc đều hướng đến logic kinh doanh của chúng tôi. Giao diện người dùng, nhà máy, cơ sở dữ liệu là những triển khai rất cụ thể và bạn không bao giờ nên phụ thuộc vào chúng. Đảo ngược các phụ thuộc để hướng tới logic kinh doanh của chúng tôi mô đun hóa hệ thống của chúng tôi, cho phép chúng tôi thay đổi các phụ thuộc mà không sửa đổi logic kinh doanh.


Một số suy nghĩ về các mẫu thiết kế

Các mẫu thiết kế đóng một vai trò quan trọng trong việc làm cho mã dễ sửa đổi hơn, bằng cách đưa ra một giải pháp thiết kế chung mà mọi lập trình viên đều có thể hiểu được. Từ quan điểm cấu trúc, các mẫu thiết kế rõ ràng là lợi thế. Họ là những giải pháp được thử nghiệm và suy nghĩ tốt.

Nếu bạn muốn tìm hiểu thêm về các mẫu thiết kế, tôi đã tạo một khóa học Tuts + Premium về chúng!


Lực lượng kiểm tra

Test-Driven Development khuyến khích viết mã dễ kiểm tra. TDD buộc bạn phải tôn trọng hầu hết các nguyên tắc trên để làm cho mã của bạn dễ kiểm tra. Tiêm phụ thuộc và viết các lớp trực giao là rất cần thiết; nếu không, bạn kết thúc với các phương pháp thử nghiệm lớn. Các bài kiểm tra đơn vị nên chạy nhanh - thực sự rất nhanh và mọi thứ không được kiểm tra nên bị chế giễu. Việc chế nhạo nhiều lớp phức tạp cho một bài kiểm tra đơn giản có thể là quá sức. Vì vậy, khi bạn thấy mình chế nhạo mười đối tượng để kiểm tra một phương thức trên một lớp, bạn có thể gặp vấn đề với mã của mình ... không phải là thử nghiệm của bạn.


Tổng kết

Vào cuối ngày, tất cả phụ thuộc vào mức độ bạn quan tâm đến mã nguồn của mình. Có kiến thức kỹ thuật là không đủ; bạn cần áp dụng kiến thức đó nhiều lần, không bao giờ hài lòng 100% với mã của mình. Bạn phải muốn làm cho mã của bạn dễ bảo trì, làm sạch và mở để thay đổi.

Cảm ơn đã đọc và cảm thấy thoải mái để đóng góp kỹ thuật của bạn trong các ý kiến dưới đây.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.