XÂY DỰNG BỘ DỮ LIỆU MÃ XẤU
2.1. Giới thiệu các bộ dữ liệu hiện tại
Do áp lực về thời gian, thiếu kỹ năng hoặc kinh nghiệm [29], các nhà phát triển không phải lúc nào cũng sẵn sàng kiểm sốt hồn tồn mức độ phức tạp của hệ thống để tìm ra giải pháp tối ưu trước khi áp dụng các sửa đổi[30].Do đó, các hoạt động bảo trì và phát triển thường được thực hiện bằng cách sử dụng các giải pháp không tối ưu, và các giải pháp này có khả năng làm sai lệch thiết kế ban đầu của hệ thống. Mã xấu [31] tức là các triệu chứng về sự hiện diện của thiết kế hoặc triển khai dưới mức tối ưu mà các nhà phát triển áp dụng trên hệ thống phần mềm. Những hành động này cịn được gọi là thực hành khơng tốt, phản mẫu, dị thường hoặc lỗi thiết kế. Về tác động của mã xấu, nhiều nghiên cứu trước đây đã chỉ ra rằng mã xấu không chỉ ảnh hưởng đến khả năng chịu đựng kém của hệ thống bởi các nhà phát triển trong các tác vụ hiểu và bảo trì mà cịn làm cho các lớp bị ảnh hưởng thay đổi nhiều hơn và dễ bị lỗi [32, 33, 34]. Do đó, mã xấu là một trong những thách thức quan trọng đối với các nhà phát triển về nỗ lực bảo trì hệ thống và chi phí [35, 36]. Kể từ khi Fowler phân loại và đặt tên cho các mã xấu phổ biến [31], nhiều nhà nghiên cứu đã đề xuất các nghiên cứu khác nhau để phát hiện mã xấu. Dựa trên phương pháp phát hiện của họ, các nghiên cứu có thể nhóm thành các phương pháp tiếp cận khác nhau như Phương pháp tiếp cận thủ công [37, 38], Phương pháp tiếp cận dựa trên số liệu [39, 40, 41], Phương pháp dựa trên hình ảnh hóa [42, 43], Phương pháp tiếp cận dựa trên triệu chứng [44, 45, 46], Phương pháp tiếp cận cơ sở hợp tác [47], Phương pháp xác suất [48, 49] và Phương pháp cơ sở tìm kiếm [50, 51, 52, 53, 54, 55, 56]. Nhìn chung, hầu hết các nghiên cứu đều có mục tiêu và cách tiếp cận riêng để mỗi nghiên cứu có bộ dữ liệu cụ thể phù hợp với các phương pháp, thuật toán phát hiện mã xấu. Bộ dữ liệu là tập hợp các thuộc tính của hệ thống phần mềm như số liệu mã nguồn, loại, số lượng mã xấu và các thuộc tính dữ liệu khác cần thiết cho nghiên cứu được sử dụng. Sau đây là một số nghiên cứu cung cấp tập dữ liệu đính kèm với các bài báo đã xuất bản của họ:
- Năm 2009, Khomh và các cộng sự đã đề xuất một phương pháp phát hiện God Class dựa trên thuật toán Bayesian Belief Network. Tập dữ liệu của nghiên cứu này được xây dựng dựa trên hai nguồn mở Java. Nó có gần 800 trường hợp số liệu nguồn và mã xấu của nó đã được xác thực theo cách thủ cơng [48].Vào năm 2011, tập dữ liệu này đã được sử dụng lại, cải tiến và bổ sung một số thuộc tính mới để phục vụ cho nghiên cứu khác của họ nhằm phát hiện ba loại God Class, Functional Decomposition và Spaghetti Code [49].
- Năm 2015, Arcelli Fontana F. và cộng sự đã tạo ra một mơ hình học máy để phát hiện bốn mã xấu God Class, Data Class, Long Method và Feature Envy. Bộ dữ liệu của nghiên cứu này có hơn 1600 phiên bản số liệu nguồn đã được trích xuất từ 74 kho lưu trữ mã nguồn mở Java. Các mã xấu trong tập dữ liệu đã được xác thực theo cách thủ công [54].
- Năm 2017, Ian Shoenberger và cộng sự đề xuất tự động hóa các quy tắc dẫn xuất để phát hiện mã xấu trong mã nguồn Javascript. Tập dữ liệu của nghiên cứu này chứa các số liệu nguồn của 100 kho Javascript được trích xuất bằng các cơng cụ InCode, PMD. Họ dựa vào tập dữ liệu này để đào tạo các quy tắc phát hiện bằng cách sử dụng Genetic Programming và tìm ngưỡng số liệu tốt nhất để tạo ra các quy tắc [57].
- Năm 2019, Pecorelli và cộng sự đã tạo một tập dữ liệu có 8534 trường hợp từ mười ba hệ thống nguồn mở. Dựa trên tập dữ liệu này, họ đã so sánh việc phát hiện 4 mã xấu giữa hai kỹ thuật là học máy và heuristic [58].
- Năm 2020, Madeyski và cộng sự đã cung cấp một tập dữ liệu chứa khoảng 15 nghìn mẫu số liệu nguồn với bốn mã xấu của 792 hệ thống dự án java. Họ hy vọng rằng tập dữ liệu này sẽ hỗ trợ các nhà nghiên cứu tìm kiếm mã xấu trong các dự án java [59].
Nói chung, các bộ dữ liệu trên là vừa đủ cho mục đích của các nhà nghiên cứu và việc phát hiện tập trung vào bốn mã xấu là God Class, Data Class, Long Method và Feature Envy Bảng 2.1. Mặt khác, quan trọng hơn, mỗi nghiên cứu có tập dữ liệu riêng nên nó dẫn đến một số nhược điểm dưới đây:
- Giá trị của các cá thể tập dữ liệu không nhất quán giữa các tập dữ liệu mà phụ thuộc vào các công cụ hoặc đánh giá chủ quan của con người
- Không thể so sánh hai mơ hình với nhau vì sự khác biệt trong tập dữ liệu của chúng.
Do đó, cần sử dụng một tập dữ liệu chung cho các nghiên cứu khác nhau và tập dữ liệu cần có một số đặc điểm sau. Đầu tiên, nó phải có một số lượng lớn các phiên bản, đã được trích xuất từ một số lượng lớn các kho lưu trữ bằng cách sử dụng một cơng cụ đáng tin cậy. Thứ hai, nó phải có đủ thuộc tính (số liệu nguồn, mã xấu,. Vv.) để phục vụ các mục đích khác nhau. Cuối cùng, nó phải được cơng bố rộng rãi để cộng đồng nghiên cứu xác nhận độ tin cậy của nó.
Bảng 2.1. Bảng tổng hợp các bộ dữ liệu về mã xấu từ năm 2009
Tác giả Mã xấu Bộ dữ liệu
Khomh và cộng sự [48] God Class, Functional Decomposition, Spaghetti Code
2 open-sources
Arcelli Fontana và cộng sự [54]
Long Method, Feature Envy, God Class, and Data Class
74 projects
Pecorelli và cộng sự [58] God Class, Spaghetti Code, Class Data Should be Private, Long Method, Complex Class
13 open-sources
Madeyski và cộng sự [59] God Class, Long Method, Data Class, Feature Envy
792 projects
2.2. Các công cụ đo
Hiện nay, có rất nhiều cơng cụ được ra đời để đánh giá chất lượng của bản mã, đo lường mức độ của bản mã. Trong phần này, tôi sẽ giới thiệu ba công cụ mà tôi thử nghiệm sâu như inFusion, PMD, iPlasma. Một số hạn chế của các công cụ được thảo luận ở cuối chương này.
2.2.1. PMD
PMD [60] là một công cụ mã nguồn mở được sử dụng để phát hiện mã xấu trong mã Java. PMD là một bộ phân tích mã nguồn cho phép tìm thấy các lỗi lập trình phổ biến như biến khơng sử dụng, khối bắt trống, tạo đối tượng khơng cần thiết, v.v. Nó hỗ trợ Java, JavaScript, Salesforce.com Apex và Visualforce, PLSQL, Apache Velocity, XML, XSL.
Ngồi ra, nó bao gồm CPD, công cụ phát hiện sao chép-dán. CPD tìm mã trùng lặp trong Java, C, C ++, C #, Groovy, PHP, Ruby, Fortran, JavaScript, PLSQL, Apache Velocity, Scala, Objective C, Matlab, Python, Go, Swift và Salesforce.com Apex và Visualforce.Các kỹ thuật phát hiện dựa trên các chỉ số dựa trên chiến lược
phát hiện được xác định bởi Lanza và Marinescu [61]. Vì PMD là một cơng cụ mã nguồn mở, nên người dùng sẽ sửa đổi các giá trị ngưỡng cho các chỉ số được khai thác. Ngoài ra, việc cải thiện các quy tắc về mã xấu cũng có thể thực hiện được đối với PMD.
2.2.2. iPlasma
iPlasma [62] là một công cụ giúp các nhà phát triển phân tích chất lượng mã nguồn của các ngơn ngữ như C++, Java. Cơng cụ này có thể phát hiện mã xấu dựa trên chỉ số và ngưỡng. Sự đa dạng của các mã xấu là một lợi thế lớn của iPlasma. Đặc biệt, kiểu lớp và các phương thức được tôi quan tâm trong bài viết này. Một ưu điểm khác của iPlasma là nó có thể phân tích các dự án quy mơ lớn với kích thước hàng triệu dịng mã (ví dụ: Eclipse và Mozilla). Giống như PMD, iPlasma cung cấp cho người dùng một giao diện để thay đổi các quy tắc và ngưỡng phù hợp với từng định nghĩa của mã xấu nếu người dùng muốn. Ưu điểm lớn nhất và khác biệt nhất của iPlasma là nó có một số lượng lớn các chỉ số được xác định trước, điều này làm cho tập dữ liệu rất phù hợp cho các vấn đề dự đoán mã xấu bằng cách sử dụng máy học.
2.2.3. inFusion
inFusion [6] [63] là một công cụ được Intooitus phát triển nhằm phát hiện một số lượng lớn các mã xấu và báo cáo chúng cùng với một giá trị mức độ nghiêm trọng. InFusion có nguồn gốc từ iPlasma, nó được mở rộng với nhiều chức năng hơn và được thương mại hóa. Đây là một cơng cụ dành cho Java, C và C++ phát hiện hơn 20 sai sót thiết kế và mã xấu dựa trên định nghĩa của Fowler [64] Các kỹ thuật phát hiện mã xấu dựa trên chiến lược của Lanza và Marinescu [61]. Khả năng cung cấp điểm số mức độ nghiêm trọng là một lợi thế cụ thể của công cụ inFusion.
2.3. Hạn chế các công cụ thử nghiệm
Một số hạn chế đã được xác định trong quá trình nghiên cứu và sử dụng các công cụ trên. Các công cụ được đề cập ở trên được tạo ra để phân tích chất lượng của phần mềm, có nghĩa là phát hiện mã xấu không phải là mục tiêu chính của các cơng cụ. Các cơng cụ chủ yếu được sử dụng cho một số ngơn ngữ lập trình, chẳng hạn như Java, C++. Đối với PMD, giới hạn của các chỉ số được lập trình sẵn khiến người dùng mất nhiều thời gian để thêm các chỉ số khác. Tuy nhiên, việc thêm các thước đo khác không hề đơn giản nếu người dùng không thể sử dụng ngơn ngữ Java để lập trình. iPlasma đã khắc phục được hạn chế này của PMD nhưng lại để lại một hạn chế mới. iPlasma sử dụng một giao diện trơng rất tiện lợi cho người dùng nhưng nó khá cồng kềnh.
2.4. Đặc tả bộ dữ liệu
2.4.1. Thu thập mã nguồn
Source code là một phần quan trọng trong việc tạo ra bộ dữ liệu. Nó là đầu vào của tồn bộ q trình tạo nên bộ dữ liệu về code smell. Vì thế, việc thu thập source code phải đảm bảo các tiêu chí như: số lượng đủ lớn, source code đến từ những tổ chức lớn, tin cậy, có độ uy tín cao. Sau q trình thu thập, 524 source code links được tơi đính kèm trong file sau đây Source code links. Đây là các source code JAVA đã
được công bố từ các nguồn uy tín như apache, google, eclipse, oracle...
2.4.2. Sử dụng công cụ iPlasma
Công cụ iPlasma version 6 được tôi sử dụng trong quá trình tạo ra bộ dữ liệu về mã xấu iPlasma tool. Tất cả source code được thu thập trong phần trên sẽ được áp
dụng vào công cụ iPlasma. Video sau đây là hướng dẫn cách sử dụng công cụ iPlasma được tôi thực hiện iPlasma tutorial video. Trong nội dung nghiên cứu này, tôi chỉ tập trung về hai nhóm mã xấu chính là method và class. Đầu ra của việc này là một tập hợp các tệp tin csv, trong đó bao gồm các độ đo của mã nguồn đối với từng loại mã xấu. Việc phân tích và xử lý các tệp tin này sẽ được tôi đề cập trong phần sau.
Hình 2.1. Áp dụng iPlasma cho mẫu code
2.4.3. Đặc tả bộ dữ liệu
Như đã mô tả ở phần trên, trong phạm vi của nghiên cứu này, hai nhóm mã xấu chính là method và class được chung tơi tập trung vào. Có tổng cộng 13 loại mã xấu được tơi thực hiện, trong đó có 7 loại mã xấu thuộc nhóm class và 6 loại mã xấu thuộc nhóm method. Có trên 30 độ đo ứng với mỗi nhóm được cơng cụ iPlasma cung cấp. Tuy nhiên, không phải tất cả độ đo đều được tôi sử dụng. Một vài độ đo không liên quan đến loại mã xấu đó sẽ được tơi loại bỏ khỏi bộ dữ liệu. Câu hỏi đặt ra ở đây là
làm cách nào xác định được độ đo nào kém liên quan đến loại mã xấu? Hệ số tương quan Pearson (Pearson Correlation) được tôi sư dụng để xác định các độ đo có độ tương quan thấp và loại bỏ chúng. Độ tương quan (Correlation) là thước đo mối quan hệ tuyến tính giữa hai biến và khơng phụ thuộc vào các đơn vị đo lường của hai biến này. Độ tương quan được đo bằng hệ số tương quan, trong đó Hệ số tương quan momen sản phẩm Pearson (Pearson product-moment correlation coefficient – PPMCC) hay Hệ số tương quan Pearson là thước đo quen thuộc nhất về sự phụ thuộc giữa hai biến.
Hệ số tương quan Pearson của 2 biến ngẫu nhiên X,Y, ký hiệu ‰x y , được tính bằng cách chia hiệp phương sai cho tích của độ lệch chuẩn. Độ lệch chuẩn đo lường độ biến thiên tuyệt đối của tập dữ liệu, do đó khi chia các giá trị hiệp phương sai cho độ lệch chuẩn, nó sẽ chia tỷ lệ giá trị xuống một phạm vi giới hạn từ –1 đến +1. Đây chính là phạm vi của các giá trị tương quan.
(5)
(6)
Trong đó:
cov(X,Y) là hiệp phương sai của 2 biến ngẫu nhiên X,Y σx σy là độ lệch chuẩn của tổng thể
(a) Tương quan thuận (b) Tương quan nghịch
(c) Khơng có tương quan
(d) Khơng có quan hệ tuyến tính và
tương quan tuyến tính
Hình 2.1 cho biết 4 trường hợp xảy ra khi tính hệ số tương quan Pearson: - Hình 2.1.a: 2 biến X và Y có quan hệ tuyến tính thuận với nhau, ρxy > 0 thì X tăng, Y tăng.
- Hình 2.1.b: 2 biến X và Y có quan hệ tuyến tính nghịch với nhau, ρxy < 0 thì X tăng, Y giảm và ngược lại.
- Hình 2.1.c và Hình 2.1.d: Khi ρxy = 0 thì 2 biến X và Y có thể khơng có mối quan hệ với nhau hoặc có mối quan hệ rõ ràng giữa các biến nhưng mối quan hệ này khơng tuyến tính và cũng khơng có tương quan.
Việc xác định các độ đo có độ tương quan kém và loại bỏ chúng làm cho bộ dữ liệu về mã xấu trở nên cô đặc hơn, mang lại thơng tin có ý nghĩa hơn và loại bỏ các thơng tin nhiễu. Thơng qua đó, kết quả phát hiện mã xấu bằng học máy cũng được kỳ vọng hơn. Bảng 2.2 dưới đây thống kê tổng quát số lượng mã xấu từng loại kèm với danh sách các độ đo của chúng.
Bảng 2.2. Bảng tổng hợp mã xấu và độ đo
Loại Mã xấu Độ đo
Class Brain Class DIT, NOPA, PNAS, WOC, NSPECM, CC, NOAM, CM, NAS, NTempF, NProtM, NOA, FDP, ATFD, NOM, CBO, AMW, FANOUT, WMC
Data Class WMC, CM, BUR, PNAS, CC, NOM, NOA, NTempF, NOPA, NOAM
Futile Abstract Pipeline CC, AMW, NOA, CM, FANOUT, NOAM, CBO, WOC, WMC, NAbsM, NSPECM, NOM, DIT, NProtM, NAS, HIT, PNAS
Futile Hierarchy NOPA, NAS, WOC, BUR, CC, CM, NAbsM, NOA, NOAM, NTempF, AMW, FDP, ATFD, NOM, FANOUT, CBO, WMC, HIT,NProtM
God Class DIT, NOPA, HIT, WOC, NSPECM, PNAS, NOA, CC, NAS, NOAM, CM, AMW, NTempF, NProtM, NOM, WMC, ATFD, FDP, FANOUT, CBO
Loại Mã xấu Độ đo
Model Class HIT, NOPA, NSPECM, CM, NAS, CC, NAbsM, NOA, NProtM,ATFD, WMC, NOAM, NTempF, FANOUT, FDP, CBO, NOM, DIT, PNAS, AMW, TCC, WOC
Schizofrenic Class NSPECM, NAbsM, NOPA, NAS, CC,
NOAM, CM, WOC, AMW,NProtM, NOA, NTempF, ATFD, FANOUT, FDP, WMC, NOM, CBO
Method Brain Method CC, CM, FANIN, NOP, CDISP, FDP, CINT, ATFD, FANOUT, NOAV, MAXNESTING, NOLV, LOC, CYCLO
Extensive Coupling FANIN, NOP, CDISP, MAXNESTING,
FANOUT, NOAV, LOC, CYCLO, ATFD, NOLV, FDP, CINT
Feature Envy NOP, CYCLO, CDISP,
MAXNESTING, NOLV, LOC, NOAV, FANOUT, CINT, FDP, ATFD
Intensive Coupling CC, CM, FANIN, NOP, CDISP, NOLV, NOAV, FDP, CYCLO, MAXNESTING,
LOC, FANOUT, ATFD, CINT
Shortcircuiting Method NOLV, ATFD, FDP, FANOUT, LOC, CINT, NOAV, CDISP, CYCLO, MAXNESTING, FANIN, CM, CC
2.5. Định nghĩa các loại mã xấu trong bộ dữliệu
2.5.1. Brain Method
Là một phương thức có xu hướng tập trung hóa chức năng của một lớp.Đặc điểm của phương pháp này là kích thước q lớn, khó sử dụng lại, khó hiểu, dễ bị lỗi và khó bảo trì.
2.5.2. Brain Class
Là một lớp có xu hướng tập trung vào nhiều chức năng chính của hệ thống. Nó thường ở dạng chứa một số Brain Methods. Các đặc điểm của Brain Class tương tự như God Class, nhưng nó khơng vi phạm quy tắc đóng gói, do đó nó hầu như khơng truy cập vào dữ liệu của các lớp khác.
2.5.3. Data Class
Được định nghĩa là lớp trong đó rất nhiều dữ liệu được lưu trữ nhưng không