1. Trang chủ
  2. » Luận Văn - Báo Cáo

Công nghệ phần mềm Tìm hiểu về Refactoring

33 24 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 33
Dung lượng 745,53 KB

Cấu trúc

  • Chương 1. Giới thiệu

  • Chương 2. Các nguyên lý về refactoring

    • 2.1. Định nghĩa refactoring

    • 2.2. Tại sao cần Refactor?

      • 2.2.1. Refactoring giúp cải thiện thiết kế

      • 2.2.2. Refactoring giúp phần mềm dễ hiểu hơn

      • 2.2.3. Refactoring giúp bạn lập trình nhanh hơn

  • Chương 3. Tiêu chí đánh giá source code tiêu chuẩn và thời điểm thích hợp để refactoring.

    • 3.1. Source code là gì ?

    • 3.2. Tiêu chí đánh giá source code đạt tiêu chuẩn ?

      • 3.2.1. Code chạy được! chạy được! chạy được!

      • 3.2.2. Code chạy đứng

      • 3.2.3. Giải quyết được vấn đề khách hàng yêu cầu

      • 3.2.4. Code có thể mở rộng

    • 3.3. Thời điểm tốt để refactoring code ?

      • 3.3.1. Khi thêm chức năng mới vào source cũ

      • 3.3.2. Khi tiến hành xem lại code và nâng cấp, tối ưu code

      • 3.3.3. Khi cần bàn giao lại

  • Chương 4. Các kỹ thuật Refactoring

    • 4.1. Composing Methods

      • 4.1.1. Kỹ thuật này dùng để làm gì ?

      • 4.1.2. Các kỹ thuật chính trong nhóm này

      • 4.1.3. Khi nào nên dùng kỹ thuật này ?

    • 4.2. Moving features between objects

      • 4.2.1. Kỹ thuật này dùng để làm gì ?

      • 4.2.2. Các kỹ thuật chính trong nhóm này

      • 4.2.3. Khi nào nên dùng kỹ thuật này ?

    • 4.3. Organizing data

      • 4.3.1. Kỹ thuật này dùng để làm gì ?

      • 4.3.2. Các kỹ thuật chính trong nhóm này

      • 4.3.3. Khi nào nên dùng kỹ thuật này ?

    • 4.4. Simplifying Conditional Expressions

      • 4.4.1. Kỹ thuật này dùng dể làm gì?

      • 4.4.2. Các kỹ thuật chính của nhóm này

      • 4.4.3. Khi nào nên sử dụng kỹ thuật này ?

    • 4.5. Simplifying Method Calls

      • 4.5.1. Kỹ thuật này dùng để làm gì?

      • 4.5.2. Các kỹ thuật chính của nhóm này

      • 4.5.3. Khi nào nên sử dụng kỹ thuật này ?

    • 4.6. Dealing With Generalizations

      • 4.6.1. Kỹ thuật này làm gì?

      • 4.6.2. Các kỹ thuật chính của nhóm này

      • 4.6.3. Khi nào nên sử dụng kỹ thuật này ?

  • Chương 5. Các công cụ Refactoring và Demo

    • 5.1. Tại sao cần sử dụng công cụ để Refactoring

    • 5.2. Giới thiệu các công cụ Refactoring được tích hợp sẵn vào các IDEs

      • 5.2.1. Đối với IDEs Inteliji IDEA

      • 5.2.1.a. Gọi chức năng Refactoring

      • 5.2.2. Đối với IDE Visual Studio Code

      • 5.2.3. Đối với IDE Visual Studio

    • 5.3. Các Plug-in hay sử dụng trong cac IDE

      • 5.3.1. Một số Plug-in cho IDE Visual Studio Code

      • 5.3.2. Một số Plug-in cho IDE Visual Studio

    • 5.4. Nhược điểm của các công cụ Refactoring

Nội dung

