Mobiele ontwikkeling is tegenwoordig veel complexer en functioneler dan tien jaar geleden. Wat ooit begon als eenvoudige projecten met een paar functies zijn nu geëvolueerd tot geavanceerde systemen met alles van biometrische authenticatie en AI tot geavanceerde camera-integraties. Deze groei vereist een architectuurstrategie die de complexiteit effectief beheert met behoud van codebases van hoge kwaliteit.
In dit artikel verkennen we een robuuste architecturale oplossing voor deze uitdaging: een modulaire of samenstelbare architectuur in mobiele ontwikkeling, geïnspireerd op de microservicearchitectuur die gangbaar is in backendontwikkeling.
Net als bij microservices splitsen we een grote applicatie op in kleine, gerichte mobiele bibliotheken, die zich elk richten op een specifiek domein of een specifieke functionaliteit. Deze modulaire architectuur maakt het mogelijk om meerdere applicaties te bouwen met behulp van deze herbruikbare componenten, waarbij ervoor wordt gezorgd dat elke module losjes gekoppeld blijft. Dit maximaliseert de flexibiliteit, testbaarheid en aanpasbaarheid van elke component.
Laten we eens dieper ingaan op de voordelen van een modulaire architectuur bij mobiele ontwikkeling.
Het gebruik van een modulaire architectuur bij mobiele ontwikkeling zorgt voor een duidelijke scheiding van zorgen. Dit gaat verder dan de onderliggende code tot de organisatiestructuur van het project. Elke module functioneert als een op zichzelf staande eenheid, die een afzonderlijk verantwoordelijkheidsdomein vertegenwoordigt en afzonderlijk wordt ontwikkeld en onderhouden. Dit verbetert niet alleen de leesbaarheid en beheersbaarheid van het project, maar stroomlijnt ook de samenwerking en het debuggen. Bijgevolg creëert de ontwerpfilosofie van de modulaire architectuur een samenhangend systeem waarin de grenzen van de componenten onmiddellijk duidelijk zijn, zelfs zonder in de codebase te duiken.
Een modulaire architectuur verduidelijkt de projectstructuur en bevordert de herbruikbaarheid en onderhoudbaarheid van de code aanzienlijk. Door de app op te delen in modules creëren we herbruikbare componenten die kunnen worden geïntegreerd in verschillende delen van de applicatie of zelfs in geheel nieuwe projecten. Dit hergebruik van code minimaliseert overbodig werk, waardoor ontwikkelaars zich kunnen richten op innovatie in plaats van het wiel opnieuw uit te vinden voor elke nieuwe functie.
Bovendien vereenvoudigt een modulaire architectuur het onderhoud en updaten van apps. Modules werken onafhankelijk van elkaar, waardoor verbeteringen of fixes op de ene module kunnen worden toegepast zonder andere modules onbedoeld te verstoren. Deze scheiding vereenvoudigt het testen en maakt gerichte validatie van wijzigingen mogelijk, wat zorgt voor een stabielere en betrouwbaardere applicatie. Het resultaat is dat de modulaire aanpak een codebase oplevert die niet alleen robuuster is, maar ook flexibeler, zodat de app zich snel kan aanpassen aan nieuwe vereisten of technologische vooruitgang.
Een van de grootste voordelen van een modulaire architectuur in grote mobiele ontwikkelingsprojecten is de verbeterde testbaarheid. In grote monolithische mobiele projecten kunnen bouwtijden aanzienlijk zijn, wat vaak resulteert in inefficiënte workflows.
Stel je bijvoorbeeld voor dat je werkt aan een grote Xamarin-applicatie zonder hot reload-mogelijkheid. Als de UI zich misdraagt, moet je de hele applicatie bouwen en de hele flow doorlopen. En als deze flow afhankelijk is van web calls die worden onderhouden door een klantenteam, dan weet je dat je te maken hebt met een ongelooflijk tijdrovend en inefficiënt proces.
Het gebruik van een modulaire architectuur voor je mobiele ontwikkelingsprojecten biedt een reeks belangrijke voordelen op het gebied van testen:
Geïsoleerd testen
Met een modulaire architectuur kun je alle gegevensafhankelijkheden van een module mocken en deze testen als een op zichzelf staande app. Deze isolatie maakt het mogelijk om gericht te testen op specifieke functionaliteiten zonder de overhead van het draaien van de hele applicatie.
Kortere bouwtijden
Het bouwen van de hele applicatie voor elke wijziging is niet nodig, waardoor de end-to-end testtijden aanzienlijk worden verkort. Deze efficiëntie leidt tot snellere ontwikkelcycli en snellere iteratie, cruciaal voor het behouden van een hoge productiviteit.
Stabiele testomgeving
Het ontkoppelen van modules minimaliseert het risico dat de ene component de andere beïnvloedt, wat zorgt voor betrouwbaardere tests en eenvoudiger opsporen van bugs.
Parallel ontwikkelen en testen
Teams kunnen verschillende modules gelijktijdig ontwikkelen en testen zonder te wachten tot een gedeelde codebase gestabiliseerd is, waardoor het ontwikkelproces versnelt en dynamische, flexibele workflows mogelijk worden.
Een modulaire architectuur resulteert in een efficiënter, betrouwbaarder en schaalbaarder mobiel ontwikkelproces en beperkt de risico's van monolithische architecturen. Door te focussen op modulariteit verbeteren we zowel de ontwikkelings- als de testfase, wat leidt tot een betere algehele softwarekwaliteit.
Bij het ontwikkelen van applicatiemodules is samenwerking met domeinexperts cruciaal om de verschillende functies binnen een organisatie volledig te begrijpen. Door deze samenwerking wordt duidelijk hoe de applicatie logisch kan worden gesegmenteerd. Het documenteren van rollen, gekoppeld aan domeinspecifieke vereisten, moet worden opgelost als een iteratief proces, waarbij voortdurende verfijningen mogelijk zijn die zijn afgestemd op de veranderende behoeften van de organisatie.
In onze modulaire architectuur gebruiken we een basismodule. Zie dit als de genetische code van de applicatie - de kern waarvan elke andere module erft. Deze basismodule bevat alle gedeelde, domeinagnostische functies, waaronder universele ontwerpelementen en besturingselementen. Het centraliseren van deze gemeenschappelijke aspecten zorgt voor een consistente look en feel in de hele app. Elke gespecialiseerde module die op deze basis is gebouwd, neemt inherent deze gedeelde kenmerken over, waardoor de ontwikkeling wordt gestroomlijnd en ervoor wordt gezorgd dat wijzigingen aan fundamentele aspecten slechts eenmaal hoeven te worden doorgevoerd, wat doorwerkt in de hele applicatie.
Zodra de basismodule klaar is, is de volgende stap het maken van de eerste samenstelbare module. De structuur bootst de klassieke gelaagde architectuur na (Data, Domain en Presentation projecten), met een extra Test project om het testen van de module te vergemakkelijken. Dit Test-project roept de module rechtstreeks aan. Het is een eenvoudige mobiele toepassing, meestal bestaande uit een knop om de component op te starten. De rol is om mock definities te bieden voor alle vereiste afhankelijkheden van de module, zodat deze kan worden ingezet op een apparaat of emulator om te testen.
Gegevensproject:
Domeinproject:
Presentatie Project:
Test Project:
Voor elke samenstelbare bibliotheek is het van cruciaal belang om gegevensafhankelijkheden te definiëren via contracten (bv. interfaces) in plaats van gegevensbronnen hard te coderen. Dit zorgt ervoor dat de bibliotheek agnostisch blijft wat betreft de herkomst van gegevens, of ze nu afkomstig zijn van een lokale database of een web-API. Dependency injection levert de juiste gegevensimplementaties aan de module.
Met deze aanpak kunnen consumenten de gegevensbron kiezen. Door ervoor te zorgen dat de samenstelbare bibliotheek zich alleen bezighoudt met het type gegevens dat nodig is, in plaats van met de herkomst van de gegevens, wordt het mocken van gegevenscontracten en de emulatie van verwachte functionele scenario's vereenvoudigd. Deze modulaire en testbare aanpak verbetert de flexibiliteit en onderhoudbaarheid van de codebase aanzienlijk.
Het integreren van een ontwikkelde module in je applicatie is eenvoudig dankzij duidelijk gedefinieerde interfaces en afhankelijkheden:
Het omarmen van modulaire architectuur in mobiele ontwikkeling biedt talloze voordelen, die zowel het ontwikkelproces als het eindproduct verbeteren. Door applicaties op te splitsen in kleinere, beheersbare componenten dwingen we scheiding van zorgen af, bevorderen we herbruikbaarheid van code en verbeteren we de onderhoudbaarheid aanzienlijk. Modules maken geïsoleerd testen mogelijk, verkorten bouwtijden en creëren een stabiele testomgeving, wat uiteindelijk leidt tot een efficiëntere en betrouwbaardere ontwikkelworkflow.