Modüler Mimari Yapıları
Modern enterprise mobil uygulamalarda modüler mimari, ölçeklenebilirlik, sürdürülebilirlik ve takım verimliliği açısından kritik öneme sahip bir mimari yaklaşımdır. Bu yaklaşım, büyük ölçekli uygulamaları yönetilebilir, bağımsız modüllere ayırarak paralel geliştirme, izole test etme ve aşamalı dağıtımı mümkün kılar.
Modüler Mimari İlkeleri
Modüler mimari temelde, endişelerin ayrılması ilkesine dayanan ve yüksek uyum, düşük bağlantı hedeflerini başaran bir sistem tasarım felsefesidir. Bu yaklaşım, karmaşık sistemleri iyi tanımlanmış sınırlara sahip daha küçük, odaklanmış bileşenlere ayırır.
Tek Sorumluluk Modülü Tasarımı
Her modül, tek sorumluluk ilkesini uygulayarak belirli alan işlevselliğini kapsüller. Bu tasarım felsefesi, modül karmaşıklığını yönetilebilir seviyelerde tutar ve değişim yayılımını minimize eder.
// Özellik modülü yapısı örneği
export interface UserFeatureModule {
// Genel API yüzeyi
getUserProfile(userId: string): Promise<UserProfile>;
updateUserProfile(userId: string, profile: Partial<UserProfile>): Promise<void>;
getUserPreferences(userId: string): Promise<UserPreferences>;
// Modül yaşam döngüsü
initialize(dependencies: UserModuleDependencies): void;
dispose(): void;
}
// Dahili modül uygulaması
class UserFeatureModuleImpl implements UserFeatureModule {
private userRepository: UserRepository;
private cacheManager: CacheManager;
private analyticsService: AnalyticsService;
constructor(private dependencies: UserModuleDependencies) {
this.userRepository = dependencies.userRepository;
this.cacheManager = dependencies.cacheManager;
this.analyticsService = dependencies.analyticsService;
}
async getUserProfile(userId: string): Promise<UserProfile> {
// Önce önbellek stratejisi
const cachedProfile = await this.cacheManager.get(`user_profile_${userId}`);
if (cachedProfile) {
this.analyticsService.track('user_profile_cache_hit');
return cachedProfile;
}
// Depodan getir
const profile = await this.userRepository.findById(userId);
await this.cacheManager.set(`user_profile_${userId}`, profile, { ttl: 300 });
this.analyticsService.track('user_profile_fetch');
return profile;
}
initialize(dependencies: UserModuleDependencies): void {
// Modül başlatma mantığı
this.setupEventListeners();
this.preloadCriticalData();
}
dispose(): void {
// Kaynakları temizle
this.cacheManager.clear();
this.removeEventListeners();
}
}
Bu uygulama, modülün dış bağımlılıklarını açıkça tanımlarken, iç uygulama detaylarını kapsüller.
Arayüz Tabanlı Modül İletişimi
Modüller arası iletişim, iyi tanımlanmış arayüzler aracılığıyla uygulanır. Bu yaklaşım, derleme zamanı sözleşme doğrulaması sağlarken, çalışma zamanı esnekliğini korur.
// Swift'te protokol tabanlı modül arayüzü
protocol AuthenticationModule {
func authenticateUser(credentials: UserCredentials) async throws -> AuthenticationResult
func refreshToken(_ token: RefreshToken) async throws -> AccessToken
func signOut() async throws
var isAuthenticated: Bool { get }
var currentUser: User? { get }
}
protocol NotificationModule {
func scheduleNotification(_ notification: LocalNotification) async throws
func cancelNotification(id: String) async throws
func requestPermissions() async throws -> NotificationPermissionStatus
}
// Modüller arası iletişimi yöneten modül koordinatörü
class ModuleCoordinator {
private let authModule: AuthenticationModule
private let notificationModule: NotificationModule
private let userModule: UserFeatureModule
init(
authModule: AuthenticationModule,
notificationModule: NotificationModule,
userModule: UserFeatureModule
) {
self.authModule = authModule
self.notificationModule = notificationModule
self.userModule = userModule
setupModuleInteractions()
}
private func setupModuleInteractions() {
// Kimlik doğrulama durum değişiklikleri kullanıcı verisi güncellemelerini tetikler
authModule.onAuthenticationStateChanged { [weak self] isAuthenticated in
if isAuthenticated {
self?.userModule.preloadUserData()
self?.notificationModule.enablePushNotifications()
} else {
self?.userModule.clearUserData()
self?.notificationModule.disablePushNotifications()
}
}
}
}
Özellik Tabanlı Modül Organizasyonu
Büyük ölçekli mobil uygulamalarda, özellik tabanlı modül organizasyon stratejisi, alan odaklı tasarım ilkelerini mobil mimariye uyarlar. Bu yaklaşım, iş yetenekleri etrafında modülleri organize ederek takım özerkliğini ve paralel geliştirmeyi kolaylaştırır.
Alan Odaklı Modül Sınırları
Alan sınırları, iş mantığı uyumuna dayanan doğal modül ayrım noktaları sağlar. Her alan modülü, belirli iş yeteneğini tamamen kapsüller ve minimum dış bağımlılık gerektirir.
// Android'de özellik modülü yapısı
@Module
@InstallIn(SingletonComponent::class)
object EcommerceFeatureModule {
@Provides
@Singleton
fun provideProductCatalogService(
productRepository: ProductRepository,
searchEngine: SearchEngine,
recommendationEngine: RecommendationEngine
): ProductCatalogService {
return ProductCatalogServiceImpl(
productRepository = productRepository,
searchEngine = searchEngine,
recommendationEngine = recommendationEngine
)
}
@Provides
@Singleton
fun provideShoppingCartService(
cartRepository: CartRepository,
pricingEngine: PricingEngine,
inventoryService: InventoryService
): ShoppingCartService {
return ShoppingCartServiceImpl(
cartRepository = cartRepository,
pricingEngine = pricingEngine,
inventoryService = inventoryService
)
}
@Provides
@Singleton
fun provideOrderManagementService(
orderRepository: OrderRepository,
paymentService: PaymentService,
shippingService: ShippingService,
notificationService: NotificationService
): OrderManagementService {
return OrderManagementServiceImpl(
orderRepository = orderRepository,
paymentService = paymentService,
shippingService = shippingService,
notificationService = notificationService
)
}
}
// Özellik modülü genel API'si
interface EcommerceModule {
val productCatalog: ProductCatalogService
val shoppingCart: ShoppingCartService
val orderManagement: OrderManagementService
}
Kapsamlı Endişelerin Yönetimi
Kapsamlı endişeler, birden fazla modüle yayılan işlevsellikler olup, özelleşmiş altyapı modülleri tarafından ele alınırlar. Günlükleme, güvenlik, önbellekleme gibi endişeler, özel modüller aracılığıyla merkezi yönetim alırlar.
// Kapsamlı endişeler için altyapı modülü
export class InfrastructureModule {
private logger: Logger;
private securityManager: SecurityManager;
private cacheManager: CacheManager;
private analyticsEngine: AnalyticsEngine;
constructor(config: InfrastructureConfig) {
this.logger = new StructuredLogger(config.logging);
this.securityManager = new SecurityManager(config.security);
this.cacheManager = new MultiLevelCacheManager(config.caching);
this.analyticsEngine = new AnalyticsEngine(config.analytics);
}
// Kapsamlı endişeler için yön odaklı programlama
createProxy<T>(target: T, moduleName: string): T {
return new Proxy(target, {
get: (target, property, receiver) => {
const originalMethod = Reflect.get(target, property, receiver);
if (typeof originalMethod === 'function') {
return (...args: any[]) => {
// Güvenlik kontrolü
this.securityManager.validateAccess(moduleName, property as string);
// Günlükleme
this.logger.info(`${moduleName}.${property as string} çağrıldı`, { args });
// Performans izleme
const startTime = performance.now();
try {
const result = originalMethod.apply(target, args);
// Asenkron metodları ele al
if (result instanceof Promise) {
return result
.then(value => {
this.logMethodCompletion(moduleName, property as string, startTime);
return value;
})
.catch(error => {
this.logMethodError(moduleName, property as string, startTime, error);
throw error;
});
}
this.logMethodCompletion(moduleName, property as string, startTime);
return result;
} catch (error) {
this.logMethodError(moduleName, property as string, startTime, error);
throw error;
}
};
}
return originalMethod;
}
});
}
}
Derleme Sistemi ve Modül Yönetimi
Modern mobil geliştirmede, gelişmiş derleme sistemleri modüler mimarinin etkili yönetimini sağlar. Bu sistemler, bağımlılık çözümlemesi, derleme optimizasyonu ve dağıtım stratejilerini ele alır.
Bağımlılık Grafiği Yönetimi
Modül bağımlılıkları, karmaşık yönlü asiklik grafikler (DAG) oluşturur ve derleme sisteminin verimli çözümleme ve doğrulamasını gerektirir. Döngüsel bağımlılıkların tespiti ve önlenmesi, sistem kararlılığı açısından kritik öneme sahiptir.
// Gradle çok modüllü derleme yapılandırması
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
android {
namespace 'com.enterprise.mobileapp'
compileSdk 34
defaultConfig {
applicationId "com.enterprise.mobileapp"
minSdk 24
targetSdk 34
versionCode 1
versionName "1.0"
}
buildTypes {
debug {
debuggable true
applicationIdSuffix ".debug"
buildConfigField "boolean", "ENABLE_LOGGING", "true"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "ENABLE_LOGGING", "false"
}
}
}
dependencies {
// Temel altyapı modülleri
implementation project(':core:infrastructure')
implementation project(':core:analytics')
implementation project(':core:security')
// Özellik modülleri
implementation project(':features:authentication')
implementation project(':features:user-profile')
implementation project(':features:ecommerce')
implementation project(':features:notifications')
// Dış bağımlılıklar
implementation libs.hilt.android
kapt libs.hilt.compiler
implementation libs.retrofit
implementation libs.okhttp
implementation libs.kotlinx.coroutines.android
}
Aşamalı Derleme Optimizasyonu
Modüler mimari, aşamalı derleme optimizasyonlarını sağlayarak geliştirme döngüsü sürelerini önemli ölçüde azaltır. Değişen modüllerin seçici derlemesi, büyük kod tabanlarında önemli zaman tasarrufu sağlar.
// Swift Paket Yöneticisi modüler yapılandırması
// Package.swift
import PackageDescription
let package = Package(
name: "MobileApp",
platforms: [
.iOS(.v15),
.macOS(.v12)
],
products: [
.library(name: "CoreInfrastructure", targets: ["CoreInfrastructure"]),
.library(name: "AuthenticationModule", targets: ["AuthenticationModule"]),
.library(name: "UserProfileModule", targets: ["UserProfileModule"]),
.library(name: "EcommerceModule", targets: ["EcommerceModule"])
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.0.0"),
.package(url: "https://github.com/realm/realm-swift.git", from: "10.0.0")
],
targets: [
// Temel altyapı
.target(
name: "CoreInfrastructure",
dependencies: ["Alamofire"],
path: "Sources/CoreInfrastructure"
),
// Özellik modülleri
.target(
name: "AuthenticationModule",
dependencies: ["CoreInfrastructure"],
path: "Sources/Features/Authentication"
),
.target(
name: "UserProfileModule",
dependencies: ["CoreInfrastructure", "AuthenticationModule"],
path: "Sources/Features/UserProfile"
),
.target(
name: "EcommerceModule",
dependencies: [
"CoreInfrastructure",
"AuthenticationModule",
"UserProfileModule"
],
path: "Sources/Features/Ecommerce"
),
// Test hedefleri
.testTarget(
name: "AuthenticationModuleTests",
dependencies: ["AuthenticationModule"],
path: "Tests/Features/Authentication"
)
]
)
Dinamik Modül Yükleme
Gelişmiş mobil uygulamalarda, dinamik modül yükleme yetenekleri çalışma zamanı esnekliği sağlarken, uygulama başlatma performansını optimize eder. Bu teknik, isteğe bağlı özellik yükleme ve A/B test senaryolarında özellikle değerlidir.
Tembel Modül Başlatma
Tembel yükleme deseni, modüllerin ilk erişimde başlatılmasını sağlayarak uygulama başlatma süresini azaltır. Bu yaklaşım, bellek ayak izini optimize ederken, algılanan performansı artırır.
// Android'de tembel modül yükleme
class ModuleRegistry {
private val moduleFactories = mutableMapOf<String, () -> FeatureModule>()
private val loadedModules = mutableMapOf<String, FeatureModule>()
fun registerModule(name: String, factory: () -> FeatureModule) {
moduleFactories[name] = factory
}
suspend fun loadModule(name: String): FeatureModule {
return loadedModules[name] ?: run {
val module = withContext(Dispatchers.Default) {
moduleFactories[name]?.invoke()
?: throw IllegalArgumentException("$name modülü kayıtlı değil")
}
module.initialize()
loadedModules[name] = module
// Analitik takibi
analyticsService.track("module_loaded", mapOf(
"module_name" to name,
"load_time" to System.currentTimeMillis()
))
module
}
}
suspend fun unloadModule(name: String) {
loadedModules[name]?.let { module ->
module.dispose()
loadedModules.remove(name)
// Modül için çöp toplamayı zorla
System.gc()
analyticsService.track("module_unloaded", mapOf(
"module_name" to name
))
}
}
}
Uzaktan Modül Teslimatı
Bulut tabanlı modül teslimatı, uygulamaların dağıtım sonrasında yeni özellikler almasını sağlar. Bu yaklaşım, uygulama mağazası onay döngülerini atlayarak, aşamalı kullanıma sunma stratejilerini mümkün kılar.
// Uzaktan modül yükleme altyapısı
class RemoteModuleLoader {
private let networkClient: NetworkClient
private let moduleCache: ModuleCache
private let securityValidator: ModuleSecurityValidator
init(
networkClient: NetworkClient,
moduleCache: ModuleCache,
securityValidator: ModuleSecurityValidator
) {
self.networkClient = networkClient
self.moduleCache = moduleCache
self.securityValidator = securityValidator
}
func loadRemoteModule(moduleId: String, version: String) async throws -> FeatureModule {
// Önce yerel önbelleği kontrol et
if let cachedModule = await moduleCache.getModule(id: moduleId, version: version) {
return cachedModule
}
// Modül paketini indir
let moduleBundle = try await networkClient.downloadModule(
id: moduleId,
version: version
)
// Güvenlik doğrulaması
try securityValidator.validateModule(moduleBundle)
// Modülü yükle ve örnekle
let module = try await instantiateModule(from: moduleBundle)
// Gelecekte kullanmak için önbelleğe al
await moduleCache.storeModule(module, id: moduleId, version: version)
return module
}
private func instantiateModule(from bundle: ModuleBundle) async throws -> FeatureModule {
// Dinamik yükleme uygulaması
guard let moduleClass = bundle.loadClass("FeatureModuleImpl") else {
throw ModuleLoadError.classNotFound
}
let module = try moduleClass.init() as! FeatureModule
await module.initialize()
return module
}
}
Modüler Mimari için Test Stratejileri
Modüler mimari, kapsamlı test stratejilerinin uygulanmasını kolaylaştırır. Modül düzeyinde izolasyon, bağımsız testi mümkün kılarken, entegrasyon testleri karmaşık senaryoları doğrular.
Modül İzolasyon Testi
Her modül, izole edilmiş ortamda test edilebilir ve sahte bağımlılıklar kullanarak deterministik test senaryoları oluşturabilir. Bu yaklaşım, hızlı geri bildirim döngüleri ve güvenilir test yürütmesi sağlar.
// Modül izolasyon test çerçevesi
describe('UserProfileModule', () => {
let userModule: UserFeatureModule;
let mockDependencies: MockUserModuleDependencies;
beforeEach(async () => {
mockDependencies = createMockDependencies();
userModule = new UserFeatureModuleImpl(mockDependencies);
await userModule.initialize(mockDependencies);
});
afterEach(async () => {
await userModule.dispose();
});
describe('getUserProfile', () => {
it('kullanılabilir olduğunda önbelleğe alınmış profili döndürmeli', async () => {
// Düzenle
const userId = 'user-123';
const cachedProfile = createMockUserProfile(userId);
mockDependencies.cacheManager.get.mockResolvedValue(cachedProfile);
// Uygula
const result = await userModule.getUserProfile(userId);
// Doğrula
expect(result).toEqual(cachedProfile);
expect(mockDependencies.cacheManager.get).toHaveBeenCalledWith(`user_profile_${userId}`);
expect(mockDependencies.userRepository.findById).not.toHaveBeenCalled();
});
it('önbellek kaçırıldığında depodan almalı', async () => {
// Düzenle
const userId = 'user-456';
const repositoryProfile = createMockUserProfile(userId);
mockDependencies.cacheManager.get.mockResolvedValue(null);
mockDependencies.userRepository.findById.mockResolvedValue(repositoryProfile);
// Uygula
const result = await userModule.getUserProfile(userId);
// Doğrula
expect(result).toEqual(repositoryProfile);
expect(mockDependencies.userRepository.findById).toHaveBeenCalledWith(userId);
expect(mockDependencies.cacheManager.set).toHaveBeenCalledWith(
`user_profile_${userId}`,
repositoryProfile,
{ ttl: 300 }
);
});
});
});
Modüller Arası Entegrasyon Testi
Çapraz modül entegrasyon testi, modüllerin doğru işbirliğini doğrular ve sistem düzeyinde davranışı onaylar. Bu testler, uçtan uca senaryoları kapsarken, modül arayüz sözleşmelerini uygular.
// Entegrasyon test çerçevesi
@RunWith(AndroidJUnit4::class)
@HiltAndroidTest
class ModuleIntegrationTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@Inject
lateinit var authModule: AuthenticationModule
@Inject
lateinit var userModule: UserFeatureModule
@Inject
lateinit var notificationModule: NotificationModule
@Before
fun setup() {
hiltRule.inject()
}
@Test
fun userAuthenticationFlow_shouldTriggerCrossModuleInteractions() = runTest {
// Düzenle
val credentials = UserCredentials("test@example.com", "password123")
// Uygula - Kullanıcı kimlik doğrulaması
val authResult = authModule.authenticateUser(credentials)
// Doğrula - Kimlik doğrulama başarılı
assertTrue(authResult.isSuccess)
assertTrue(authModule.isAuthenticated)
// Doğrula - Kullanıcı modülü kimlik doğrulama olayını alır
val currentUser = userModule.getCurrentUser()
assertNotNull(currentUser)
assertEquals(credentials.email, currentUser?.email)
// Doğrula - Bildirim modülü etkinleştirilir
val notificationStatus = notificationModule.getPermissionStatus()
assertTrue(notificationStatus.isEnabled)
// Uygula - Çıkış yap
authModule.signOut()
// Doğrula - Tüm modüller çıkışa tepki verir
assertFalse(authModule.isAuthenticated)
assertNull(userModule.getCurrentUser())
assertFalse(notificationModule.getPermissionStatus().isEnabled)
}
}
Modüler mimari deseninin kapsamlı uygulaması, büyük ölçekli mobil uygulamalarda sürdürülebilirlik, ölçeklenebilirlik ve takım verimliliğini dramatik olarak iyileştirir. Bu sistematik yaklaşım, karmaşık sistemlerin yönetilebilir bileşenlere ayrılmasını sağlarken, yüksek kaliteli yazılım teslimatını kolaylaştırır.