BÁO CÁO CÔNG NGHỆ PHẦN MỀM Đề Tài: Tìm Hiểu Về Refactoring   Mục Lục Chương 1. Giới thiệu 5 Chương 2. Các nguyên lý về refactoring 6 2.1. Định nghĩa refactoring 6 2.2. Tại sao cần refactor? 6 2.2.1. Refactoring giúp cải thiện thiết kế 6 2.2.2. Refactoring giúp phần mềm dễ hiểu hơn 7 2.2.3. Refactoring giúp bạn lập trình nhanh hơn 7 Chương 3. Tiêu chí đánh giá source code tiêu chuẩn và thời điểm thích hợp để refactoring. 9 3.1. Source code là gì ? 9 3.2. Tiêu chí đánh giá source code đạt tiêu chuẩn ? 9 3.2.1. Code chạy được chạy được chạy được 9 3.2.2. Code chạy đứng 9 3.2.3. Giải quyết được vấn đề khách hàng yêu cầu 10 3.2.4. Code có thể mở rộng 10 3.3. Thời điểm tốt để refactoring code ? 10 3.3.1. Khi thêm chức năng mới vào source cũ 10 3.3.2. Khi tiến hành xem lại code và nâng cấp, tối ưu code 11 3.3.3. Khi cần bàn giao lại 11 Chương 4. Các kỹ thuật Refactoring 12 4.1. Composing Methods 12 4.1.1. Kỹ thuật này dùng để làm gì ? 12 4.1.2. Các kỹ thuật chính trong nhóm này 12 4.1.3. Khi nào nên dùng kỹ thuật này ? 12 4.2. Moving features between objects 13 4.2.1. Kỹ thuật này dùng để làm gì ? 13 4.2.2. Các kỹ thuật chính trong nhóm này 13 4.2.3. Khi nào nên dùng kỹ thuật này ? 14 4.3. Organizing data 14 4.3.1. Kỹ thuật này dùng để làm gì ? 14 4.3.2. Các kỹ thuật chính trong nhóm này 14 4.3.3. Khi nào nên dùng kỹ thuật này ? 15 4.4. Simplifying Conditional Expressions 16 4.4.1. Kỹ thuật này dùng dể làm gì? 16 4.4.2. Các kỹ thuật chính của nhóm này 16 4.4.3. Khi nào nên sử dụng kỹ thuật này ? 17 4.5. Simplifying Method Calls 17 4.5.1. Kỹ thuật này dùng để làm gì? 17 4.5.2. Các kỹ thuật chính của nhóm này 17 4.5.3. Khi nào nên sử dụng kỹ thuật này ? 18 4.6. Dealing With Generalizations 19 4.6.1. Kỹ thuật này làm gì? 19 4.6.2. Các kỹ thuật chính của nhóm này 19 4.6.3. Khi nào nên sử dụng kỹ thuật này ? 20 Chương 5. Các công cụ Refactoring và Demo 21 5.1. Tại sao cần sử dụng công cụ để Refactoring 21 5.2. Giới thiệu các công cụ Refactoring được tích hợp sẵn vào các IDEs 22 5.2.1. Đối với IDEs Inteliji IDEA 22 5.2.1.a. Gọi chức năng Refactoring 22 5.2.2. Đối với IDE Visual Studio Code 25 5.2.3. Đối với IDE Visual Studio 26 5.3. Các Plugin hay sử dụng trong cac IDE 27 5.3.1. Một số Plugin cho IDE Visual Studio Code 28 5.3.2. Một số Plugin cho IDE Visual Studio 29 5.4. Nhược điểm của các công cụ Refactoring 29 Chương 1. Giới thiệu Refactoring là quá trình thay đổi một hệ thống phần mềm nhằm cái tiến cấu trúc bên trong nhưng không làm biến đổi hành vi bên ngoài của nó. Refactoring là việc dọn dẹp mã nguồn một cách có tổ chức sao cho tối thiểu hoá khả năng gây ra lỗi. Về bản chất refactoring là nâng cấp thiết kế của mã nguồn sau khi nó đã được viết ra. Trong những hiểu biết thông thường về công nghệ phần mềm, chúng ta thiết kế trước sau đó mới cài đặt. Cần có thiết kế tốt trước sau đó mới có cài đặt tốt. Qua thời gian, mã nguồn bị sửa đổi và sự nhất quán của hệ thống, cấu trúc của nó theo thiết kế, dần dần mờ nhạt. Quá trình cài đặt chuyển dần từ chế tạo sang chắp vá. Refactoring là cách làm ngược lại. Khi refactor bạn có thể lấy một thiết kế tồi, thậm chí là hỗn loạn, và làm lại để nó trở thành một mã nguồn được thiết kế tốt. Mỗi bước đều đơn giản, thậm chí rất đơn giản. Bạn chỉ chuyển một trường từ lớp này sang lớp khác, lấy vài đoạn mã ra khỏi phương thức để tạo ra phương thức riêng và đẩy vài đoạn mã lên hay xuống cây thừa kế. Tuy nhiên tác động tích luỹ của những thay đổi nhỏ đó có thể cái thiện đáng kể thiết kế. Đó là sự đảo ngược của khái niệm software decay. Khi refactor bạn sẽ nhận thấy sự phân phối công việc thay đổi. Thiết kế thay vì diễn ra đầu tiên, lại diễn ra liên tục trong suốt quá trình phát triển. Bạn học được cách cải tiến thiết kế từ việc xây dựng hệ thống. Kết quả của sự tương tác này dẫn đến một chương trình với thiết kế luôn tốt khi quá trình phát triển tiếp diễn. Qua quá trình phát triển của công nghệ phần mềm, cùng với sự phát triển mạnh mẽ của phần cứng thì yêu cầu về hiệu suất xử lý ngày càng ít quan trọng thay vào đó, tính dễ hiểu được đề cao. Do đó các kỹ thuật refactoring cũng ngày càng được chú ý nhằm nâng cao chất lượng phần mềm. Thực tế học tập của sinh viên Việt Nam cho thấy các phần mềm được viết trên ghế nhà trường thường không có được thiết kế tốt ngay từ ban đầu. Dẫn đến tình trạng này có rất nhiều nguyên nhân chủ quan lẫn khách quan như thiếu kinh nghiệm, thiếu thời gian, chưa chú trọng đến quy trình phát triển phần mềm v.v... Để những phần mềm này vượt ra khỏi phạm vi của những bài tập lớn, đồ án môn học, đồ án tốt nghiệp... tiếp tục phát triển thành sản phẩm thực tế và thành công trong cuộc sống thì kỹ năng refactoring là rất cần thiết. Chương 2. Các nguyên lý về refactoring 2.1. Định nghĩa refactoring Thuật ngữ refactoring được phát minh bởi Ward Cunningham và Kent Beck vào khoảng những năm 1980 khi làm việc với ngôn ngữ Smalltalk. Trong cuốn sách “Refactoring: Improving the Design of Existing Code” cung cấp hai định nghĩa như sau: Refactoring (danh từ): một sự thay đổi ở cấu trúc bên trong của phần mềm giúp nó dễ hiểu và dễ sửa đổi hơn mà không làm thay đổi hành vi bên ngoài. Refactor (động từ): tái cấu trúc phần mềm bằng cách áp dụng một loạt thao tác refactoring mà không làm thay đổi hành vi bên ngoài. Trong một số tài liệu tiếng Việt, refactoring được chuyển ngữ thành “cải tiến mã nguồn” tuy nhiên cách nói này khá dài dòng và cũng không diễn tả được hết ý nghĩa của thuật ngữ. Tài liệu này sẽ để nguyên thuật ngữ tiếng Anh với hai dạng như trên, ngoài ra refactoring cũng được hiểu là tổng hợp các phương pháp và công cụ để tiến hành refactor phần mềm nói chung. Như vậy, hiểu theo nghĩa nào đó refactor chỉ đơn giản là dọn dẹp mã nguồn. Tuy nhiên bằng cách áp dụng những phương pháp, công cụ của refactoring, việc dọn dẹp mã nguồn sẽ hiệu quả hơn đáng kể. Cần phân biệt refactoring và tối ưu hoá hiệu năng (performance optimization). Mục đích của refactoring là làm cho phần mềm dễ hiểu và dễ sửa chữa hơn. Tối ưu hoá hiệu năng cũng không làm thay đổi hành vi bên ngoài của phần mềm (trừ tốc độ) mà chỉ thay đổi cấu trúc bên trong tuy nhiên việc tối ưu hoá thường dẫn đến những đoạn mã nguồn khó hiểu và khó sửa chữa. Một đặc tính quan trọng nữa của refactoring là không thay đổi hành vi bên ngoài của phần mềm. Phần mềm vẫn phải thực hiện những chức năng giống hệt những gì nó làm trước đó. Người dùng, kể cả end user và lập trình viên, không thể nhận ra rằng có gì đó vừa thay đổi. 2.2. Tại sao cần Refactor? 2.2.1. Refactoring giúp cải thiện thiết kế Không có refactoring, thiết kế của phần mềm sẽ phân rã (software decay). Khi mã nguồn được thay đổi để hiện thực hoá những mục tiêu ngắn hạn hoặc thay đổi mà không hiểu đầy đủ thiết kế, mã nguồn mất dần cấu trúc. Ngày càng khó nhận ra thiết kế bằng cách đọc mã nguồn. Refactoring giống như sắp xếp lại mã nguồn. Bạn xếp lại những gì không ở đúng chỗ của nó. Sự mất cấu trúc của mã nguồn có hiệu ứng tích luỹ. Càng khó nhận ra thiết kế từ mã nguồn thì càng khó duy trì thiết kế đó. Refactoring thường xuyên có thể giúp mã nguồn giữ được hình dạng. Mã nguồn được thiết kế không tốt thường chữa nhiều đoạn mã làm cùng một việc, thông thường là do mã nguồn hay làm cùng một việc ở những chỗ khác nhau. Vì thế một khía cạnh quan trọng của cải tiến thiết kế là xoá bỏ những đoạn mã trùng lặp. Tầm quan trọng của việc này nằm ở những thay đổi mã nguồn trong tương lai. Giảm lượng mã không giúp hệ thống chạy nhanh hơn chút nào nhưng lại khiến việc sửa đổi dễ dàng hơn rất nhiều. Có ít mã cần phải hiểu hơn và chỉ cần sửa ở một nơi sự thay đổi sẽ được áp dụng trên toàn bộ hệ thống. 2.2.2. Refactoring giúp phần mềm dễ hiểu hơn Lập trình giống như cuộc trò chuyện với máy tính. Bạn viết mã để bảo máy tính cần phải làm gì và nó sẽ trả lời bằng cách làm chính xác điều bạn bảo. Bạn cần xoá bỏ khoảng cách giữa điều bạn muốn máy tính làm với điều bạn nói với nó. Lập trình theo cách hiểu này chỉ đơn giản là nói chính xác điều bạn muốn. Tuy nhiên còn có những người khác cần sử dụng mã nguồn của bạn. Ai đó sẽ thử đọc mã nguồn của bạn trong thời gian vài tháng để có thể sửa đổi vài chỗ. Chúng ta dễ quên mất người sử dụng bổ sung đó, trong khi họ thực ra lại là những người quan trọng nhất. Ai bận tâm nếu máy tính mất thêm vài xung nhịp để dịch? Nhưng sự khác biệt sẽ rất lớn nếu một lập trình viên mất một tuần để thực hiện một sự sửa đổi trong khi đáng lẽ mất vài giờ nếu anh ta hiểu mã nguồn của bạn. Bạn cũng có thể sử dụng refactoring như một cách để hiểu những đoạn mã của người khác. Đọc một vài dòng mã và cố gắng thay đổi nó để phản ánh đúng hơn cách hiểu của bạn sau đó thử chạy lại xem nó còn làm việc hay không. Với cách làm này dần dần bạn sẽ có hiểu biết chắc chắn về hệ thống và việc trở lại những đoạn mã đã được refactoring sẽ dễ dàng hơn nhiều. 2.2.3. Refactoring giúp bạn lập trình nhanh hơn Điều này nghe như một nghịch lý. Để nâng cao chất lượng mã nguồn, chúng ta cần đầu tư thời gian vào việc refactoring, chẳng phải việc đó sẽ làm giảm năng suất? Thực tế chứng minh rằng thiết kế tốt là rất quan trọng đối với tốc độ phát triển phần mềm. Không có một thiết kế tốt, bạn có thể tiến nhanh một lúc nhưng sau đó sẽ sớm chậm lại. Bạn phải dành thời gian tìm và sửa lỗi thay vì thêm chức năng mới. Việc sửa đổi lâu hơn vì bạn phải cố hiểu hệ thống và tìm những đoạn mã trùng lặp. Thiết kế tốt là điều kiện cần để duy trì tốc độ phát triển phần mềm và refactoring giúp bạn chống lại sự phân rã (decay) của thiết kế, thậm chí còn cải thiện thiết kế nữa. Chương 3. Tiêu chí đánh giá source code tiêu chuẩn và thời điểm thích hợp để refactoring. 3.1. Source code là gì ? Source code hay mã nguồn là những bộ mã chương trình được tạo ra bởi lập trình viên khi sử dụng ngôn ngữ lập trình. Chúng ta thường thấy source code được hiển thị ở dưới dạng văn bản. Trong source code sẽ tập hợp những dòng lệnh để tạo nên một thao tác nào đó trên website. Website quảng bá được coi như là bộ mặt của công ty nên các công ty thường không ngại chi một khoản không nhỏ để phát triển source code riêng của họ. Nói đến đây thì chúng ta đã hiểu được tầm quan trọng của source code. 3.2. Tiêu chí đánh giá source code đạt tiêu chuẩn ? Để tạo nên những phần mềm ứng dụng cho công việc và đời sống, hơn hết những dòng code phải thật sự chất lượng và những người viết code cũng thật sự hiểu chúng. Để đánh giá một source code tốt hay xấu, bằng cảm tính có thể thấy dễ dàng khi chạy phần mềm. Dưới đây là một số quy tắc định tính để đánh giá source code có đạt tiêu chuẩn hay không? 3.2.1. Code chạy được chạy được chạy được Điều quan trọng phải nhắc đến 3 lần, “chạy được” là vấn đề tiên quyết để khẳng định sự tồn tại của phần mềm.Nếu viết một chương trình dài 1000m trên không nhưng bị lỗi cơ bản như: lỗi biên dịch, tràn bộ nhớ,… thì tất nhiên công sức code cũng tan thành mây khói. Là người phát triển phần mềm, hơn ai hết, chúng ta đều hy vọng code chạy được. Để hy vọng không thành “tuyệt vọng” thì phải trải qua khổ luyện và kinh nghiệm nghiên cứu và thực hành để sửa các lỗi. 3.2.2. Code chạy đứng Đúng ở đây là đúng với mục đích người code muốn đạt được. Để đạt được điều này, người lập trình phải nắm vững các kiến thức cơ bản và nâng cao về chuyên môn của họ. Không phải ngẫu nhiên, những nền móng cơ bản cho người lập trình là cấu trúc dữ liệu, phân tích và thiết kế giải thuật, cơ sở dữ liệu, … Đó là nền tảng cơ bản để người lập trình có được tư duy logic hay nói cách khác là điều khiển được code của mình chạy đúng ý mình. 3.2.3. Giải quyết được vấn đề khách hàng yêu cầu Code chạy đúng ý của người viết ra code nhưng mục tiêu viết ra phần mềm là hướng tới người dùng. Những yêu cầu của khách hàng là những bài toán bắt buộc chúng ta phải có lời giải đúng và chính xác nhất. Để thực sự đáp ứng được nghiệp vụ mà khác hàng yêu cầu. Làm rõ những thắc mắc và thực hiện những trao đổi giữa các bên liên quan (khách hàng, dev, tester, … ) để tất cả cùng hiểu đúng “đầu ra” của sản phẩm. 3.2.4. Code có thể mở rộng Một phần mềm khi được viết ra thường được sử dụng cho mục đích hiện tại và cả trong tương tai luôn luôn có sự thay đổi. Vì thế quy mô phần mềm thường lớn dần đòi hỏi người lập trình cũng phải mở rộng code của mình. Những phần mềm luôn luôn duy trì hoạt động nâng cấp và mở rộng từng phút từng giờ như Facebook, Google, Twitter,… Vậy nên tiêu chí đánh giá code có thể dễ mở rộng là tiêu chí quan trọng để đánh giá một source code có thực sự tốt hay không? 3.3. Thời điểm tốt để refactoring code ? Với những tiêu chí đánh giá code như trên thì việc refactoring code là vô cùng quan trọng để ngày càng tiệm cận với độ hoàn hảo đạt được các tiêu chí. Vậy chúng ta có thể refactoring khi nào và thời điểm nào là hoàn hảo nhất để thực hiện refactoring? Câu trả lời là bất cứ lúc nào, bạn cũng có thể refactoring code của mình để code mình trông dễ hiểu, dễ sử dụng. Sau đây là một vài thời điểm “vàng” để refactoring. 3.3.1. Khi thêm chức năng mới vào source cũ Ứng với tiêu chí đánh giá thứ tư của một source code đạt tiêu chuẩn: code dễ mở rộng thì việc thêm một chức năng mới vào source cũ là thời điểm tốt để refactoring. Yêu cầu khách hàng thường chỉ có tăng chứ không giảm. Bất chợt đang sắp hoàn thành sản phẩm nhưng khách hàng yêu cầu thêm 1 tác vụ, 1 chức năng nữa thì bạn phải viết thêm code. Hoặc một source code bạn viết sẵn đã lâu không đụng đến, nay phải lôi ra và viết thêm 1 chức năng mới gì đấy. Đây là thời điểm bạn phải đọc lại source code cũ để dễ hiêu và thêm vào 1 phần mới, có thể phần mới này sẽ ảnh hưởng cả đến những phần source cũ thi đây là thời điểm thích hợp để refactoring. 3.3.2. Khi tiến hành xem lại code và nâng cấp, tối ưu code Ứng với tiêu chí đánh giá thứ nhất và thứ hai của một source code đạt tiêu chuẩn: việc tiến hành xem lại code, và tối ưu code là thời điểm tốt để refactoring. Lắm lúc chúng ta muốn code không bị cồng kềnh, cần tối ưu, thu gọn code của mình thì điều đầu tiên đặt ra là vẫn phải hoàn thiện tiêu chí “chạy được” và “chạy đúng”. Có thể xảy ra vài trường hợp khá bực tức là sau khi thu gọn, tối ưu thì các chức năng đã viết bị ảnh hưởng dẫn đến việc mất đi mối liên kết của phần mềm với người dùng. Do đó, đây cũng là thời điểm tốt để refactoring code. Làm cho code trở nên đơn giản nhưng vẫn giữ được bản chất, chức năng vốn có của phần mềm. 3.3.3. Khi cần bàn giao lại Ứng với tiêu chí thứ 3 của một source code đạt tiêu chuẩn: luôn luôn hướng đến khách hàng. Sản phẩm thì luôn đến tay người tiêu dùng. Vậy khách hàng phải là người hiểu và biết cách sử dụng cũng như tự canh chỉnh, thay đổi để thuận tiện việc quản lí và sử dụng. Có những đoạn code rắc rối, phức tạp chỉ người viết hiểu nên khi bàn giao lại cho khách hàng, người mới sử dụng sẽ gây khó khăn nên đây là thời điểm tốt để refactoring. Đây là vấn đề thường gặp của các bên thứ ba, bán và mua phần mềm để phục vụ cho doanh nghiệp, công ty,… Chương 4. Các kỹ thuật Refactoring Có rất nhiều kỹ thuật refactoring khác nhau, mỗi kỹ thuật đôi khi chỉ làm thay đổi một chút nho nhỏ mã nguồn, nhưng những thay đổi nhỏ đó được tích luỹ dần theo thời gian thì tạo nên một ảnh hưởng rất lớn, giúp cho hệ thống của chúng ta trở nên tốt hơn.Dưới đây là các nhóm kỹ thuật dùng để refactoring. 4.1. Composing Methods 4.1.1. Kỹ thuật này dùng để làm gì ? Trong hầu hết các trường hợp, các phương thức quá dài là gốc rễ của mọi vấn đề phát sinh (exception,bug... ). Những phương thức này khiến cho chương trình trở nên khó hiểu, che giấu tính logic, thứ tự thực hiện, khó khăn cho công tác bảo trì. Nhóm kỹ thuật này để hợp lý hóa các phương thức, loại bỏ sự trùng lặp code, mở đường cho các cải tiến trong tương lai. 4.1.2. Các kỹ thuật chính trong nhóm này • Extract Method (Tách phương thức) • Inline Method (Gộp phương thức) • Extract Variable (Tách biến) • Inline Temp (Gộp biến tạm thời) • Substitute Algorithm (Thay thế thuật toán) • Replace Temp with Query (Thay biến tạm bằng phương thức) • Split Temporary Variable (Tách biến tạm) • Remove Assignments to Parameters (Không thay đổi tham số) • Replace Method with Method Object (Thay phương thức bằng phương thức của đối tượng) 4.1.3. Khi nào nên dùng kỹ thuật này ?  Nếu phương thức của bạn quá dài do gộp quá nhiều tác vụ vào, gây mơ hồ khi đọc => Dùng kỹ thuật Extract Method.  Nếu phần thân của phương thức rõ ràng hơn tên của nó => Dùng kỹ thuật Inline Method  Nếu bạn có những biểu thức khó hiểu => Dùng kỹ thuật Extract Variable  Nếu bạn có một biến tạm thời được gán cho một phương thức đơn giản => Dùng kỹ thuật Inline Temp  Nếu bạn muốn một kết quả dùng được cho nhiều phương thức thay vì một phương thức => Dùng kỹ thuật Replace Temp with Query  Nếu bạn chỉ có một biến tạm để lưu kết quả cho tất cả các biểu thức => Dùng kỹ thuật Split Temporary Variable  Nếu bạn muốn tránh việc thay đổi tham số truyền vào => Dùng kỹ thuật Remove Assignments to Parameters  Nếu bạn có một phương thức quá dài với những biến cục bộ đan xen mà không thể dùng kỹ thuật Extract Method => Dùng kỹ thuật Replace Method with Method Object.  Nếu bạn muốn thay đổi thuật toán hiện tại => Dùng kỹ thuật Substitute Algorithm 4.2. Moving features between objects 4.2.1. Kỹ thuật này dùng để làm gì ? Mặc dù bạn có thể dùng chung các phương thức cho các class khác nhau nhưng trong một số trường hợp, việc này không phải là cách tốt nhất. Nhóm kỹ thuật này chỉ ra cách di chuyển các feature giữa các class một cách an toàn, tạo các lớp mới và ẩn các triển khai chi tiết khỏi các truy cập công khai. 4.2.2. Các kỹ thuật chính trong nhóm này • Move Method (Di chuyển phương thức) • Move Field (Di chuyển trườngthuộc tính) • Extract Class (Tách lớp) • Inline Class (Gộp lớp) • Hide Delegate (Ẩn uỷ quyền) • Remove Middle Man (Loại bỏ trung gian) • Introduce Foreign Method (Giới thiệu phương thức ngoài) • Introduce Local Extension (Giới thiệu tiện ích nội bộ) 4.2.3. Khi nào nên dùng kỹ thuật này ?  Nếu một phương thức được sử dụng ở class khác nhiều hơn class chứa nó => Dùng kỹ thuật Move Method  Nếu một trường được sử dụng ở class khác nhiều hơn class chứa nó => Dùng kỹ thuật Move Field  Nếu một class làm 2 việc trở lên => Dùng kỹ thuật Extract Class  Nếu một class hầu như không chịu trách nhiệm bất cứ việc gì mà chỉ ủy quyền cho class khác => Dùng kỹ thuật Inline Class  Nếu bạn không muốn cho client biết về chuỗi kết nối giữa các class => Dùng kỹ thuật Hide Delegate  Nếu bạn thấy việc gọi class này thông qua class khác là không cần thiết => Dùng kỹ thuật Remove Middle Man  Nếu một lớp tiện ích hay lớp được định nghĩa trước(predefined class) không có phương thức bạn cần, mà bạn không thể thêm phương thức này vào lớp đó => Dùng kỹ thuật Introduce Foreign Method  Nếu một lớp tiện ích hay lớp được định nghĩa trước không có một số phương thức bạn cần nhưng bạn không thể thêm các phương thức này vào lớp đó => Dùng kỹ thuật Introduce Local Extension 4.3. Organizing data 4.3.1. Kỹ thuật này dùng để làm gì ? Các kỹ thuật tái cấu trúc này giúp xử lý dữ liệu, thay thế các nguyên thủy bằng method class phong phú. Một kết quả quan trọng khác là gỡ rối các liên kết giữa các class, điều này làm cho các class linh động hơn và có thể tái sử dụng. 4.3.2. Các kỹ thuật chính trong nhóm này • Change Value to Reference (Thay đổi giá trị thành tham chiếu) • Change Reference to Value (Thay đổi tham chiếu thành giá trị) • Duplicate Observed Data (Trùng lặp dữ liệu quan sát) • Self Encapsulate Field (Trường tự đóng gói) • Replace Data Value with Object (Thay thế dữ liệu bằng đối tượng) • Replace Array with Object (Thay thế mảng bằng đối tượng) • Change Unidirectional Association to Bidirectional (Thay đổi liên kết một chiều thành hai chiều) • Change Bidirectional Association to Unidirectional (Thay đổi liên kết hai chiều thành một chiều) • Encapsulate Field (Đóng gói trường) • Encapsulate Collection (Đóng gói bộ) • Replace Magic Number with Symbolic Constant (Thay thế số bằng hằng số) • Replace Type Code with Class (Thay thế loại mã bằng lớp) • Replace Type Code with Subclasses (Thay thế loại mã bằng lớp con) • Replace Type Code with StateStrategy (Thay thế loại mã bằng trạng thái) • Replace Subclass with Fields (Thay thế lớp con bằng trường) 4.3.3. Khi nào nên dùng kỹ thuật này ?  Nếu bạn có nhiều trường hợp giống hệt nhau trong 1 class mà bạn cần thay thế chung bằng một đối tượng duy nhất => Dùng kỹ thuật Change Value to Reference  Nếu bạn có một đối tượng tham chiếu quá nhỏ và không thường xuyên được thay đổi để phù hợp với việc quản lý vòng đời của đối tượng đó => Dùng kỹ thuật Change Reference to Value  Nếu dữ liệu được lưu trữ các lớp chịu trách nhiệm về GUI => Dùng kỹ thuật Duplicate Observed Data  Nếu bạn sử dụng truy cập trực tiếp đến các thuộc tính riêng tư => Dùng kỹ thuật Self Encapsulate Field  Nếu một class (hoặc một nhóm các class) chứa một trường dữ liệu mà trường đó có hành vi riêng tư và dữ liệu liên quan => Dùng kỹ thuật Replace Data Value with Object.  Nếu bạn có một mảng chứa nhiều kiểu dữ liệu => Dùng kỹ thuật Replace Array with Object.  Nếu bạn có 2 class mà mỗi class cần sử dụng tính năng của class kia nhưng liên kết giữa chúng chỉ là một chiều => Dùng kỹ thuật Change Unidirectional Association to Bidirectional.  Nếu bạn có 2 class mà liên kết giữa chúng là 2 chiều nhưng chỉ có một class cần sử dụng tính năng của class kia => Dùng kỹ thuật Change Bidirectional Association to Unidirectional  Nếu bạn có các trườngthuộc tính công khai => Dùng kỹ thuật Encapsulate Field  Nếu có một class chứa một trường tập hợp và một getter và setter đơn giản để làm việc với tập hợp => Dùng kỹ thuật Encapsulate Collection.  Nếu bạn có một số có ý nghĩa và muốn thay đổi thành hằng số => Dùng kỹ thuật Replace Magic Number with Symbolic Constant.  Nếu một class có một thuộc tính chứa mã kiểu. Các giá trị của loại này không được sử dụng trong các điều kiện của toán tử và không ảnh hưởng đến hoạt động của chương trình => Dùng kỹ thuật Replace Type Code with Class  Nếu bạn có kiểu được mã hóa ảnh hưởng trực tiếp đến hành vi của chương trình (các giá trị của trường này kích hoạt nhiều mã khác nhau trong điều kiện) => Dùng kỹ thuật Replace Type Code with Subclass  Nếu có một loại được mã hóa ảnh hưởng đến hành vi nhưng bạn không thể sử dụng các subclass để loại bỏ nó => Dùng kỹ thuật Replace Type Code with StateStrategy.  Nếu có các lớp con chỉ khác nhau về phương thức( trả về không đổi) => Dùng kỹ thuật Replace Subclass with Fields. 4.4. Simplifying Conditional Expressions 4.4.1. Kỹ thuật này dùng dể làm gì? Các điều kiện có xu hướng ngày càng trở nên phức tạp hơn trong logic của chúng và kỹ thuật này dùng để chống lại điều này. 4.4.2. Các kỹ thuật chính của nhóm này • Consolidate Conditional Expression (Hợp nhất biểu thức có điều kiện) • Consolidate Duplicate Conditional Fragments (Hợp nhất các đoạn điều kiện trùng lặp) • Decompose Conditional (Phá hủy điều kiện) • Replace Conditional with Polymorphism (Thay thế điều kiện bằng tính đa hình) • Remove Control Flag (Loại bỏ cờ điều khiển) • Replace Nested Conditional with Guard Clauses (Thay thế điều kiện lồng nhau bằng các điều khoản bảo vệ) • Introduce Null Object (Giới thiệu đối tượng rỗng) • Introduce Assertion (Giới thiệu khẳng định) 4.4.3. Khi nào nên sử dụng kỹ thuật này ?  Nếu có nhiều điều kiện dẫn đến cùng một hành động hoặc kết quả => Dùng Consolidate Conditional Expression.  Nếu có các đoạn mã giống hệt nhau được tìm thấy trong các nhánh điều kiện => Dùng Consolidate Duplicate Conditional Fragments  Nếu có những điều kiện quá phức tạp => Dùng Decompose Conditional  Nếu bạn có các điều kiện thực hiện những hành động khác nhau dựa vào kiểu đối tượng hoặc thuộc tính => Dùng kỹ thuật Replace Conditional with Polymorphism.  Nếu có 1 biến boolean hành động như cờ điều khiển cho nhiều biểu thức Boolean.  Nếu có một nhóm các điều kiện lồng nhau và khó xác định quy trình thực thi mã bình thường.  Nếu bạn không muốn trả về null mà trả về đối tượng null thể hiện hành vi mặc định => Dùng kỹ thuật Introduce Null Object  Nếu bạn muốn các điều kiện hoặc giá trị đều phải dung => Dùng kỹ thuật Introduce Assertion. 4.5. Simplifying Method Calls 4.5.1. Kỹ thuật này dùng để làm gì? Kỹ thuật này khiến cho việc gọi phương thức trở nên đơn giản và dễ hiểu hơn. Điều này làm đơn giản hóa giao diện cho sự tương tác giữa các class. 4.5.2. Các kỹ thuật chính của nhóm này • Add Parameter (Thêm tham số) • Remove Parameter (Xóa tham số) • Rename Method (Đổi tên phương thức) • Separate Query from Modifier (Tách truy vấn khỏi công cụ sửa đổi ) • Parameterize Method (Tham số hóa) • Introduce Parameter Object (Giới thiệu đối tượng tham số) • Preserve Whole Object (Giữ toàn bộ đối tượng) • Remove Setting Method (Loại bỏ phương thức cài đặt) • Replace Parameter with Explicit Methods (Thay thế tham số bằng rõ ràng) • Replace Parameter with Method Call (Thay thế tham số bằng phương thức gọi) • Hide Method (Ẩn phương thức) • Replace Constructor with Factory Method (Thay thế phương thức khởi tạo bằng phương thức nhà máy) • Replace Error Code with Exception (Thay thế code lỗi bằng ngoại lệ) • Replace Exception with Test (Thay thế ngoại lệ bằng kiểm tra) 4.5.3. Khi nào nên sử dụng kỹ thuật này ?  Nếu một phương thức không có đủ dữ liệu để thực hiện các hành động nhất định => Dùng kỹ thuật Add Parameter  Nếu một tham số không được sử dụng trong phương thức => Dùng kỹ thuật Remove Parameter  Nếu tên của phương thức không giải thích được điều nó thực sự làm => Dùng kỹ thuật Rename Method  Nếu bạn có một phương thức trả về một giá trị nhưng bên trong nó có một thứ gì đó bị thay đổi => Dùng kỹ thuật Separate Query from Modifier  Nếu có phương thức chỉ khác nhau về giá trị, số hoặc phép toán => Dùng kỹ thuật Parameterize Method  Nếu phương thức của bạn chứa nhóm tham số lặp => Dùng kỹ thuật Introduce Parameter Object  Nếu bạn nhận một số giá trị từ 1 đổi tượng và sau đó chuyển chúng dưới dạng tham số cho một phương thức => Dùng kỹ thuật Preserve Whole Object  Nếu bạn muốn xóa các phương thức đặt thuộc tính => Dùng kỹ thuật Remove Setting Method.  Nếu có một phương thức được chia thành nhiều phần và mỗi phần hành động dựa vào giá trị của tham số => Dùng kỹ thuật Replace Parameter with Explicit Methods  Nếu gọi một phương thức truy vấn và truyền kết quả của nó như một tham số cho phương thức khác, trong khi phương thức đó có thể gọi truy vấn trực tiếp => Dùng kỹ thuật Replace Parameter with Method Call  Nếu một phương thức không được sử dụng bởi các lớp khác hoặc chỉ được sử dụng trong hệ thống phân cấp lớp của chính nó => Dùng kỹ thuật Hide Method.  Nếu bạn có một phương thức khởi tạo phức tạp không chỉ là thiết lập các giá trị tham số trong các thuộc tính => Dùng kỹ thuật Replace Constructor with Factory Method.  Nếu có một phương thức trả về một lỗi => Dùng kỹ thuật Replace Error Code with Exception.  Nếu bạn ném một ngoại lệ đến nơi kiểm tra ngoại lệ đó => Dùng kỹ thuật Replace Exception with Test. 4.6. Dealing With Generalizations 4.6.1. Kỹ thuật này làm gì? Trừu tượng có một nhóm kỹ thuật tái cấu trúc riêng, chủ yếu liên quan đến việc di chuyển chức năng dọc theo hệ thống phân cấp kế thừa lớp, tạo ra các lớp và giao diện mới, đồng thời thay thế kế thừa bằng ủy quyền và ngược lại. 4.6.2. Các kỹ thuật chính của nhóm này • Pull Up Field (Đẩy thuộc tính lên) • Pull Up Method (Đẩy phương thức lên) • Pull Up Constructor Body (Đẩy hàm khởi tạo lên) • Push Down Field (Đẩy thuộc tính xuống) • Push Down Method (Đẩy phương thức xuống) • Extract Subclass (Tách lớp con) • Extract Superclass (Tách lớp cha) • Extract Interface (Tách interface) • Collapse Hierarchy (Gộp biểu mẫu phân tách) • Form Template Method (Phương thức mẫu thay thế) • Replace Inheritance with Delegation (Thay thế kế thừa bằng ủy quyền) • Replace Delegation with Inheritance (Thay thế ủy quyền bằng kế thừa) 4.6.3. Khi nào nên sử dụng kỹ thuật này ?  Nếu 2 lớp có cùng thuộc tính => Dùng kỹ thuật Pull Up Field.  Nếu các lớp con có các phương thức hoạt động như nhau => Dùng kỹ thuật Pull Up Method.  Nếu các lớp con có các hàm khởi tạo với các mã hầu như giống nhau => Dùng kỹ thuật Pull Up Constructor Body.  Nếu chỉ có một lớp con sử dụng thuộc tính này => Dùng kỹ thuật Push Down Field.  Nếu một phương thức chỉ được sử dụng trong một lớp con => Dùng kỹ thuật Push Down Method.  Nếu một lớp có chức năng chỉ được sử dụng trong một số trường hợp nhất định => Dùng kỹ thuật Extract Subclass.  Nếu có 2 lớp có trường và phương thức chung => Dùng kỹ thuật Extract Superclass.  Nếu nhiều máy khách đang sử dụng cùng 1 phần của lớp giao diện hoặc một phần của lớp giao diện trong 2 lớp là như nhau => Dùng kỹ thuật Extract Interface.  Nếu bạn có một hệ thống phân cấp trong đó một lớp con giống với lớp cha => Dùng kỹ thuật Collapse Hierarchy,  Nếu các lớp con triển khai các thuật toán chứa các bước tương tự theo cùng một thứ tự => Dùng kỹ thuật Form Template Method.  Nếu có một lớp con chỉ sử dụng một phần các phương thức của lớp cha(hoặc không thể kể thừa dữ liệu của lớp cha) => Dùng kỹ thuật Replace Inheritance with Delegation.  Nếu có một lớp chứa nhiều phương thức đơn giản ủy quyền cho các phương thức khác => Dùng kỹ thuật Replace Delegation with Inheritance. Chương 5. Các công cụ Refactoring và Demo 5.1. Tại sao cần sử dụng công cụ để Refactoring Như chúng ta đã biết, kĩ thuật Refactoring loại bỏ những “Code Smells” khỏi mã nguồn của dự án. Nó có rất nhiều lợi ích cho kế hoạch lâu dài của dự án. Khi thực hiện Refactoring cho dự án, chúng ta cần chỉnh sửa rất nhiều mã lệnh. Nếu chúng ta theo một trong những quy chuẩn Refactoring như trên thì ta phải sửa rất nhiều vị trí mà các vị trí đó có cách sửa như nhau. Vậy nên các công cụ Refactoring được sinh ra để xử lí các tác vụ Refactoring nhanh hơn, chính xác hơn, tránh sai sót cho người phát triển dự án. Như hình trên, chương trình nguồn của dự án tồn tại rất nhiều lỗi (Bad Smells) mà con người không thể tìm ra hết để xử lí. Các công cụ Refactoring can thiệp trực tiếp vào môi trường phát triển ứng dụng (IDEs) để thực hiện chức năng Refactoring. Ứng với từng môi trường phát triển ứng dụng sẽ có các công cụ Refactoring được phát triển, giúp cho quá trình Refactoring trên các môi trường thuận tiện và hiệ quả. Khi sử dụng các công cụ Refactoring, nó có thể chỉ ra trong chương trình nguồn đó các vị trí mà nên Refactoring với các kĩ thuật Refactoring theo quy chuẩn và được cập nhật mới nhất, phục vụ cho việc Refactoring trở nên nhanh hơn, chính xác hơn, hiệu quả hơn. Các công cụ Refactoring được phân thành hai nhóm chính: • Các công cụ Refactoring được tích hợp sẵn vào các IDEs do nhà phát triển IDEs cung cấp. • Các công cụ Refactoring do bên thứ 3 phát triển (Plugin) 5.2. Giới thiệu các công cụ Refactoring được tích hợp sẵn vào các IDEs Hiện nay, có rất nhiều IDEs được sử dụng cho nhiều dự án với các ngôn ngữ khác nhau. Trong bài báo cáo này sẽ giới thiệu một số công cụ Refactoring được tích hợp sẵn trong các IDEs phổ biến như: Inteliji IDEA, Visual Studio Code, Visual Studio. 5.2.1. Đối với IDEs Inteliji IDEA 5.2.1.a. Gọi chức năng Refactoring 1. Chọn phần code cần refactoring (có thể chọn các files, các thư mục trong dự án hoặc các đoạn lệnh, dòng lệnh trong IDE) 2. Nhấn phím tắt Ctrl + Alt + T để mở danh sách các chức năng Refactoring do nhà cung cấp viết sẵn. Hình ảnh sau khi gọi chức năng Refactoring của IDE Inteliji IDEA 5.2.1.b. Xem trước thay đổi sau khi Refactoring 1. Để xem thay đổi, bấm vào nút Preview trong cửa sổ Refactoring. Cửa sổ Refactoring 2. Trong khi xem trước những thay đổi sau khi Refactoring, bạn có thể xoá (sử dụng phím Delete) hoặc di chuyển (sử dụng tổ hợp phím Ctrl + X) những thành phần đang có vấn đề. Xem trước những thay đổi code sau khi Refactoring 3. Sau khi xem xong những thay đổi, bạn kích vào Do Refactor để thực hiện Refactoring với những thay đổi như khi xem trước. 5.2.1.c. Xử lí xung đột code khi Refactoring Khi thực hiện Refactoring, có lúc sẽ xuất hiện một vài xung đột code. Inteliji đã hỗ trợ phần xử lí xung đột khi Refactoring. Cửa sổ xử lí xung đột khi Refactoring 1. Lựa chọn Continue để bỏ qua xung đột. Code Refactoring sẽ ghi đè code cũ mặc dù sẽ có vấn đề ở đó. 2. Lựa chọn Show Conflics in View để xem các nơi code bị xung đột bằng công cụ Find. Sau đó bạn có thể sửa lại những vùng đó cho phù hợp. Cửa sổ xem các nới bị xung đột code bằng công cụ Find 3. Lựa chọn Cancel để huỷ bỏ Refactoring. Code của bạn sẽ giữ nguyên và không có Refactoring xảy ra. 5.2.1.d Thiết lập cài đặt Refactoring Bạn có thể sửa lại cách mà công cụ Refactoring trong IDE Inteliji cung cấp hoạt động. 5.2.2. Đối với IDE Visual Studio Code Trong Visual Studio Code, có một chức năng tương tự như Refactoring như của Inteliji, gọi là Code Actions. Nó hỗ trợ Refactoring và Quickfix (dùng để sửa nhanh những vấn đề đơn giản). 5.2.2.a. Gọi chức năng Refactoring Cách 1: Bạn có thể gọi chức năng Code Actions (Code Actions bao gồm cả chức năng Refactoring) bằng tổ hợp phím Ctrl + . hoặc nhấn vào biểu tượng bóng đèn gần nơi muốn Refactoring. Code Actions trong VS Code Cách 2: Bạn chỉ dùng chức năng Refactoring thì nhấn tổ hợp phím Ctrl + Shift + R. 5.2.2.b. Thực hiện Refactoring 1. Tách hàm, tách biến Chọn đoạn code mà bạn muốn refactoring. Sau đó gọi chức năng Refactoring, bạn sẽ nhìn thấy các tuỳ chọn Refactoring có sẵn trong đó có các chức năng tách hàm (Extract to function), tách biến (Extract variable). 5.2.2.c. Đổi tên biến Chọn biến cần đổi tên, sau đó nhấn phím F2. Nhập tên biến mới vào rồi nhần Enter. IDE sẽ tự lựa chọn tất cả các biến có tên liên quan để đổi sang tên mới. Chức năng này có thể đổi tên biến giữa các file có liên quan với nhau. 5.2.3. Đối với IDE Visual Studio 5.2.3.a. Đổi tên biến, tên hàm 1. Chọn tên biến cần đổi 2. Chọn chức năng Quick Actions and Refactorings rồi chọn mục Change Signature. Sau đó đổi tên mới rồi nhấn OK. Đổi tên biến 5.2.3.b. Tách hàm 1. Chọn đoạn code cần tách hàm 2. Chọn chức năng Quick Actions and Refactorings rồi chọn mục Extract Method. Sau đó đổi tên mới rồi nhấn OK. 5.3. Các Plugin hay sử dụng trong cac IDE Hiện nay, nhiều nhà phát triển đã tạo ra những Plugin phục vụ cho quá trình Refactoring chạy trên môi trường của các IDE để lập trình viên dễ dàng sử dụng. 5.3.1. Một số Plugin cho IDE Visual Studio Code 5.3.2. Một số Plugin cho IDE Visual Studio 5.4. Nhược điểm của các công cụ Refactoring • Đôi khi, các công cụ Refactoring thay đổi ngữ nghĩa của code không mong muốn. • Đôi khi, các công cụ Refactoring thay đổi ngữ nghĩa của code không mong muốn. • Cần phải bỏ ra thời gian để học cách sử dụng các công cụ mới. • Một số công cụ hướng tới Refactoring theo một cách nào đó nhưng không phù hợp với hiện tại. • Nhiều công cụ phải trả phí để dùng. • Trong một dự án, nếu muốn dùng một công cụ Refactoring nào đó, cần phải có sự thống nhất giữa mọi người trong nhóm. Tài Liệu Tham Khảo 1 https:www.jetbrains.comhelpidearefactoringsourcecode.html 2 https:code.visualstudio.comdocseditorrefactoring 3 https:docs.microsoft.comenusvisualstudioiderefactoringinvisualstudio?view=vs2019 4 https:marketplace.visualstudio.com 5 https:marketplace.visualstudio.com

thiệu

Refactoring là quá trình cải tiến cấu trúc bên trong của hệ thống phần mềm mà không làm thay đổi hành vi bên ngoài Quá trình này giúp dọn dẹp mã nguồn một cách có tổ chức, giảm thiểu khả năng xảy ra lỗi Về bản chất, refactoring là việc nâng cấp thiết kế của mã nguồn sau khi đã hoàn thành viết.

Trong lĩnh vực công nghệ phần mềm, quy trình thường gặp là thiết kế trước, sau đó mới tiến hành cài đặt Một thiết kế tốt là điều kiện cần để có được cài đặt hiệu quả Tuy nhiên, theo thời gian, mã nguồn có thể bị thay đổi, dẫn đến sự mất nhất quán trong hệ thống và cấu trúc thiết kế ban đầu Điều này khiến cho quá trình cài đặt dần chuyển từ việc chế tạo sang chắp vá, ảnh hưởng đến chất lượng và hiệu suất của phần mềm.

Refactoring là quá trình cải thiện mã nguồn bằng cách biến đổi các thiết kế kém hoặc hỗn loạn thành mã được tổ chức tốt hơn Mỗi bước trong quá trình refactor đều đơn giản, như chuyển trường giữa các lớp, tách mã ra thành phương thức riêng, hoặc điều chỉnh cấu trúc thừa kế Mặc dù từng thay đổi nhỏ có vẻ không đáng kể, nhưng khi tích lũy lại, chúng có thể mang lại sự cải thiện đáng kể cho thiết kế tổng thể, ngược lại với khái niệm "software decay".

Khi thực hiện refactor, bạn sẽ thấy sự thay đổi trong phân phối công việc, với thiết kế không chỉ diễn ra ở giai đoạn đầu mà còn liên tục trong suốt quá trình phát triển Qua việc xây dựng hệ thống, bạn sẽ học cách cải tiến thiết kế, dẫn đến một chương trình có thiết kế ngày càng tốt hơn theo thời gian.

Trong quá trình phát triển công nghệ phần mềm, cùng với sự tiến bộ của phần cứng, yêu cầu về hiệu suất xử lý đã giảm bớt, trong khi tính dễ hiểu của mã nguồn ngày càng được coi trọng Vì vậy, các kỹ thuật refactoring đang trở nên phổ biến hơn nhằm nâng cao chất lượng phần mềm.

Thực trạng học tập của sinh viên Việt Nam cho thấy rằng phần mềm được phát triển trong môi trường học tập thường thiếu thiết kế tối ưu do nhiều nguyên nhân như thiếu kinh nghiệm, thời gian hạn chế và chưa chú trọng quy trình phát triển phần mềm Để các sản phẩm này có thể tiến xa hơn từ những bài tập lớn hay đồ án tốt nghiệp và trở thành sản phẩm thực tế thành công, cần có sự cải thiện trong quy trình học tập và phát triển phần mềm.

