Η αρθρωτότητα είναι η αρχή κατά την οποία η εφαρμογή συναρμολογείται από ανεξάρτητα αρθρώματα, κάθε ένα από τα οποία είναι υπεύθυνο για μία λειτουργικότητα. Σύμφωνα με το Android Developers, η διαίρεση σε αρθρώματα επιταχύνει τη δημιουργία μέσω της παράλληλης μεταγλώττισης και επιτρέπει σε ομάδες να εργάζονται σε διαφορετικά μέρη της εφαρμογής ανεξάρτητα. Η αρθρωτή αρχιτεκτονική έχει γίνει πρότυπο για μεγάλα κινητά έργα με δεκάδες προγραμματιστές.
Κύρια σημεία
Αρθρωτότητα είναι ένας τρόπος οργάνωσης κώδικα κατά τον οποίο η εφαρμογή αποτελείται από χαλαρά συνδεδεμένα αρθρώματα, κάθε ένα από τα οποία παρέχει αυστηρά καθορισμένη λειτουργικότητα μέσω μιας δημόσιας διεπαφής. Σε αντίθεση με τη μονολιθική αρχιτεκτονική, όπου όλες οι κλάσεις βρίσκονται σε ένα έργο, η αρθρωτή προσέγγιση διαιρεί τον κώδικα σε φυσικά ανεξάρτητες μονάδες μεταγλώττισης.
Ο κύριος σκοπός της αρθρωτότητας είναι η διαχείριση της πολυπλοκότητας. Ο προγραμματιστής μπορεί να εστιάσει σε ένα άρθρωμα χωρίς να κρατά όλη τη βάση κώδικα στο μυαλό του. Κάθε άρθρωμα έχει τη δική του ζώνη ευθύνης και μπορεί να αναπτυχθεί, να δοκιμαστεί και να αναπτυχθεί ανεξάρτητα από τα υπόλοιπα. Αυτό είναι ιδιαίτερα πολύτιμο σε έργα με 10+ προγραμματιστές, όπου η παράλληλη εργασία σε ένα μονόλιθο οδηγεί σε συχνές συγκρούσεις συγχώνευσης.
Είναι σημαντικό να διαχωρίζουμε την αρθρωτότητα από τη πολυεπίπεδη αρχιτεκτονική. Τα επίπεδα (Presentation, Domain, Data) διαιρούν τον κώδικα βάσει τεχνικού κριτηρίου, ενώ τα αρθρώματα βάσει λειτουργικού κριτηρίου. Το άρθρωμα \u201cΠροφίλ Χρήστη\u201d μπορεί να περιέχει τα δικά του επίπεδα εντός του. Στην πράξη, η αρθρωτή προσέγγιση και η πολυεπίπεδη αρχιτεκτονική συνδυάζονται: κάθε άρθρωμα έχει τη δική του τριών επιπέδων δομή.
Αρθρώματα Feature — ο πιο δημοφιλής τύπος αρθρωμάτων. Κάθε οθόνη ή ομάδα σχετικών οθονών βρίσκεται σε ξεχωριστό άρθρωμα: Onboarding, Profile, Settings, Feed. Ένα άρθρωμα Feature περιέχει όλα όσα χρειάζονται για τη λειτουργία της λειτουργίας: UI, επιχειρηματική λογική, επίπεδο δεδομένων. Τα όρια του αρθρώματος προστατεύονται — άλλες λειτουργίες δεν μπορούν να έχουν πρόσβαση στις εσωτερικές κλάσεις του.
Αρθρώματα Core περιέχουν την κοινή υποδομή: εργασία δικτύου, βάση δεδομένων, αναλυτική, σύστημα σχεδίασης. Δεν εξαρτώνται από τα αρθρώματα Feature, αλλά τα αρθρώματα Feature εξαρτώνται από αυτά. Αυτή η διαίρεση εγγυάται ότι η αλλαγή του SDK αναλυτικής δεν θα επηρεάσει το επίπεδο δικτύου και αντίστροφα. Τα αρθρώματα Core επαναχρησιμοποιούνται μεταξύ λειτουργιών χωρίς αντιγραφή κώδικα.
Αρθρώματα Shared περιέχουν κώδικα που χρησιμοποιείται από πολλές λειτουργίες: μοντέλα δεδομένων, βοηθητικά εργαλεία, σταθερές, προσαρμοσμένες προβολές. Το κύριο πρόβλημα των shared αρθρωμάτων είναι ο κίνδυνος να γίνουν χώρος σκουπιδιών (\u201cmisc module\u201d), όπου συσσωρεύεται ετερογενής κώδικας με την πάροδο του χρόνου. Κανόνας: ένα shared άρθρωμα πρέπει να έχει σαφές θέμα, για παράδειγμα \u201cshared-ui\u201d ή \u201cshared-models\u201d.
Στο Android τα shared αρθρώματα συχνά διαχωρίζονται σε βιβλιοθήκες με πρόθεμα lib: lib-network, lib-database, lib-ui-components. Στο iOS τις ίδιες λειτουργίες εκτελούν εσωτερικά Swift Packages εντός του Workspace. Στην πράξη, οι ομάδες περιορίζουν τον αριθμό των shared αρθρωμάτων σε 3–5 για να αποφύγουν ένα υπερβολικό δίκτυο εξαρτήσεων που περιπλέκει τη δημιουργία.
Ξεχωριστά αρθρώματα δοκιμών επιτρέπουν την εκτέλεση δοκιμών μόνο για το τροποποιημένο άρθρωμα, χωρίς να εκτελείται ολόκληρη η βάση δοκιμών. Αυτό μειώνει τον χρόνο του pipeline CI/CD από ώρες σε λεπτά. Τα αρθρώματα εξασφαλίζουν τον διαχωρισμό σε επίπεδο δημιουργίας: το άρθρωμα του επιπέδου δικτύου δεν μπορεί να εισαγάγει τυχαία βιβλιοθήκες UI στις δοκιμές.
Κάθε άρθρωμα πρέπει να έχει μια σαφώς καθορισμένη δημόσια API. Στο Android αυτό επιτυγχάνεται μέσω τροποποιητών πρόσβασης και api vs implementation στο Gradle. Στο iOS — μέσω τροποποιητών πρόσβασης public/internal και διαχειριζόμενων εξαρτήσεων μέσω Package.swift. Η μείωση της ορατότητας στο ελάχιστο απαραίτητο είναι μια βασική πρακτική του αρθρωτού σχεδιασμού.
Gradle υποστηρίζει εγγενώς την αρθρωτή αρχιτεκτονική: κάθε άρθρωμα είναι μια ξεχωριστή μονάδα μεταγλώττισης με το δικό του αρχείο build.gradle. Τα έργα Android χρησιμοποιούν έναν συνδυασμό ενός application αρθρώματος (app) και αρκετών library αρθρωμάτων. Τα αρθρώματα βιβλιοθήκης δεν μπορούν να εκτελεστούν ως εφαρμογή, αλλά μπορούν να δημοσιευτούν ως AAR στο αποθετήριο.
Το κλειδί χαρακτηριστικό του Gradle είναι η παράλληλη δημιουργία ανεξάρτητων αρθρωμάτων. Εάν τα αρθρώματα A, B και C δεν εξαρτώνται μεταξύ τους, το Gradle τα μεταγλωττίζει ταυτόχρονα, χρησιμοποιώντας όλους τους πυρήνες του επεξεργαστή. Σε έργα με 20+ αρθρώματα, αυτό μειώνει την πλήρη δημιουργία από 15 σε 3–5 λεπτά. Η προσαυξητική δημιουργία ενός τροποποιημένου αρθρώματος διαρκεί δευτερόλεπτα.
Το Gradle παρέχει δύο τύπους εξαρτήσεων μεταξύ αρθρωμάτων: api (μεταβατικές) και implementation (μη μεταβατικές). Η διαφορά είναι κρίσιμη για την αρθρωτότητα: το implementation κρύβει τις μεταβατικές εξαρτήσεις από τους καταναλωτές του αρθρώματος. Εάν το άρθρωμα :profile χρησιμοποιεί το :networking μέσω implementation, οι καταναλωτές του :profile δεν γνωρίζουν για το :networking και δεν μπορούν να αναφερθούν σε αυτό.
// settings.gradle — δήλωση μονάδων
include ':app'
include ':feature:profile'
include ':feature:settings'
include ':core:network'
include ':core:database'
// build.gradle feature/profile — εξαρτήσεις μονάδας
dependencies {
implementation project(':core:network')
implementation project(':core:database')
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0'
}
Ο κώδικας δείχνει τη δομή ενός αρθρωτού έργου Android. Το Settings.gradle απαριθμεί όλα τα αρθρώματα, και το build.gradle κάθε αρθρώματος Feature καθορίζει μόνο τα αρθρώματα Core που χρειάζεται. Το σύστημα δημιουργίας επιλύει αυτόματα τις μεταβατικές εξαρτήσεις και μεταγλωττίζει τα αρθρώματα στη σωστή σειρά.
Swift Package Manager (SPM) — το πρότυπο εργαλείο αρθρωτότητας στο iOS από το 2019. Το SPM επιτρέπει τη διαίρεση της εφαρμογής σε Swift Packages, κάθε ένα από τα οποία μπορεί να είναι library ή executable. Το Package καθορίζει τα αρθρώματα (targets) και τις εξαρτήσεις τους μέσω Package.swift. Το SPM είναι ενσωματωμένο στο Xcode και δεν απαιτεί πρόσθετα εργαλεία.
CocoaPods παραμένει ο κύριος διαχειριστής εξαρτήσεων για βιβλιοθήκες τρίτων. Τα Podfile και Podspec καθορίζουν την αρθρωτή δομή, και τα CocoaPods δημιουργούν ένα workspace με ξεχωριστά pod έργα. Για τη δική τους αρθρωτότητα, οι ομάδες επιλέγουν ολοένα και περισσότερο το SPM, επειδή είναι ενσωματωμένο στο Xcode και δεν απαιτεί εγκατάσταση.
Στην αρθρωτότητα iOS ο έλεγχος πρόσβασης παίζει σημαντικό ρόλο: public, package, internal, fileprivate και private. Ένα άρθρωμα δημοσιεύει μόνο τους τύπους που πρέπει να είναι προσβάσιμοι από άλλα αρθρώματα. Οι εσωτερικές λεπτομέρειες υλοποίησης είναι κρυμμένες πίσω από τροποποιητές internal και private. Αυτό αποτρέπει την εμφάνιση κρυφών εξαρτήσεων μεταξύ αρθρωμάτων.
// Package.swift — αρθρωτή δομή έργου iOS
let package = Package(
name: "MyApp",
platforms: [.iOS(SupportedPlatform.iOSVersion.v17)],
products: [
.library(name: "ProfileFeature", targets: ["ProfileFeature"]),
.library(name: "NetworkCore", targets: ["NetworkCore"]),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.9.0")
],
targets: [
.target(name: "ProfileFeature", dependencies: ["NetworkCore"]),
.target(name: "NetworkCore", dependencies: ["Alamofire"]),
]
)
Το Package.swift δηλώνει δύο προϊόντα βιβλιοθήκης: ProfileFeature και NetworkCore. Το ProfileFeature εξαρτάται από το NetworkCore, αλλά δεν γνωρίζει την ύπαρξη του Alamofire — είναι κρυμμένο μέσα στο NetworkCore. Τέτοια απομόνωση είναι η άμεση εφαρμογή του διαχωρισμού σε επίπεδο αρθρώματος: οι αλλαγές στον πελάτη HTTP δεν απαιτούν εκ νέου μεταγλώττιση του ProfileFeature.
Το κύριο πλεονέκτημα της αρθρωτότητας είναι η ταχύτητα ανάπτυξης. Οι ομάδες εργάζονται παράλληλα σε διαφορετικά αρθρώματα χωρίς συγκρούσεις κώδικα. Το pipeline CI/CD δημιουργεί μόνο τα τροποποιημένα αρθρώματα και εκτελεί μόνο τις δοκιμές τους. Ο χρόνος ανάδρασης μειώνεται και η συχνότητα εκδόσεων αυξάνεται. Οι Spotify, Uber και Airbnb έχουν δημοσιεύσει περιπτώσεις μετάβασης σε αρθρωτή αρχιτεκτονική με βελτίωση μετρικών κατά 2–3 φορές.
Το δεύτερο πλεονέκτημα — η απομόνωση σφαλμάτων. Ένα σφάλμα στο άρθρωμα Profile δεν επηρεάζει το άρθρωμα Payments, εάν δεν υπάρχουν άμεσες εξαρτήσεις μεταξύ τους. Αυτό είναι ιδιαίτερα σημαντικό σε εφαρμογές με λειτουργίες υψηλού κινδύνου (πληρωμές, ιατρικά δεδομένα), όπου ένα σφάλμα σε μια μη σχετική οθόνη δεν πρέπει να αποκλείει την έκδοση κρίσιμης λειτουργικότητας.
Η κύρια πρόκληση — η διαχείριση εξαρτήσεων. Σε λανθασμένο σχεδιασμό, δημιουργείται ένας γράφος αρθρωμάτων όπου η αλλαγή ενός αρθρώματος αναδομεί καταρρακτωδώς δεκάδες άλλα. Λύση — ακολουθήστε τον κανόνα της ακυκλικότητας: ο γράφος εξαρτήσεων των αρθρωμάτων πρέπει να είναι κατευθυνόμενος ακυκλικός γράφος (DAG). Εργαλεία όπως το Gradle Module Graph Assert βοηθούν στον εντοπισμό κύκλων κατά τη φάση δημιουργίας.
Η δεύτερη πρόκληση — η αύξηση του χρόνου αρχικής ρύθμισης. Η δημιουργία μιας αρθρωτής αρχιτεκτονικής απαιτεί περισσότερο χρόνο κατά τη φάση εκκίνησης του έργου. Τα μικρά έργα με 1–3 προγραμματιστές μπορεί να μην ωφεληθούν από την αρθρωτότητα, ξοδεύοντας χρόνο για τη διατήρηση των ορίων των αρθρωμάτων χωρίς πραγματική ανάγκη παραλληλοποίησης. Λύση — ξεκινήστε με μονολιθική εφαρμογή και εξάγετε αρθρώματα καθώς η ομάδα μεγαλώνει.
Η προσέγγιση Feature-first ομαδοποιεί τα αρθρώματα βάσει λειτουργικότητας: κάθε οθόνη ή ομάδα οθονών γίνεται ξεχωριστό άρθρωμα. Η προσέγγιση Layer-first διαιρεί τον κώδικα βάσει τεχνικού κριτηρίου: ξεχωριστά αρθρώματα για UI, επιχειρηματική λογική και δεδομένα. Στην πράξη, οι περισσότερες ομάδες επιλέγουν feature-first με Core αρθρώματα — αυτό παρέχει καλύτερη απομόνωση και σαφή πλοήγηση στο έργο.
Η επιλογή μεταξύ προσεγγίσεων εξαρτάται από το μέγεθος της ομάδας και την προβλεψιμότητα της λειτουργικότητας. Εάν γνωρίζετε ακριβώς ποιες οθόνες θα είναι στο έργο, η Feature-first επιτρέπει σε κάθε προγραμματιστή να είναι υπεύθυνος για το δικό του άρθρωμα. Εάν η λειτουργικότητα αλλάζει συχνά και αλληλεπικαλύπτεται μεταξύ οθονών, η Layer-first παρέχει μεγαλύτερη ευελιξία στην επαναχρησιμοποίηση κώδικα μεταξύ διαφορετικών λειτουργιών.
Συχνές Ερωτήσεις
Ο βέλτιστος αριθμός εξαρτάται από το μέγεθος του έργου και της ομάδας. Για μια ομάδα 5 ατόμων αρκούν 6–10 αρθρώματα. Για 20+ προγραμματιστές — 20–40 αρθρώματα. Κανόνας: το άρθρωμα πρέπει να είναι αρκετά μικρό ώστε ένας προγραμματιστής να το κατανοεί πλήρως και αρκετά μεγάλο ώστε να μην δημιουργεί υπερβολικό δίκτυο εξαρτήσεων.
Η σωστή αρθρωτότητα επιταχύνει τη δημιουργία μέσω παράλληλης μεταγλώττισης και προσωρινής αποθήκευσης. Αλλά ο υπερβολικός αριθμός αρθρωμάτων με πυκνές εξαρτήσεις επιβραδύνει τη δημιουργία — το Gradle και το Xcode ξοδεύουν χρόνο στην επίλυση του γράφου. Το κλειδί για γρήγορη δημιουργία — ελαχιστοποίηση μεταβατικών εξαρτήσεων και τήρηση ακυκλικότητας.
Ναι, αλλά επαναληπτικά. Ξεκινήστε με την εξαγωγή αρθρωμάτων Core (δίκτυο, βάση δεδομένων), στη συνέχεια εξάγετε λειτουργίες μία προς μία. Χρησιμοποιήστε feature flags για να ενεργοποιήσετε τον νέο αρθρωτό κώδικα παράλληλα με τον παλιό μονολιθικό. Η πλήρης μετάβαση μιας μεγάλης εφαρμογής διαρκεί από 3 έως 12 μήνες.
Τα αρθρώματα είναι μονάδες μεταγλώττισης εντός μιας εφαρμογής. Οι μικροϋπηρεσίες είναι ξεχωριστές διεργασίες που εκτελούνται σε διαφορετικούς διακομιστές. Τα αρθρώματα διαιρούν τον κώδικα, οι μικροϋπηρεσίες διαιρούν τον χρόνο εκτέλεσης. Στην κινητή ανάπτυξη, ο όρος \u201cmicroapps\u201d χρησιμοποιείται συχνά ως υβρίδιο: αρθρώματα Feature που μπορούν να εκτελεστούν ως αυτόνομες εφαρμογές.
Κάθε άρθρωμα έχει τις δικές του δοκιμές μονάδας, που εκτελούνται ανεξάρτητα. Οι δοκιμές ολοκλήρωσης ελέγχουν την αλληλεπίδραση μεταξύ αρθρωμάτων. Οι δοκιμές UI καλύπτουν αρθρώματα Feature με ψευδοδεδομένα. Η αρθρωτή αρχιτεκτονική απλοποιεί τη δοκιμή: η ψευδοποίηση μιας εξάρτησης άλλου αρθρώματος είναι ευκολότερη από την ψευδοποίηση ενός μέρους ενός μονόλιθου.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης