Code decay, software erosion and software entropy
Gnicie oprogramowania, znane również jako gnicie kodu, erozja oprogramowania, rozpad oprogramowania lub entropia oprogramowania, to (powolne) pogarszanie się sprawności i wydajności oprogramowania np. przejawiające się w dłuższym czasie reakcji (tzw. „zamulanie”).
Gnicie oprogramowania występuje nawet jeśli „nic się nie zmieniło” w samym oprogramowaniu. Może być zatem wywołane zmianami, które zachodzą w cyfrowym ekosystemie, w którym to oprogramowanie działa.
Software aging: starzenie się oprogramowania
W trakcie swojego życia systemy oprogramowania są poddawane konserwacji, która ma na celu np. wprowadzenie nowych funkcji lub uczynienie oprogramowania konkurencyjnym w stosunku do alternatywnych produktów, usunięcie usterek lub dostosowanie oprogramowania do nowych środowisk i architektur. Ze względu na presję czasu, ograniczone zasoby i brak zdyscyplinowania procesu konserwacji, działania te mają tendencję do niszczenia struktury systemu oprogramowania, zwiększając złożoność kodu źródłowego i utrudniając zrozumienie i utrzymanie systemu w przyszłości [Canfora i in. 2014]. Parnas [1994] nazwał to zjawisko „starzeniem się oprogramowania” (software aging): podobnie jak starzenie się ludzi, starzenie się oprogramowania jest nieuniknione, ale podobnie jak w przypadku starzenia się ludzi, istnieją rzeczy, które można zrobić, aby spowolnić proces starzenia się, a czasem nawet odwrócić jego skutki. Nie można zapobiec starzeniu się oprogramowania, ale można zrozumieć jego przyczyny, podjąć kroki w celu ograniczenia jego skutków, cofnąć niektóre szkody i przygotować się na dzień, w którym oprogramowanie nie będzie już sprawne.
Na systemy oprogramowania wpływa zjawisko degradacji: pogarsza się niezawodność, struktura systemu ulega uszkodzeniu, następuje utrata spójności dokumentacji, zmniejsza się łatwość konserwacji. Taka degradacja musi zostać wykryta, gdy tylko pojawi się w systemie oprogramowania, w przeciwnym razie system zacznie się starzeć [Bianchi i in. 2001].
Starzenie się oprogramowania jest związane ze wzrostem złożoności i dezorganizacji kodu.
Ewolucja systemu oprogramowania może charakteryzować się różnego rodzaju zmianami, z których niektóre zwiększają złożoność oprogramowania, niektóre zmniejszają ją, a niektóre mają na nią ograniczony wpływ. Prawo Lehmana i Belady’ego [1985], oprócz oświadczenia o rosnącej złożoności systemu oprogramowania wskazuje, że mogą istnieć środki zaradcze w celu spowolnienia lub złagodzenia skutków starzenia się oprogramowania. Reengineering, redocumentation i refactoring to przykłady działań mających na celu złagodzenie, a nawet cofnięcie skutków starzenia się oprogramowania.
Restructuring vs Refactoring
Systemy oprogramowania ciągle się zmieniają z różnych powodów, takich jak dodawanie nowych funkcji, naprawianie błędów, restrukturyzacja lub refaktoryzacja. Zmiany mogą zwiększyć złożoność i dezorganizację kodu źródłowego lub zmniejszyć skalę tych zjawisk.
Zgodnie z taksonomią Chikofsky’ego i Crossa [1990] restrukturyzację (restructuring) definiuje się jako „transformację z jednej formy reprezentacji do drugiej, na tym samym względnym poziomie abstrakcji, przy jednoczesnym zachowaniu zewnętrznych zachowań systemu (funkcjonalności i semantyki). Często pojawia się transformacja restrukturyzacyjna, np. zmiana kodu w celu ulepszenia jego struktury w tradycyjnie rozumianym projektowaniu strukturalnym.
Termin refaktoryzacja (refactoring) został ukuty przez Williama Opdyke [1992]. Refaktoryzacja jest zasadniczo zorientowanym obiektowo wariantem restrukturyzacji: jest to proces przekształcenia (zorientowanego obiektowo) systemu oprogramowania w taki sposób, że nie zmienia on zewnętrznego zachowania kodu, ale poprawia jego wewnętrzną strukturę. Kluczową ideą jest tutaj redystrybucja klas, zmiennych i metod w całej hierarchii klas, aby ułatwić przyszłe adaptacje i rozszerzenia [Mens i Tourwé 2004]. Parnas [1994] użył terminu „geriatria oprogramowania”, w kontekście jego starzenia się, i przyrównał refaktoryzację do poważnej operacji medycznej.
W kontekście ewolucji oprogramowania, restrukturyzacja i refaktoryzacja są stosowane w celu poprawy jakości oprogramowania, np. jego rozszerzalności, modułowości, możliwości ponownego użycia, złożoności, łatwości konserwacji lub wydajności. Refaktoryzacja i restrukturyzacja są również stosowane w reengineeringu, czyli takiej modyfikacji oprogramowania, aby odtworzyć je i wdrożyć w nowej formie. W tym kontekście konieczna jest restrukturyzacja starego lub uszkodzonego kodu w bardziej modułową lub strukturalną formę, migracja kodu do innego języka programowania lub nawet zmiana paradygmatu [Mens i Tourwé 2004].
Software entropy
Systemy oprogramowania ewoluują z różnych powodów. Według badań zmiany wprowadzane w oprogramowaniu mają tendencję do zwiększania jego złożoności i sprzyjają pogorszeniu jego struktury, co jest znane jako „starzenie się” oprogramowania [Parnas 1994]. Wielu badaczy analizowało to zjawisko stosując entropię Shannona [1948], w szczególności do modelowania złożoności systemu oprogramowania, a dokładniej charakteryzowania entropii zmian oprogramowania [Hassan 2009].
Czym jest entropia oprogramowania [Canfora i in. 2014], a czym jest entropia zmiany oprogramowania [Hassan 2009]? Entropia oprogramowania jest związana z entropią Shannona, tj. miarą niepewności związanej ze zmienną losową, która kwantyfikuje informacje zawarte w komunikacie wytworzonym przez emiter danych [Shannon 1948]. Entropię Shannona można interpretować jako liczbę bitów potrzebną do jednoznacznej identyfikacji gnicia danych: im wyższa entropia, tym większa niepewność w określeniu gnicia danych. W podstawowym modelu zmiany kodu wg Hassana [2009] przyjęto, że system oprogramowania jest emiterem danych, a modyfikacje plików źródłowych to dane generowane przez emiter [Canfora i in. 2014].
Entropia systemu oprogramowania to klasa wskaźników służących do oceny stopnia zaburzeń w strukturze systemu oprogramowania. Entropia obejmuje wszystkie elementy systemu oprogramowania na różnych poziomach abstrakcji, a także relacje między nimi w zakresie identyfikowalności [Bianchi i in. 2001].
Code decay
Zjawisko stopniowego wzrostu złożoności oprogramowania z powodu (niezamierzonej) interakcji między modułami, które jest trudne do zatrzymania, nazwano także „gniciem kodu” (code decay) i degeneracją architektury oprogramowania (architectural degeneration) [Eick i in. 2001, Hochstein i Lindvall 2003]. Code decay odnosi się do naruszeń architektury, zasad projektowania i standardów kodowania, które utrudniają modyfikację oprogramowania [Bandi i in. 2013].
Software decay to pogorszenie się wewnętrznej struktury oprogramowania. Rozpad (gnicie) wzoru projektowego (design pattern decay) to pogorszenie integralności strukturalnej realizacji wzoru projektowego. Aby gnicie oprogramowania mogło nastąpić, realizacja wzoru musi podlegać negatywnym zmianom (pogorszeniu), poprzez kolejne wydania i ewolucję [Izurieta i Bieman 2007]. Rozpad kodu jest procesem stopniowym, który negatywnie wpływa na jakość systemu oprogramowania. Programiści potrzebują sprawdzonych technik pomiarowych, aby ocenić, czy ich systemy uległy rozkładowi [Bandi i in. 2013].
Stopniowe gnicie oprogramowania jest konsekwencją ewolucji oprogramowania. Rozpad jest najbardziej widoczny, gdy czas wymagany do wprowadzenia zmian w systemie oprogramowania wzrasta, niezależnie od ilości dostępnych zasobów [Izurieta i Bieman 2007].
Eick i jego zespół projektowy [2001] zbadali nasilenie zjawiska code decay w przypadku oprogramowania telefonów i wykazali, że system zepsuł się z powodu kolejnych modyfikacji. Godfrey i Lee [2000] przeanalizowali kod przeglądarki Mozilla, wyodrębniając modele architektoniczne przy użyciu narzędzi inżynierii odwrotnej. Przeglądarka Mozilla (M9) składała się z ponad 2 milionów wierszy kodu źródłowego w ponad siedmiu tysiącach plików nagłówkowych i implementacyjnych (C i C ++). Po dokładnej ocenie modeli architektury, Godfrey i Lee doszli do wniosku, że albo architektura Mozilli uległa znacznemu rozpadowi w stosunkowo krótkim czasie użytkowania, albo nie została starannie zaprojektowana.
Badania pokazały, że starzenie się oprogramowania jest zjawiskiem typowym dla dużych projektów z dużą liczbą podmiotów odpowiedzialnych i ujawniły, że nie wszystkie zmiany wpływają na starzenie się oprogramowania w ten sam sposób. Potwierdziły również, że starzeniu można przeciwdziałać za pomocą określonych działań, takich jak refaktoryzacja [Canfora i in. 2014]. Ponadto Canfora i współautorzy [2014] postawiali hipotezę, że w środowisku korporacyjnym, w którym istnieje wspólna kultura korporacyjna i egzekwowane są wytyczne i standardy dotyczące projektowania i kodowania można złagodzić negatywne skutki wynikające z faktu, że wielu programistów pracuje nad jednym projektem.
Źródła
- Bandi, A., Williams, B.J., Allen, E.B. (2013). Empirical evidence of code decay: A systematic mapping study. In 20th Working Conference on Reverse Engineering (pp. 341-350). IEEE. https://doi.org/10.1109/WCRE.2013.6671309
- Bianchi, A., Caivano, D., Lanubile, F., Visaggio, G. (2001). Evaluating software degradation through entropy. In Proceedings Seventh International Software Metrics Symposium (pp. 210-219). IEEE. https://doi.org/10.1109/METRIC.2001.915530
- Canfora, G., Cerulo, L., Cimitile, M., Di Penta, M. (2014). How changes affect software entropy: an empirical study. Empirical Software Engineering, 19(1), 1-38. https://doi.org/10.1007/s10664-012-9214-z
- Chikofsky, E.J., Cross, J.H. (1990). Reverse engineering and design recovery: A taxonomy. IEEE Software, 7(1), 13-17. https://doi.org/10.1109/52.43044
- Eick, S. G., Graves, T.L., Karr, A.F., Marron, J., Mockus, A. (2001). Does code decay? Assessing the evidence from change management data. IEEE Transactions on Software Engineering, 27(1), 1-12. https://doi.org/10.1109/32.895984
- Godfrey, M.W., Lee, E.H.S. (2000). Secrets from the monster: Extracting Mozilla’s software architecture. In 2nd International Symposium on Constructing Software Engineering Tools.
- Hochstein, L., Lindvall, M. (2003). Diagnosing architectural degeneration. In 28th Annual NASA Goddard Software Engineering Workshop. https://doi.org/10.1109/SEW.2003.1270736
- Izurieta, C., Bieman, J.M. (2007). How software designs decay: A pilot study of pattern evolution. In First International Symposium on Empirical Software Engineering and Measurement (pp. 449-451). IEEE. https://doi.org/10.1109/ESEM.2007.55
- Lehman. M.M., Belady, L.A. (1985). Program evolution: processes of software change. Academic Press Professional, London.
- Mens, T., Tourwé, T. (2004). A survey of software refactoring. IEEE Transactions on software engineering, 30(2), 126-139. https://doi.org/10.1109/TSE.2004.1265817
- Opdyke, W.F. (1992). Refactoring: A Program Restructuring Aid in Designing Object-Oriented Application Frameworks, Ph.D. thesis. University of Illinois at Urbana-Champaign.
- Parnas, D.L. (1994). Software aging. In Proceedings of 16th International Conference on Software Engineering (pp. 279-287). IEEE. https://doi.org/10.1109/ICSE.1994.296790
- Shannon, C.E. (1948). A mathematical theory of communication. Bell System Technical Journal, 27(3), 379-423. https://doi.org/10.1002/j.1538-7305.1948.tb01338.x