nguyên lý về refactoring

Định nghĩa refactoring

The term "refactoring" was coined by Ward Cunningham and Kent Beck in the 1980s while working with the Smalltalk programming language In their book "Refactoring: Improving the Design of Existing Code," they provide two definitions of the concept.

Refactoring là quá trình thay đổi cấu trúc bên trong của phần mềm, nhằm mục đích cải thiện khả năng hiểu và sửa đổi mà không làm thay đổi hành vi bên ngoài của nó.

Refactor (động từ): tái cấu trúc phần mềm bằng cách áp dụng một loạt thao tác refactoring mà không làm thay đổi hành vi bên ngoài.

Trong một số tài liệu tiếng Việt, thuật ngữ "refactoring" thường được dịch là “cải tiến mã nguồn”, nhưng cách diễn đạt này không hoàn toàn chính xác và có phần dài dòng Vì vậy, tài liệu này sẽ giữ nguyên thuật ngữ tiếng Anh "refactoring" và hiểu nó như là tổng hợp các phương pháp và công cụ dùng để cải tiến phần mềm.

Refactor có thể được hiểu là quá trình dọn dẹp mã nguồn, nhưng khi áp dụng các phương pháp và công cụ của refactoring, việc này sẽ trở nên hiệu quả hơn rất nhiều.

Cần phân biệt giữa refactoring và tối ưu hoá hiệu năng trong phát triển phần mềm Refactoring nhằm mục đích cải thiện tính dễ hiểu và khả năng sửa chữa của mã nguồn, trong khi tối ưu hoá hiệu năng chỉ thay đổi cấu trúc bên trong mà không ảnh hưởng đến hành vi bên ngoài, ngoại trừ tốc độ Tuy nhiên, quá trình tối ưu hoá thường dẫn đến mã nguồn trở nên khó hiểu và khó bảo trì.

Một đặc điểm quan trọng của refactoring là không làm thay đổi hành vi bên ngoài của phần mềm Phần mềm cần tiếp tục thực hiện các chức năng giống hệt như trước đây, đảm bảo rằng cả người dùng cuối và lập trình viên đều không nhận ra sự thay đổi nào vừa diễn ra.

Tại sao cần refactor?

2.2.1 Refactoring giúp cải thiện thiết kế

Không có refactoring, thiết kế phần mềm sẽ bị phân rã, dẫn đến sự mất cấu trúc của mã nguồn Khi mã nguồn được thay đổi để đáp ứng các mục tiêu ngắn hạn mà không hiểu rõ thiết kế ban đầu, việc nhận diện cấu trúc trở nên khó khăn hơn Refactoring là quá trình sắp xếp lại mã nguồn, giúp khôi phục lại sự tổ chức và dễ hiểu cho thiết kế Sự mất cấu trúc tích lũy theo thời gian, làm cho việc duy trì thiết kế trở nên phức tạp hơn Việc thực hiện refactoring thường xuyên là cần thiết để giữ cho mã nguồn luôn ở trạng thái tốt nhất.

Mã nguồn thiết kế kém thường chứa nhiều đoạn mã trùng lặp, điều này xảy ra khi cùng một chức năng được thực hiện ở nhiều vị trí khác nhau Do đó, việc loại bỏ mã trùng lặp là một yếu tố quan trọng trong cải tiến thiết kế Mặc dù việc giảm mã không làm tăng tốc độ hệ thống, nhưng nó giúp việc sửa đổi trở nên dễ dàng hơn Khi có ít mã cần hiểu hơn, việc chỉnh sửa chỉ cần thực hiện ở một nơi, và sự thay đổi sẽ tự động áp dụng cho toàn bộ hệ thống.

2.2.2 Refactoring giúp phần mềm dễ hiểu hơn

Lập trình giống như một cuộc trò chuyện giữa bạn và máy tính, nơi bạn viết mã để chỉ dẫn cho máy tính thực hiện nhiệm vụ cụ thể Để lập trình hiệu quả, bạn cần truyền đạt rõ ràng những gì bạn muốn máy tính làm, xóa bỏ mọi khoảng cách giữa ý tưởng và mã lệnh Hơn nữa, mã nguồn của bạn cũng có thể được sử dụng bởi những người khác, vì vậy việc viết mã rõ ràng và dễ hiểu là rất quan trọng.

