Günümüzde donanım hata oranları ve geliştirme maliyetleri azalırken, yazılım geliştirme ve bakım maliyetleri giderek artmaktadır. Birçok yazılım projesi, zaman ve bütçe kısıtlarını aşarak başarısızlıkla sonuçlanmaktadır. Araştırmalara göre yazılım geliştirme maliyetinin büyük çoğunluğunu ise yazılım bakım faaliyetleri oluşturmaktadır. Pratikte, herhangi bir yazılım sistemi hakkında bilgi edinmek yazılım bakımındaki en önemli gereksinimdir. Ancak çoğu zaman, yazılım tasarım dokümanları, güncelliğini yitirmiş, kısmen ya da tamamen eksik durumdadır. Bununla beraber yazılımın zamanla evrilmesiyle mimari tasarımı da zamanla değişmekte ve başlangıçta bulunduğu şeklinden tamamen farklı bir hale dönüşebilmektedir. Tüm bunlar yazılım sistemi anlamayı daha da zor ve maliyetli bir iş haline getirmektedir. Bu nedenle, yazılım sistemlerini daha kolay ve daha hızlı anlamayı sağlayacak yöntem, algoritma ve otomatik sonuç üreten araçlara gereksinim duyulmaktadır.
Yazılım geliştirme tecrübeleri, geride bıraktığımız yıllar içinde farklı geliştirme metodolojilerinin ortaya çıkmasına neden olmuştur. Her metodoloji geçişinde daha büyük ve daha karmaşık yazılımlara çözüm aranmaya çalışılmıştır. Karmaşıklık zamanla artarken, yazılım tasarımında daha geniş tanecikli yapılar kullanılarak karmaşık daha iyi yönetilmeye çalışılmıştır. Bu nedenle prosedürel dillerdeki fonksiyonun yanına, nesneye dayalı sistemlerde sınıf, sınıfın yanına da bileşen ve servis kavramları getirilmiştir. Yazılım sistemin mimarisi, yazılımın büyük parçalı yapılarından meydana gelir, sistemin bileşenlerini ve üst seviyede bu bileşenlerin etkileşimini tanımlar. Yazılım modülleri, davranışlarına ve verilerine bir arayüz üzerinden kontrollü erişim sağlayarak gerçeklemelerini saklarlar.
Yazılım mimarları ve geliştiriciler modüler, yeniden kullanılabilir yazılımlar üretmek için nesneye dayalı tasarım prensiplerine başvururlar. Bu nedenle nesneye dayalı sistemlerde modül adı verilen, belirli bir servise özel yazılım sınıf grupları ortaya çıkar. Bazı durumlarda yazılımın uygulama alanına göre, gerçek dünyada ilgili işler yapan nesneler grup oluşturduğu için, bunların yazılımdaki yansımaları da yazılım sınıf gruplarını oluşturabilir. Tasarım kalıplarının kullanılması programlama açısından, bu modüllerin daha esnek ve tekrar kullanılabilir olmasına yardımcı olur. Yazılımlardaki bu modülleri bulmak, yazılımı daha iyi anlaşılmasında, daha etkin bir şekilde yazılım mimarisini ortaya çıkarılmasında, servis adaylarının belirlenerek var olan sistemlerin servis odaklı mimariye geçirilmesinde ve bu servislerin bulut tabanlı platformlara ya da dağıtılmış sistemlere taşınmasında kritik önem taşımaktadır.
Bu tez çalışmasında nesneye dayalı sistemlerdeki servisleri belirlemek için özgün bir otomatik modül bulma yaklaşımı (LBME) sunulmuştur. Bu yaklaşım, statik analizlerle çıkarılan yapısal bağımlılıkları kullanan ve nesneye dayalı tasarım mimarilerinde rastlanan tasarım kalıpları ile tasarım prensiplerinden faydalanan,
xviii
öğrenmeye dayalı bir modül bulma yaklaşımdır. Önerilen yaklaşımda ilk olarak yazılım sistemi için düğümlerin sınıfları, ayrıtların ise sınıflar arası ilişkileri temsil ettiği ağırlıklı ve yönlü bir çizge oluşturulmaktadır. Ardından modülleri belirlemek için bu çizge üzerinde ağırlıklı kümeleme algoritmaları uygulanmaktadır. Kullanılan kümeleme algoritmaları nesneye dayalı sistemlerin çizge karakteristikleri göz önünde bulundurularak seçilmiştir. Çizge üzerindeki ayrıtların ağırlığı, ayrıtların modül içinde ya da modül dışında olma olasılıklarına göre belirlenmektedir. Bu konumsal olasılıkları mümkün olduğu kadar doğru şekilde belirmek için makine öğrenmesi tabanlı sınıflandırma sistemi kullanılmıştır ve bu sistem gerçek dünyadan nesneye dayalı referans bir sistem ile eğitilmiştir.
Bu bağlamda yazılımın analizinin yapılabildiği, otomatik modül bulma aracı geliştirilmiş ve sunulan özgün yaklaşım, çeşitli açık kaynaklı ve endüstriyel projeler üzerinde değerlendirilmiştir. Deneysel sonuçlar göstermiştir ki, sunulan yeni yaklaşım nesneye dayalı sistemler için gerçeğe çok yakın sonuçlar üretmekte ve literatürde bulunan mevcut metotlardan daha iyi başarım göstermektedir.
|
Studies show that up to 75 percent of the total development cost is spent on maintenance activities through the full software development lifecycle. In practice, acquiring knowledge about a software system is the most crucial need in software maintenance. In most cases, documentation of software design is outdated, incomplete or absent, which make software systems difficult to understand. Therefore, automated tools and support of algorithms are required to understand software systems more quickly and easily.
Developers apply object-oriented (OO) design principles to produce modular, reusable software. Therefore, service-specific groups of related software classes called modules arise in OO systems. Extracting the modules is critical for better software comprehension, efficient architecture recovery, determination of service candidates to migrate legacy software to service-oriented architecture, and transportation of such services to distributed systems or cloud-based platforms. Correctly identifying software modules is also important for software evolution processes because with the increasing popularity of distributed systems and cloud computing, service-oriented architecture (SOA) and migration to SOA have received further stimulus. Developers attempt to identify modules in a software system to transform the underlying services into standard, independent and distributed services. Distributing these services by transporting them into cloud-based service-oriented platforms properly can improve the performance, reliability and security of the programs. In addition, service modules are reusable parts of the system that can be collected in libraries to use in future projects. Identifying software services automatically saves time and makes easier to ensure all these mentioned benefits to the software developers.
In this study, we propose a learning-based module extraction method for object-oriented (OO) systems (LBME) that considers the modular structure of the OO software. Studies on modularization in the literature generally represent an OO software system as a dependency matrix or a dependency graph comprised of classes and their relations. Clustering algorithms have been widely applied on the software graphs for automated architecture recovery. Modularization methods try to define and optimize a modularity objective function by some criteria. These criteria are based on the assumption that modules should be highly cohesive and loosely coupled; therefore, the density of the intra-module (internal) edges should be high, and inter-module (external) edge density should be low.
Our module extraction approach does not depend only on the density of the edges, besides we also consider the characteristics of the classes and the attributes of the relations represented by the edges to discover the modules. The characteristics of the classes and their relations are determined by the OO principles that are applied during the design. The architects and developers aim to develop reusable and flexible components to create maintainable, high-quality software systems. Hence, they follow or "at least try to" follow OO design principles and design patterns. We believe that such concerns strongly affect the modularity of an OO system. For example, Facade classes usually take place on the boundary of a module and they have low cohesion, low complexity, and high coupling. On the other hand, classes inside a module (inner classes) implement the functionality of the module (service) and therefore they can have more complex structures and high level of coupling to libraries. If such inner classes of the modules were written properly, they should be highly cohesive.
Clustering algorithms group some "strongly-connected" nodes in the graph and cut some "weak" edges to form the modules. To improve the accuracy of our algorithm we assign weights to the edges according their probability being internal or external respect to the modules in the system. To determine the weights properly we use two machine learning-based classifiers in the form of decision trees. Using the first decision tree we estimate the probability of the positions (internal/external) of the edges according to the attributes of the relations they represent, such as inheritance, message call, association, aggregation, uses, etc. Considering only the properties of the relations is not sufficient to determine the correct position of an edge. Therefore, using the second decision tree we also classify the source and destination nodes of the edges as "inner class" (in a module) or "border class" (at the border of a module) according to their types such as abstract, interface and metrics such as complexity cohesion, and coupling. Then we combine the results of these two classifiers and determine the probability of the position (internal/external) of the edge more accurately. At the last step, high weight values are assigned to the edges with a high probability of being internal and low weight values are assigned to edges that are more likely external. We train our classifiers with data that are gathered from a real-world software system that is examined in advance.
The reference software system has been developed in a modular structure considering OO principles and patterns. The train data contains the attributes of selected classes and edges, and their real positions in the reference project. After the train phase, the classifiers "learn" the properties of the modular OO design, so that they can classify the positions of new nodes and edges correctly depending on their characteristics. To the best of our knowledge, there has been no mature study reported using OO design features for module extraction.
After the learning phase the proposed module extraction method that contains three main steps is ready to use. In the first step, we build the complete graph model of the software architecture by extracting the software entities (i.e., classes and interfaces) and their relations (i.e., extend and method call) directly from the Abstract Syntax Tree (AST) of the software project. We represent the architecture of the system as a simple directed and labeled graph. In the second step, we assign weight values to the edges depending on the probabilities of the edges being in a module or between different modules. Here, we use decision tree-based classifiers that were trained with the reference project to determine the positions of edges in the graph. Finally, for finding modules in these weighted and directed graphs we apply the agglomerative hierarchical clustering algorithm Fast Community that suits the properties of OO systems as we have shown in a preliminary study.
We implemented an automatic module extraction tool and evaluated the proposed approach on several open source and industrial projects. We evaluated our approach on different industrial OO software systems by working closely with the development team of the projects and on many popular open-source projects. We compared automatically extracted modules by our method, with the modules identified by the developers of the projects or by software experts. We observe that the modules are realistically (close to real modules) extracted. Experimental results show that the proposed approach is highly accurate in modular service extraction for OO systems and outperforms existing methods. The results also show that the proposed method outperforms previously published approaches in the terms of stability, and non-extremity of the module size distribution. |