Trong vài tháng tới, một người có thể sẽ xem xét mã nguồn của bạn để thực hiện những sửa đổi cần thiết Chúng ta thường quên rằng người sử dụng bổ sung là rất quan trọng Việc máy tính tiêu tốn thêm vài xung nhịp để dịch không phải là vấn đề lớn, nhưng nếu một lập trình viên mất một tuần để sửa đổi mã nguồn thay vì chỉ vài giờ, thì sự khác biệt này sẽ rất đáng kể.

Refactoring không chỉ giúp cải thiện mã nguồn mà còn là cách hiệu quả để hiểu mã của người khác Bằng cách đọc và thay đổi một số đoạn mã để phù hợp với cách hiểu của bạn, bạn có thể kiểm tra xem nó còn hoạt động hay không Qua quá trình này, bạn sẽ dần dần nắm vững hệ thống, và việc quay lại những đoạn mã đã được refactoring sẽ trở nên dễ dàng hơn rất nhiều.

2.2.3 Refactoring giúp bạn lập trình nhanh hơn Điều này nghe như một nghịch lý Để nâng cao chất lượng mã nguồn, chúng ta cần đầu tư thời gian vào việc refactoring, chẳng phải việc đó sẽ làm giảm năng suất? tiến nhanh một lúc nhưng sau đó sẽ sớm chậm lại Bạn phải dành thời gian tìm và sửa lỗi thay vì thêm chức năng mới Việc sửa đổi lâu hơn vì bạn phải cố hiểu hệ thống và tìm những đoạn mã trùng lặp.

Thiết kế tốt là yếu tố quan trọng để duy trì tốc độ phát triển phần mềm, trong khi refactoring không chỉ giúp ngăn chặn sự phân rã của thiết kế mà còn có khả năng cải thiện nó.

chí đánh giá source code tiêu chuẩn và thời điểm thích hợp để refactoring

Source code là gì ?

Mã nguồn, hay còn gọi là source code, là tập hợp các mã chương trình do lập trình viên tạo ra thông qua ngôn ngữ lập trình Thông thường, mã nguồn được trình bày dưới dạng văn bản.

Trong source code sẽ tập hợp những dòng lệnh để tạo nên một thao tác nào đó trên website.

Website quảng bá là bộ mặt của công ty, do đó, nhiều doanh nghiệp sẵn sàng đầu tư một khoản lớn để phát triển mã nguồn riêng Điều này cho thấy tầm quan trọng của mã nguồn trong việc xây dựng hình ảnh và thương hiệu.

Tiêu chí đánh giá source code đạt tiêu chuẩn ?

Để phát triển phần mềm ứng dụng hiệu quả, chất lượng mã nguồn là yếu tố then chốt, và lập trình viên cần nắm vững kiến thức về mã của mình Việc đánh giá mã nguồn có tốt hay không có thể thực hiện thông qua trải nghiệm khi sử dụng phần mềm Dưới đây là một số tiêu chí định tính để xác định chất lượng mã nguồn.

3.2.1 Code chạy được! chạy được! chạy được! Điều quan trọng phải nhắc đến 3 lần, “chạy được” là vấn đề tiên quyết để khẳng định sự tồn tại của phần mềm.Nếu viết một chương trình dài 1000m trên không nhưng bị lỗi cơ bản như: lỗi biên dịch, tràn bộ nhớ,… thì tất nhiên công sức code cũng tan thành mây khói Là người phát triển phần mềm, hơn ai hết, chúng ta đều hy vọng code chạy được Để hy vọng không thành “tuyệt vọng” thì phải trải qua khổ luyện và kinh nghiệm nghiên cứu và thực hành để sửa các lỗi

3.2.2 Code chạy đứng Đúng ở đây là đúng với mục đích người code muốn đạt được Để đạt được điều này, người lập trình phải nắm vững các kiến thức cơ bản và nâng cao về chuyên môn của họ Không phải ngẫu nhiên, những nền móng cơ bản cho người lập trình là cấu trúc dữ liệu, phân tích và thiết kế giải thuật, cơ sở dữ liệu, … Đó là nền tảng cơ bản để người lập trình có được tư duy logic hay nói cách khác là điều khiển được code của mình chạy đúng ý mình

3.2.3 Giải quyết được vấn đề khách hàng yêu cầu

Mục tiêu chính khi phát triển phần mềm là đáp ứng nhu cầu của người dùng, vì vậy việc hiểu và giải quyết các yêu cầu của khách hàng là rất quan trọng Để đảm bảo sản phẩm cuối cùng đúng với mong đợi, cần phải làm rõ những thắc mắc và thực hiện trao đổi hiệu quả giữa các bên liên quan như khách hàng, lập trình viên và kiểm thử viên Sự phối hợp này giúp tất cả các bên cùng hiểu rõ về "đầu ra" của sản phẩm.

3.2.4 Code có thể mở rộng

Phần mềm được phát triển không chỉ phục vụ nhu cầu hiện tại mà còn phải thích ứng với sự thay đổi trong tương lai, dẫn đến quy mô ngày càng lớn và yêu cầu lập trình viên phải mở rộng mã nguồn Các ứng dụng như Facebook, Google và Twitter liên tục nâng cấp và mở rộng, cho thấy rằng khả năng mở rộng của mã nguồn là tiêu chí quan trọng để đánh giá chất lượng của một source code.

Thời điểm tốt để refactoring code ?

Refactoring code là một bước quan trọng để nâng cao chất lượng và đạt được các tiêu chí đánh giá code Thời điểm lý tưởng để thực hiện refactoring là bất cứ lúc nào, giúp cho code trở nên dễ hiểu và dễ sử dụng hơn Dưới đây là một số thời điểm “vàng” để tiến hành refactoring.

3.3.1 Khi thêm chức năng mới vào source cũ Ứng với tiêu chí đánh giá thứ tư của một source code đạt tiêu chuẩn: code dễ mở rộng thì việc thêm một chức năng mới vào source cũ là thời điểm tốt để refactoring.

Yêu cầu của khách hàng thường chỉ gia tăng, và khi bạn gần hoàn thành sản phẩm, họ có thể yêu cầu thêm một chức năng mới, buộc bạn phải viết thêm code Nếu bạn cần làm việc với một source code cũ, việc đọc lại để hiểu rõ và thêm chức năng mới là rất cần thiết Đây cũng là cơ hội tốt để thực hiện refactoring, giúp cải thiện chất lượng code và đảm bảo rằng các phần mới không ảnh hưởng tiêu cực đến các phần cũ.

3.3.2 Khi tiến hành xem lại code và nâng cấp, tối ưu code Ứng với tiêu chí đánh giá thứ nhất và thứ hai của một source code đạt tiêu chuẩn: việc tiến hành xem lại code, và tối ưu code là thời điểm tốt để refactoring

Để tối ưu và thu gọn code mà không làm ảnh hưởng đến chức năng, điều quan trọng là phải đảm bảo rằng code vẫn "chạy được" và "chạy đúng" Việc thu gọn code có thể dẫn đến những vấn đề không mong muốn, như mất đi sự liên kết giữa phần mềm và người dùng Do đó, đây là thời điểm thích hợp để thực hiện refactoring, giúp làm cho code trở nên đơn giản hơn nhưng vẫn giữ nguyên bản chất và chức năng của phần mềm.

3.3.3 Khi cần bàn giao lại Ứng với tiêu chí thứ 3 của một source code đạt tiêu chuẩn: luôn luôn hướng đến khách hàng

Sản phẩm luôn đến tay người tiêu dùng, vì vậy khách hàng cần hiểu cách sử dụng và tự điều chỉnh để quản lý hiệu quả Những đoạn code phức tạp thường chỉ người viết mới hiểu, dẫn đến khó khăn cho người dùng mới khi tiếp nhận Đây là thời điểm thích hợp để thực hiện việc refactoring, đặc biệt là vấn đề thường gặp của các bên thứ ba trong việc mua bán phần mềm phục vụ doanh nghiệp.

kỹ thuật Refactoring

Composing Methods

4.1.1 Kỹ thuật này dùng để làm gì ?

Trong nhiều trường hợp, các phương thức quá dài là nguyên nhân chính gây ra các vấn đề như lỗi và ngoại lệ Những phương thức này làm cho chương trình trở nên khó hiểu, che khuất tính logic và thứ tự thực hiện, đồng thời gây khó khăn trong việc bảo trì Đội ngũ kỹ thuật đang nỗ lực hợp lý hóa các phương thức, loại bỏ sự trùng lặp mã nguồn và tạo điều kiện cho các cải tiến trong tương lai.

4.1.2 Các kỹ thuật chính trong nhóm này

 Extract Method (Tách phương thức)

 Inline Method (Gộp phương thức)

 Inline Temp (Gộp biến tạm thời)

 Substitute Algorithm (Thay thế thuật toán)

 Replace Temp with Query (Thay biến tạm bằng phương thức)

 Split Temporary Variable (Tách biến tạm)

 Remove Assignments to Parameters (Không thay đổi tham số)

 Replace Method with Method Object (Thay phương thức bằng phương thức của đối tượng)

4.1.3 Khi nào nên dùng kỹ thuật này ?

 Nếu phương thức của bạn quá dài do gộp quá nhiều tác vụ vào, gây mơ hồ khi đọc => Dùng kỹ thuật Extract Method.

 Nếu phần thân của phương thức rõ ràng hơn tên của nó => Dùng kỹ thuật Inline Method

 Nếu bạn có những biểu thức khó hiểu => Dùng kỹ thuật Extract Variable

 Nếu bạn có một biến tạm thời được gán cho một phương thức đơn giản => Dùng kỹ thuật Inline Temp

 Nếu bạn muốn một kết quả dùng được cho nhiều phương thức thay vì một phương thức => Dùng kỹ thuật Replace Temp with Query

 Nếu bạn chỉ có một biến tạm để lưu kết quả cho tất cả các biểu thức => Dùng kỹ thuật Split Temporary Variable

 Nếu bạn muốn tránh việc thay đổi tham số truyền vào => Dùng kỹ thuật Remove Assignments to Parameters

Nếu phương thức của bạn quá dài và chứa nhiều biến cục bộ phức tạp, không thể áp dụng kỹ thuật Extract Method, hãy xem xét sử dụng kỹ thuật Replace Method with Method Object Kỹ thuật này giúp cải thiện cấu trúc mã bằng cách chuyển đổi phương thức thành một đối tượng, từ đó làm cho mã dễ đọc và bảo trì hơn.

 Nếu bạn muốn thay đổi thuật toán hiện tại => Dùng kỹ thuật Substitute Algorithm

Moving features between objects

4.2.1 Kỹ thuật này dùng để làm gì ?

Mặc dù bạn có thể dùng chung các phương thức cho các class khác nhau nhưng trong một số trường hợp, việc này không phải là cách tốt nhất.

Nhóm kỹ thuật này hướng dẫn cách di chuyển các tính năng giữa các lớp một cách an toàn, đồng thời tạo ra các lớp mới và ẩn các chi tiết triển khai khỏi truy cập công khai.

4.2.2 Các kỹ thuật chính trong nhóm này

 Move Method (Di chuyển phương thức)

 Move Field (Di chuyển trường/thuộc tính)

 Hide Delegate (Ẩn uỷ quyền)

 Remove Middle Man (Loại bỏ trung gian)

 Introduce Foreign Method (Giới thiệu phương thức ngoài)

 Introduce Local Extension (Giới thiệu tiện ích nội bộ)

4.2.3 Khi nào nên dùng kỹ thuật này ?

 Nếu một phương thức được sử dụng ở class khác nhiều hơn class chứa nó => Dùng kỹ thuật Move Method

 Nếu một trường được sử dụng ở class khác nhiều hơn class chứa nó => Dùng kỹ thuật Move Field

 Nếu một class làm 2 việc trở lên => Dùng kỹ thuật Extract Class

 Nếu một class hầu như không chịu trách nhiệm bất cứ việc gì mà chỉ ủy quyền cho class khác => Dùng kỹ thuật Inline Class

 Nếu bạn không muốn cho client biết về chuỗi kết nối giữa các class => Dùng kỹ thuật Hide Delegate

 Nếu bạn thấy việc gọi class này thông qua class khác là không cần thiết => Dùng kỹ thuật Remove Middle Man

Nếu một lớp tiện ích hoặc lớp được định nghĩa trước không có phương thức cần thiết và bạn không thể thêm phương thức đó vào lớp, hãy áp dụng kỹ thuật Introduce Foreign Method.

Nếu một lớp tiện ích hoặc lớp được định nghĩa trước thiếu một số phương thức cần thiết và bạn không thể thêm các phương thức này vào lớp đó, bạn có thể áp dụng kỹ thuật Introduce Local Extension để giải quyết vấn đề.

Organizing data

4.3.1 Kỹ thuật này dùng để làm gì ?

Các kỹ thuật tái cấu trúc giúp cải thiện việc xử lý dữ liệu bằng cách thay thế các kiểu nguyên thủy bằng các phương thức trong class phong phú Điều này không chỉ giúp gỡ rối các mối liên kết giữa các class mà còn tăng cường tính linh động và khả năng tái sử dụng của chúng.

4.3.2 Các kỹ thuật chính trong nhóm này

 Change Value to Reference (Thay đổi giá trị thành tham chiếu)

 Change Reference to Value (Thay đổi tham chiếu thành giá trị)

 Duplicate Observed Data (Trùng lặp dữ liệu quan sát)

 Self Encapsulate Field (Trường tự đóng gói)

 Replace Data Value with Object (Thay thế dữ liệu bằng đối tượng)

 Replace Array with Object (Thay thế mảng bằng đối tượng)

 Change Unidirectional Association to Bidirectional (Thay đổi liên kết một chiều thành hai chiều)

 Change Bidirectional Association to Unidirectional (Thay đổi liên kết hai chiều thành một chiều)

 Encapsulate Field (Đóng gói trường)

Encapsulate Collection (Đóng gói bộ)

 Replace Magic Number with Symbolic Constant (Thay thế số bằng hằng số)

 Replace Type Code with Class (Thay thế loại mã bằng lớp)

 Replace Type Code with Subclasses (Thay thế loại mã bằng lớp con)

 Replace Type Code with State/Strategy (Thay thế loại mã bằng trạng thái)

 Replace Subclass with Fields (Thay thế lớp con bằng trường)

4.3.3 Khi nào nên dùng kỹ thuật này ?

Nếu bạn có nhiều trường hợp giống hệt nhau trong một lớp và cần thay thế chúng bằng một đối tượng duy nhất, hãy áp dụng kỹ thuật "Change Value to Reference".

Nếu bạn có một đối tượng tham chiếu nhỏ và không được cập nhật thường xuyên để phù hợp với quản lý vòng đời của nó, hãy áp dụng kỹ thuật "Change Reference to Value".

 Nếu dữ liệu được lưu trữ các lớp chịu trách nhiệm về GUI => Dùng kỹ thuật Duplicate Observed Data

 Nếu bạn sử dụng truy cập trực tiếp đến các thuộc tính riêng tư => Dùng kỹ thuật Self Encapsulate Field

 Nếu một class (hoặc một nhóm các class) chứa một trường dữ liệu mà trường đó có hành vi riêng tư và dữ liệu liên quan

=> Dùng kỹ thuật Replace Data Value with Object.

 Nếu bạn có một mảng chứa nhiều kiểu dữ liệu => Dùng kỹ thuật Replace Array with Object.

If you have two classes where each class needs to utilize the features of the other, but the relationship between them is unidirectional, you should apply the technique of changing unidirectional association to bidirectional.

If you have two classes with a bidirectional relationship, but only one class requires the functionality of the other, it's advisable to implement the technique of changing bidirectional association to unidirectional This approach simplifies the relationship and enhances code maintainability.

 Nếu bạn có các trường/thuộc tính công khai => Dùng kỹ thuật Encapsulate Field

 Nếu có một class chứa một trường tập hợp và một getter và setter đơn giản để làm việc với tập hợp => Dùng kỹ thuật Encapsulate Collection.

 Nếu bạn có một số có ý nghĩa và muốn thay đổi thành hằng số => Dùng kỹ thuật Replace Magic Number with Symbolic Constant.

Nếu một lớp có thuộc tính chứa mã kiểu và các giá trị của loại này không được sử dụng trong các điều kiện của toán tử cũng như không ảnh hưởng đến hoạt động của chương trình, thì nên áp dụng kỹ thuật "Thay thế mã kiểu bằng lớp".

Nếu kiểu được mã hóa ảnh hưởng trực tiếp đến hành vi của chương trình, với các giá trị của trường này kích hoạt nhiều mã khác nhau trong điều kiện, bạn nên áp dụng kỹ thuật "Replace Type Code with Subclass".

Nếu bạn gặp phải một loại mã hóa ảnh hưởng đến hành vi mà không thể loại bỏ bằng các subclass, hãy áp dụng kỹ thuật "Thay thế Mã loại bằng Trạng thái/Chiến lược" Kỹ thuật này giúp cải thiện tính linh hoạt và khả năng bảo trì của mã nguồn.

 Nếu có các lớp con chỉ khác nhau về phương thức( trả về không đổi) => Dùng kỹ thuật Replace Subclass with Fields.

Simplifying Conditional Expressions

4.4.1 Kỹ thuật này dùng dể làm gì?

Các điều kiện có xu hướng ngày càng trở nên phức tạp hơn trong logic của chúng và kỹ thuật này dùng để chống lại điều này.

4.4.2 Các kỹ thuật chính của nhóm này

 Consolidate Conditional Expression (Hợp nhất biểu thức có điều kiện)

 Consolidate Duplicate Conditional Fragments (Hợp nhất các đoạn điều kiện trùng lặp)

 Decompose Conditional (Phá hủy điều kiện)

 Replace Conditional with Polymorphism (Thay thế điều kiện bằng tính đa hình)

 Remove Control Flag (Loại bỏ cờ điều khiển)

 Replace Nested Conditional with Guard Clauses (Thay thế điều kiện lồng nhau bằng các điều khoản bảo vệ)

 Introduce Null Object (Giới thiệu đối tượng rỗng)

4.4.3 Khi nào nên sử dụng kỹ thuật này ?

 Nếu có nhiều điều kiện dẫn đến cùng một hành động hoặc kết quả => Dùng Consolidate Conditional Expression.

 Nếu có các đoạn mã giống hệt nhau được tìm thấy trong các nhánh điều kiện => Dùng Consolidate Duplicate

 Nếu có những điều kiện quá phức tạp => Dùng Decompose Conditional

 Nếu bạn có các điều kiện thực hiện những hành động khác nhau dựa vào kiểu đối tượng hoặc thuộc tính => Dùng kỹ thuật Replace Conditional with Polymorphism.

 Nếu có 1 biến boolean hành động như cờ điều khiển cho nhiều biểu thức Boolean.

 Nếu có một nhóm các điều kiện lồng nhau và khó xác định quy trình thực thi mã bình thường.

 Nếu bạn không muốn trả về null mà trả về đối tượng null thể hiện hành vi mặc định => Dùng kỹ thuật Introduce Null Object

 Nếu bạn muốn các điều kiện hoặc giá trị đều phải dung => Dùng kỹ thuật Introduce Assertion.

Simplifying Method Calls

4.5.1 Kỹ thuật này dùng để làm gì?

Kỹ thuật này giúp đơn giản hóa việc gọi phương thức, từ đó làm cho giao diện tương tác giữa các lớp trở nên dễ hiểu hơn.

4.5.2 Các kỹ thuật chính của nhóm này

 Add Parameter (Thêm tham số)

 Remove Parameter (Xóa tham số)

 Rename Method (Đổi tên phương thức)

 Separate Query from Modifier (Tách truy vấn khỏi công cụ sửa đổi )

 Parameterize Method (Tham số hóa)

 Introduce Parameter Object (Giới thiệu đối tượng tham số)

 Preserve Whole Object (Giữ toàn bộ đối tượng)

 Remove Setting Method (Loại bỏ phương thức cài đặt)

 Replace Parameter with Explicit Methods (Thay thế tham số bằng rõ ràng)

 Replace Parameter with Method Call (Thay thế tham số bằng phương thức gọi)

 Hide Method (Ẩn phương thức)

 Replace Constructor with Factory Method (Thay thế phương thức khởi tạo bằng phương thức nhà máy)

 Replace Error Code with Exception (Thay thế code lỗi bằng ngoại lệ)

 Replace Exception with Test (Thay thế ngoại lệ bằng kiểm tra)

4.5.3 Khi nào nên sử dụng kỹ thuật này ?

 Nếu một phương thức không có đủ dữ liệu để thực hiện các hành động nhất định => Dùng kỹ thuật Add Parameter

 Nếu một tham số không được sử dụng trong phương thức => Dùng kỹ thuật Remove Parameter

 Nếu tên của phương thức không giải thích được điều nó thực sự làm => Dùng kỹ thuật Rename Method

 Nếu bạn có một phương thức trả về một giá trị nhưng bên trong nó có một thứ gì đó bị thay đổi => Dùng kỹ thuật

 Nếu có phương thức chỉ khác nhau về giá trị, số hoặc phép toán => Dùng kỹ thuật Parameterize Method

 Nếu bạn nhận một số giá trị từ 1 đổi tượng và sau đó chuyển chúng dưới dạng tham số cho một phương thức => Dùng kỹ thuật Preserve Whole Object

 Nếu bạn muốn xóa các phương thức đặt thuộc tính => Dùng kỹ thuật Remove Setting Method.

Nếu một phương thức được chia thành nhiều phần và mỗi phần thực hiện hành động dựa vào giá trị của tham số, bạn nên áp dụng kỹ thuật "Thay thế tham số bằng các phương thức rõ ràng".

Khi gọi một phương thức truy vấn và truyền kết quả của nó như một tham số cho phương thức khác, trong khi phương thức đó có khả năng gọi truy vấn trực tiếp, bạn nên áp dụng kỹ thuật "Thay thế tham số bằng cuộc gọi phương thức".

Nếu một phương thức không được các lớp khác sử dụng hoặc chỉ được áp dụng trong hệ thống phân cấp của chính nó, thì nên áp dụng kỹ thuật Ẩn Phương Thức (Hide Method).

Nếu bạn đang sử dụng một phương thức khởi tạo phức tạp hơn việc chỉ thiết lập giá trị tham số trong các thuộc tính, hãy áp dụng kỹ thuật "Thay thế Constructor bằng Factory Method" để cải thiện thiết kế mã nguồn của bạn.

 Nếu có một phương thức trả về một lỗi => Dùng kỹ thuật Replace Error Code with Exception.

 Nếu bạn ném một ngoại lệ đến nơi kiểm tra ngoại lệ đó => Dùng kỹ thuật Replace Exception with Test.

Dealing With Generalizations

4.6.1 Kỹ thuật này làm gì?

Trừu tượng là một nhóm kỹ thuật tái cấu trúc, chủ yếu tập trung vào việc di chuyển chức năng trong hệ thống phân cấp kế thừa lớp Kỹ thuật này tạo ra các lớp và giao diện mới, đồng thời thay thế kế thừa bằng ủy quyền và ngược lại.

4.6.2 Các kỹ thuật chính của nhóm này

 Pull Up Field (Đẩy thuộc tính lên)

 Pull Up Method (Đẩy phương thức lên)

 Pull Up Constructor Body (Đẩy hàm khởi tạo lên)

 Push Down Field (Đẩy thuộc tính xuống)

 Push Down Method (Đẩy phương thức xuống)

 Extract Subclass (Tách lớp con)

 Extract Superclass (Tách lớp cha)

 Collapse Hierarchy (Gộp biểu mẫu phân tách)

 Form Template Method (Phương thức mẫu thay thế)

 Replace Inheritance with Delegation (Thay thế kế thừa bằng ủy quyền)

 Replace Delegation with Inheritance (Thay thế ủy quyền bằng kế thừa)

4.6.3 Khi nào nên sử dụng kỹ thuật này ?

 Nếu 2 lớp có cùng thuộc tính => Dùng kỹ thuật Pull Up Field.

 Nếu các lớp con có các phương thức hoạt động như nhau => Dùng kỹ thuật Pull Up Method.

 Nếu các lớp con có các hàm khởi tạo với các mã hầu như giống nhau => Dùng kỹ thuật Pull Up Constructor Body.

 Nếu chỉ có một lớp con sử dụng thuộc tính này => Dùng kỹ thuật Push Down Field.

 Nếu một phương thức chỉ được sử dụng trong một lớp con => Dùng kỹ thuật Push Down Method.

 Nếu một lớp có chức năng chỉ được sử dụng trong một số trường hợp nhất định => Dùng kỹ thuật Extract Subclass.

 Nếu có 2 lớp có trường và phương thức chung => Dùng kỹ thuật Extract Superclass.

Khi nhiều máy khách sử dụng cùng một phần của lớp giao diện hoặc một phần tương tự trong hai lớp khác nhau, việc áp dụng kỹ thuật Extract Interface là cần thiết để tối ưu hóa và tái sử dụng mã.

 Nếu bạn có một hệ thống phân cấp trong đó một lớp con giống với lớp cha => Dùng kỹ thuật Collapse Hierarchy,

 Nếu các lớp con triển khai các thuật toán chứa các bước tương tự theo cùng một thứ tự => Dùng kỹ thuật Form

If a subclass only utilizes a portion of the methods from its parent class or is unable to inherit the data from the parent class, it is advisable to implement the technique of replacing inheritance with delegation.

 Nếu có một lớp chứa nhiều phương thức đơn giản ủy quyền cho các phương thức khác => Dùng kỹ thuật Replace

Chương 5 Các công cụ Refactoring và Demo

Tại sao cần sử dụng công cụ để Refactoring

Kỹ thuật Refactoring giúp loại bỏ "Code Smells" khỏi mã nguồn dự án, mang lại nhiều lợi ích cho kế hoạch dài hạn Khi thực hiện Refactoring, việc chỉnh sửa mã lệnh là cần thiết, và nếu tuân theo quy chuẩn Refactoring, chúng ta sẽ phải sửa nhiều vị trí giống nhau Do đó, các công cụ Refactoring ra đời nhằm xử lý các tác vụ này nhanh chóng và chính xác, giảm thiểu sai sót cho các nhà phát triển.

Chương trình nguồn của dự án chứa nhiều lỗi (Bad Smells) mà con người khó có thể phát hiện và xử lý Các công cụ Refactoring được tích hợp trực tiếp vào môi trường phát triển ứng dụng (IDEs) để thực hiện chức năng Refactoring Mỗi môi trường phát triển ứng dụng sẽ có các công cụ Refactoring riêng, giúp quá trình Refactoring trở nên thuận tiện và hiệu quả hơn.

Sử dụng các công cụ Refactoring giúp xác định những vị trí cần cải tiến trong mã nguồn, đồng thời áp dụng các kỹ thuật Refactoring theo tiêu chuẩn mới nhất Điều này không chỉ giúp quá trình Refactoring diễn ra nhanh chóng mà còn đảm bảo tính chính xác và hiệu quả cao.

Các công cụ Refactoring được phân thành hai nhóm chính:

 Các công cụ Refactoring được tích hợp sẵn vào các IDEs do nhà phát triển IDEs cung cấp.

 Các công cụ Refactoring do bên thứ 3 phát triển (Plug-in)

Giới thiệu các công cụ Refactoring được tích hợp sẵn vào các IDEs

Hiện nay, nhiều IDEs được sử dụng cho các dự án với ngôn ngữ lập trình đa dạng Bài viết này sẽ giới thiệu một số công cụ Refactoring tích hợp sẵn trong các IDE phổ biến như IntelliJ IDEA, Visual Studio Code và Visual Studio.

5.2.1 Đối với IDEs Inteliji IDEA

1 Chọn phần code cần refactoring (có thể chọn các files, các thư mục trong dự án hoặc các đoạn lệnh, dòng lệnh trong IDE)

2 Nhấn phím tắt Ctrl + Alt + T để mở danh sách các chức năng Refactoring do nhà cung cấp viết sẵn.

Hình ảnh sau khi gọi chức năng Refactoring của IDE Inteliji IDEA

5.2.1.b Xem trước thay đổi sau khi Refactoring

1 Để xem thay đổi, bấm vào nút Preview trong cửa sổ Refactoring.

2 Trong khi xem trước những thay đổi sau khi Refactoring, bạn có thể xoá (sử dụng phím Delete) hoặc di chuyển (sử dụng tổ hợp phím Ctrl + X) những thành phần đang có vấn đề.

3 Sau khi xem xong những thay đổi, bạn kích vào Do Refactor để thực hiện Refactoring với những thay đổi như khi xem trước. 5.2.1.c Xử lí xung đột code khi Refactoring

Khi thực hiện Refactoring, có lúc sẽ xuất hiện một vài xung đột code Inteliji đã hỗ trợ phần xử lí xung đột khi Refactoring.

Cửa sổ xử lí xung đột khi Refactoring

1 Lựa chọn Continue để bỏ qua xung đột Code Refactoring sẽ ghi đè code cũ mặc dù sẽ có vấn đề ở đó.

2 Lựa chọn Show Conflics in View để xem các nơi code bị xung đột bằng công cụ Find Sau đó bạn có thể sửa lại những vùng đó cho phù hợp.

Cửa sổ xem các nới bị xung đột code bằng công cụ Find

3 Lựa chọn Cancel để huỷ bỏ Refactoring Code của bạn sẽ giữ nguyên và không có Refactoring xảy ra.

5.2.1.d Thiết lập cài đặt Refactoring

Bạn có thể sửa lại cách mà công cụ Refactoring trong IDE Inteliji cung cấp hoạt động.

5.2.2 Đối với IDE Visual Studio Code

In Visual Studio Code, there is a feature similar to IntelliJ's Refactoring called Code Actions This functionality assists with both Refactoring and Quick Fixes, allowing users to quickly resolve simple issues in their code.

Bạn có thể sử dụng chức năng Code Actions, bao gồm cả Refactoring, bằng cách nhấn tổ hợp phím Ctrl + hoặc nhấp vào biểu tượng bóng đèn gần vị trí cần Refactoring.

Code Actions trong VS Code

Select the code segment you wish to refactor Then, invoke the Refactoring function to view the available options, which include features such as Extract to Function and Extract Variable.

Để đổi tên biến, bạn chỉ cần chọn biến cần thay đổi, nhấn phím F2, nhập tên mới và nhấn Enter IDE sẽ tự động cập nhật tất cả các biến liên quan sang tên mới, bao gồm cả các file liên quan.

5.2.3 Đối với IDE Visual Studio

5.2.3.a Đổi tên biến, tên hàm

1 Chọn tên biến cần đổi

2 Chọn chức năng Quick Actions and Refactorings rồi chọn mục Change Signature Sau đó đổi tên mới rồi nhấn OK. Đổi tên biến 5.2.3.b Tách hàm

1 Chọn đoạn code cần tách hàm

2 Chọn chức năng Quick Actions and Refactorings rồi chọn mục Extract Method Sau đó đổi tên mới rồi nhấn OK.

Các Plug-in hay sử dụng trong cac IDE

Hiện nay, nhiều nhà phát triển đã tạo ra các plug-in hỗ trợ quá trình refactoring cho các IDE, giúp lập trình viên sử dụng dễ dàng hơn.

5.3.1 Một số Plug-in cho IDE Visual Studio Code

5.3.2 Một số Plug-in cho IDE Visual Studio

Nhược điểm của các công cụ Refactoring

 Đôi khi, các công cụ Refactoring thay đổi ngữ nghĩa của code không mong muốn.

 Đôi khi, các công cụ Refactoring thay đổi ngữ nghĩa của code không mong muốn.

 Cần phải bỏ ra thời gian để học cách sử dụng các công cụ mới.

 Một số công cụ hướng tới Refactoring theo một cách nào đó nhưng không phù hợp với hiện tại.

 Nhiều công cụ phải trả phí để dùng.

[1] https://www.jetbrains.com/help/idea/refactoring-source-code.html

[2] https://code.visualstudio.com/docs/editor/refactoring

[3] https://docs.microsoft.com/en-us/visualstudio/ide/refactoring-in-visual-studio?view=vs-2019

Ngày đăng: 15/10/2021, 22:32

HÌNH ẢNH LIÊN QUAN

Như hình trên, chương trình nguồn của dự án tồn tại rất nhiều lỗi (Bad Smells) mà con người không thể tìm ra hết để xử lí - Công nghệ phần mềm Tìm hiểu về Refactoring
h ư hình trên, chương trình nguồn của dự án tồn tại rất nhiều lỗi (Bad Smells) mà con người không thể tìm ra hết để xử lí (Trang 23)
Hình ảnh sau khi gọi chức năng Refactoring của IDE Inteliji IDEA - Công nghệ phần mềm Tìm hiểu về Refactoring
nh ảnh sau khi gọi chức năng Refactoring của IDE Inteliji IDEA (Trang 24)

TỪ KHÓA LIÊN QUAN

w