SlideShare une entreprise Scribd logo
@Xebiconfr #Xebicon18 @pjechris
Build the future
Architecturer son application mobile
sur la durée
Jean-Christophe Pastant
1
@Xebiconfr #Xebicon18 @pjechris
Qui suis-je ?
Jean-Christophe Pastant
iOS Developer/Architect
Xebia IT Architects
@pjechris
2
@Xebiconfr #Xebicon18 @pjechris
Une architecture n’a pas besoin d’être complexe
pour être réussie
3
@Xebiconfr #Xebicon18 @pjechris
Architecturer ?
4
@Xebiconfr #Xebicon18 @pjechris
Bonne architecture ?
5
@Xebiconfr #Xebicon18 @pjechris
Bonne architecture ?
● Orientée vers le besoin fonctionnel
● Construite pour le présent (Pragmatique)
● Lisible (Simple)
● Cohérente (Simple, Pragmatique)
6
@Xebiconfr #Xebicon18 @pjechris
Architecture pérenne ?
7
@Xebiconfr #Xebicon18 @pjechris
Architecture pérenne ?
● Robuste dans le temps (petites modifications)
● Évolutive dans le temps (grosses modifications)
8
@Xebiconfr #Xebicon18 @pjechris
Architecturer ?
Une bonne architecture pérenne se doit d’être :
● Simple
KEEP IT SIMPLE, STUPID
● Pragmatique
YOU AIN’T GONNA NEED IT
● Fonctionnelle/métier
DOMAIN DRIVEN DESIGN
● Modifiable/évolutive
SEPARATION OF CONCERN, OPEN/CLOSED PRINCIPLE
9
@Xebiconfr #Xebicon18 @pjechris
Structurer
en couches
Keep it simple, You ain’t gonna need it, Domain Driven Design, Separation of Concern
@Xebiconfr #Xebicon18 @pjechris
Structurer en couches permet de :
● Séparer les responsabilités
○ Affichage
○ Appels réseaux
○ ….
● Réfléchir quel rôle (couche) joue une classe
● Être plus ouvert aux changements
○ On est agnostique des couches supérieures
Structurer en couches
11
@Xebiconfr #Xebicon18 @pjechris
Structurer en couches
Données
Métier
UI
DB WS Cache
login
logout
checkout
addBook
Layout i18n Formatting
12
@Xebiconfr #Xebicon18 @pjechris
Structurer en couches
Données
Métier
UI
DB WS Cache
login
logout
checkout
addBook
Layout i18n Formatting
Modèles
métier
13
@Xebiconfr #Xebicon18 @pjechris
Modèles métier
14
Keep it simple, Domain Driven Design
@Xebiconfr #Xebicon18 @pjechris
Exemple
● Pouvoir ajouter des livres dans un panier
● Afficher le panier
● Afficher le prix total du panier
source : application Fnac (Android)
15
@Xebiconfr #Xebicon18 @pjechris
Modèles métier
struct Book {
let id: Int
let isbn: String
let title: String
let price: Float
}
16
@Xebiconfr #Xebicon18 @pjechris
Modèles métier
import ReactiveKit
struct Cart {
private(set) var books: [Book]
var total: Observable<Float>
mutating func add(book: Book) { }
mutating func remove(index: Int) { }
}
17
@Xebiconfr #Xebicon18 @pjechris
Modèles métier
import ReactiveKit
struct Cart {
private(set) var books: [Book]
var total: Float
mutating func add(book: Book) { }
mutating func remove(index: Int) { }
}
18
@Xebiconfr #Xebicon18 @pjechris
Modèles métier
struct Cart {
private(set) var books: [Book]
var total: Float
mutating func add(book: Book) { }
mutating func remove(book: Book) { }
}
19
@Xebiconfr #Xebicon18 @pjechris
Modèles métier
● Notion centrale du métier/fonctionnel dans l’application
● Donne du sens dans la communication entre les couches
● Doit être orienté métier
● Objets simples
○ Immutables
○ Pas de réseau, pas d’asynchrone, etc...
20
@Xebiconfr #Xebicon18 @pjechris
UI
“Dumb components”
Keep it simple, Domain Driven Design, Open/Closed principle
@Xebiconfr #Xebicon18 @pjechris
Exemple
Application Fnac (Android)
CartItemView
priceLabel
title
22
@Xebiconfr #Xebicon18 @pjechris
Exemple
Application Fnac (Android)
CartItemView
23
CartRecapView
@Xebiconfr #Xebicon18 @pjechris
UI
class CartItemView: UIView {
var priceLabel: UILabel!
var title: UILabel!
func configure(title: String, price: String) {
priceLabel.text = price
title.text = title
}
}
24
@Xebiconfr #Xebicon18 @pjechris
UI
class CartItemView: UIView {
var priceLabel: UILabel!
var title: UILabel!
func configure(title: String, price: String) {
priceLabel.text = price
title.text = title
}
}
class CartRecapView: UIView {
var priceLabel: UILabel!
func configure(price: String) {
priceLabel.text = price
}
}
25
@Xebiconfr #Xebicon18 @pjechris
UI
class CartItemView: UIView {
var priceLabel: UILabel!
var title: UILabel!
func configure(book: Book) {
priceLabel.text = price
title.text = title
}
}
class CartRecapView: UIView {
var priceLabel: UILabel!
func configure(cart: Cart) {
priceLabel.text = price
}
}
26
@Xebiconfr #Xebicon18 @pjechris
UI
class CartItemView: UIView {
var priceLabel: UILabel!
var title: UILabel!
func configure(book: Book) {
priceLabel.text = stringify(book.price, .currency)
title.text = book.title.uppercased
}
}
class CartRecapView: UIView {
var priceLabel: UILabel!
func configure(cart: Cart) {
priceLabel.text = stringify(cart.total, .currency)
}
}
27
@Xebiconfr #Xebicon18 @pjechris
UI
struct PriceComponent {
func bind(price: Float, label: UILabel) {
}
}
28
@Xebiconfr #Xebicon18 @pjechris
UI
struct PriceComponent {
func bind(price: Float, label: UILabel) {
label.text = stringify(price, style: .currency)
}
}
29
@Xebiconfr #Xebicon18 @pjechris
UI
struct PriceComponent {
func bind(price: Float, label: UILabel) {
label.text = stringify(price, style: .currency)
}
}
struct TitleComponent {
func bind(title: String, label: UILabel) {
label.text = title.capitalize
}
}
30
@Xebiconfr #Xebicon18 @pjechris
UI
class CartItemView: UIView {
var priceLabel: UILabel!
var title: UILabel!
func configure(book: Book) {
priceLabel.text = stringify(book.price, .currency)
title.text = book.title.uppercased
}
}
class CartRecapView: UIView {
var priceLabel: UILabel!
func configure(cart: Cart) {
priceLabel.text = stringify(cart.total, .currency)
}
}
31
@Xebiconfr #Xebicon18 @pjechris
UI
class CartItemView: UIView {
var priceLabel: UILabel!
var title: UILabel!
func configure(book: Book) {
priceLabel.bind(book.price, with: PriceComponent.self)
title.bind(book.title, with: TitleComponent.self)
}
}
class CartRecapView: UIView {
var priceLabel: UILabel!
func configure(cart: Cart) {
priceLabel.bind(cart.total, with: PriceComponent.self)
}
}
32
@Xebiconfr #Xebicon18 @pjechris
UI
● Faire des petits composants UI réutilisables
● Préférer combiner les composants plutôt que l’héritage
● Exposer une API métier
33
@Xebiconfr #Xebicon18 @pjechris
Métier
“Smart components”
Keep it simple, You ain’t gonna need it, Domain Driven Design
@Xebiconfr #Xebicon18 @pjechris
Métier
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
}
35
@Xebiconfr #Xebicon18 @pjechris
Métier
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
private let httpRepository: XebiaWSRepository
init(cart: Cart) {
self.cart = cart
self.httpRepository = XebiaWSRepository(...)
}
}
36
@Xebiconfr #Xebicon18 @pjechris
Métier
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
private let httpRepository: XebiaWSRepository
init(cart: Cart) {
self.cart = cart
self.httpRepository = XebiaWSRepository(...)
self.checkoutAction = Action(
enabledIf: { !cart.isEmpty },
factory: { httpRepository.checkout(self.cart) })
}
}
37
@Xebiconfr #Xebicon18 @pjechris
Métier
● Lien entre la couche données et la couche UI
● Définissent les actions / règles métier
○ Passer une commande seulement si le panier n’est pas vide
○ …
● Font les appels réseaux
● Gérent les états
● Exposent une API métier
38
@Xebiconfr #Xebicon18 @pjechris
Données
39
Keep it simple, Separation of Concern
@Xebiconfr #Xebicon18 @pjechris
Données
class XebiaWSRepository {
func checkout(cart: Cart, success: (Void) -> (), failure:
(Error) -> ()) {
}
40
@Xebiconfr #Xebicon18 @pjechris
Données
class XebiaWSRepository {
func checkout(cart: Cart, success: (Void) -> (), failure:
(Error) -> ()) {
let url = URL(string: “…”)
SessionManager.default.request(url).responseJSON {
}
}
41
@Xebiconfr #Xebicon18 @pjechris
class XebiaWSRepository {
func checkout(cart: Cart, success: (Void) -> (), failure:
(Error) -> ()) {
let url = URL(string: “…”)
SessionManager.default.request(url).responseJSON {
let json = JSON(data: $0.jsonData)
do {
let books = try JSONDecoder().decode([Book].self,
from: jsonData)
success(books)
}
catch let error { failure(error) }
}
}
42
@Xebiconfr #Xebicon18 @pjechris
Données
class XebiaWSRepository {
func checkout(cart: Cart) -> Promise<Void> {
}
}
43
@Xebiconfr #Xebicon18 @pjechris
Données
class XebiaWSRepository {
let builder: HttpQueryBuilder<XebiaEndpoint>
func checkout(cart: Cart) -> Promise<Void> {
return builder.query(.checkout(cart)).request()
}
}
44
@Xebiconfr #Xebicon18 @pjechris
Données
class XebiaWSRepository {
let builder: HttpQueryBuilder<XebiaEndpoint>
func checkout(cart: Cart) -> Promise<Void> {
return builder.query(.checkout(cart)).request()
}
func findBooks() -> Promise<[Book]> {
return builder.query(.books).request()
}
}
45
@Xebiconfr #Xebicon18 @pjechris
Données
● Doit être simple mais fiable et lisible
● Stateless
● Mapping 1-to-1 avec les services fournies
○ 1 classe = 1 service (DB, WS, …)
○ 1 méthode = 1 API
46
@Xebiconfr #Xebicon18 @pjechris
Providers
47
Separation of Concern
@Xebiconfr #Xebicon18 @pjechris
Providers
class CartProvider {
let httpRepository: XebiaWSRepository
func checkout(cart: Cart) -> Promise<Void> {
return httpRepository
.checkout(cart)
}
}
48
@Xebiconfr #Xebicon18 @pjechris
Providers
class CartProvider {
let httpRepository: XebiaWSRepository
let realmRepository: RealmRepository
func checkout(cart: Cart) -> Promise<Void> {
return httpRepository
.checkout(cart)
.then { realmRepository.savePurchasedCart($0) }
}
}
49
@Xebiconfr #Xebicon18 @pjechris
Providers
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
private let httpRepository: XebiaWSRepository
init(cart: Cart) {
self.cart = cart
self.httpRepository = XebiaWSRepository(...)
self.checkoutAction = Action(
enabledIf: { !cart.isEmpty },
factory: { httpRepository.checkout(self.cart) })
}
}
50
@Xebiconfr #Xebicon18 @pjechris
Providers
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
private let cartProvider: CartProvider
init(cart: Cart) {
self.cart = cart
self.cartProvider = CartProvider(...)
self.checkoutAction = Action(
enabledIf: { !cart.isEmpty },
factory: { cartProvider.checkout(cart: self.cart) })
}
}
51
@Xebiconfr #Xebicon18 @pjechris
Providers
● Facilite la synchronisation/les accès à plusieurs Repository
● Réduit la logique dans les Smart Components
● 1 classe par objet métier (BookProvider, CartProvider, …)
52
@Xebiconfr #Xebicon18 @pjechris
Injection de dépendances
53
Keep it simple, Separation of Concern
@Xebiconfr #Xebicon18 @pjechris
Injection de dépendances
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
private let cartProvider: CartProvider
init(cart: Cart) {
self.cart = cart
self.cartProvider = CartProvider(...)
self.checkoutAction = Action(
enabledIf: { !cart.isEmpty },
factory: { cartProvider.checkout(cart: self.cart) })
}
}
54
@Xebiconfr #Xebicon18 @pjechris
Injection de dépendances
class CartComponentContext {
// API
private(set) var cart: Variable<Cart>
let checkoutAction: Action
private let cartProvider: CartProvider
init(cart: Cart, cartProvider: CartProvider) {
self.cart = cart
self.cartProvider = cartProvider
self.checkoutAction = Action(
enabledIf: { !cart.isEmpty },
factory: { cartProvider.checkout(cart: self.cart) })
}
}
55
@Xebiconfr #Xebicon18 @pjechris
Injection de dépendances
● Aide à garder les couches indépendantes
● Limite la connaissance de chaque objet au strict minimum
● Permet de tester plus facilement
56
@Xebiconfr #Xebicon18 @pjechris
Tests unitaires
57
@Xebiconfr #Xebicon18 @pjechris
Tests unitaires
Tester doit être simple
Si :
● Vous écrivez trop de lignes pour un test (+ 10 lignes)
● C’est trop compliqué de tester malgré tous vos protocoles/interfaces
Revoyez votre architecture !
58
@Xebiconfr #Xebicon18 @pjechris
We did it!
59
@Xebiconfr #Xebicon18 @pjechris
We did it!
● Simple
Petites classes, code réutilisable, séparation des rôles
● Pragmatique
Code incrémental, isolation des rôles
● Fonctionnelle/métier
APIs orientées modèles métier
● Modifiable/évolutive
Structure en couches, injection de dépendances, principes SOLID
60
@Xebiconfr #Xebicon18 @pjechris
MERCI
Questions ?

Contenu connexe

PDF
XebiCon'18 - Deno, le nouveau NodeJS qui inverse la tendance ?
PDF
XebiCon'18 - Comment j'ai développé un jeu vidéo avec des outils de développe...
PDF
XebiCon'18 - La sécurité, douce illusion même en 2018
PDF
Xebicon'18 - Spark in jail : conteneurisez vos traitements data sans serveur
PDF
XebiCon'18 - Les utilisateurs finaux, les oubliés de nos produits !
PDF
XebiCon'16 : GraphQL et Falcor, un nouveau regard sur les architectures REST ...
PDF
XebiCon'16 : NodeJS x Craftsmanship - Comment faire un projet dans les règles...
PDF
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services Par Al...
XebiCon'18 - Deno, le nouveau NodeJS qui inverse la tendance ?
XebiCon'18 - Comment j'ai développé un jeu vidéo avec des outils de développe...
XebiCon'18 - La sécurité, douce illusion même en 2018
Xebicon'18 - Spark in jail : conteneurisez vos traitements data sans serveur
XebiCon'18 - Les utilisateurs finaux, les oubliés de nos produits !
XebiCon'16 : GraphQL et Falcor, un nouveau regard sur les architectures REST ...
XebiCon'16 : NodeJS x Craftsmanship - Comment faire un projet dans les règles...
XebiCon'16 : Choisissez votre style avec Docker & Amazon Web Services Par Al...

Tendances (8)

PDF
XebiCon'16 : La programmation concurrente en Go. Par Jérome Doucet et Diana O...
PDF
XebiCon'16 : Orange - Transformation DevOps, les conteneurs sont vos alliés !
PDF
XebiCon'16 : Les coulisses de Xebia Studio. Par Ludovic Perot et Nicolas Joz...
PDF
XebiCon'16 : Le futur de la télévision, les applications ! Par Fabien Mirault...
PDF
Xebicon2016 - React Native & Redux
PPTX
XebiCon'16 : Cellenza - Votre miroir interactif connecté avec Raspberry Pi 2,...
PPTX
XebiCon'16 : Xebia Labs : Les outils de déploiement sont morts avec les Conta...
PPTX
OVHcloud Tech-Talk S01E04 - La télémétrie au service de l'agilité
XebiCon'16 : La programmation concurrente en Go. Par Jérome Doucet et Diana O...
XebiCon'16 : Orange - Transformation DevOps, les conteneurs sont vos alliés !
XebiCon'16 : Les coulisses de Xebia Studio. Par Ludovic Perot et Nicolas Joz...
XebiCon'16 : Le futur de la télévision, les applications ! Par Fabien Mirault...
Xebicon2016 - React Native & Redux
XebiCon'16 : Cellenza - Votre miroir interactif connecté avec Raspberry Pi 2,...
XebiCon'16 : Xebia Labs : Les outils de déploiement sont morts avec les Conta...
OVHcloud Tech-Talk S01E04 - La télémétrie au service de l'agilité
Publicité

Similaire à XebiCon'18 - Architecturer son application mobile pour la durabilité (20)

PDF
Devoxx France - Nouvelles du Front
PDF
Architecture ASIS (iOS)
PDF
Apple Watch par Benoit Capallere et Joeffrey Bocquet
PPTX
OOP & Design Pattern - Algiers Developers Meetup August 2015
PPTX
OOP and Design Patterns
PPS
Client riche et nouvelles technologies
PDF
XebiConFr 15 - Swift dans la vraie vie
PDF
AGL.pdf
PDF
Urbaniser un SI pour 10 ans
PDF
Design applicatif avec symfony2
PPTX
AspectizeWhyHowWhat
PDF
Mobiliteatime #2 - WatchKit, le framework de développement pour l’Apple Watch
PDF
Gestion des actifs applicatifs
PDF
XebiConFr 15 - Ingenico Group : Microservices et architecture réactive pour u...
PPTX
MVVM de A à Z
PPTX
USI 2009 - Du RIA pour SI
PDF
Design applicatif avec symfony - Zoom sur la clean architecture - Symfony Live
PPT
Introduction au Domain Driven Design
PDF
Parlons App Economie : du dev à l'usage
PDF
La Gestion de Projet Mobile
Devoxx France - Nouvelles du Front
Architecture ASIS (iOS)
Apple Watch par Benoit Capallere et Joeffrey Bocquet
OOP & Design Pattern - Algiers Developers Meetup August 2015
OOP and Design Patterns
Client riche et nouvelles technologies
XebiConFr 15 - Swift dans la vraie vie
AGL.pdf
Urbaniser un SI pour 10 ans
Design applicatif avec symfony2
AspectizeWhyHowWhat
Mobiliteatime #2 - WatchKit, le framework de développement pour l’Apple Watch
Gestion des actifs applicatifs
XebiConFr 15 - Ingenico Group : Microservices et architecture réactive pour u...
MVVM de A à Z
USI 2009 - Du RIA pour SI
Design applicatif avec symfony - Zoom sur la clean architecture - Symfony Live
Introduction au Domain Driven Design
Parlons App Economie : du dev à l'usage
La Gestion de Projet Mobile
Publicité

Plus de Publicis Sapient Engineering (20)

PDF
XebiCon'18 - L'algorithme de reconnaissance de formes par le cerveau humain
PDF
Xebicon'18 - IoT: From Edge to Cloud
PDF
XebiCon'18 - Modern Infrastructure
PDF
XebiCon'18 - La Web App d'aujourd'hui et de demain : état de l'art et bleedin...
PDF
XebiCon'18 - Des notebook pour le monitoring avec Zeppelin
PDF
XebiCon'18 - Event Sourcing et RGPD, incompatibles ?
PDF
XebiCon'18 - Boostez vos modèles avec du Deep Learning distribué
PDF
XebiCon'18 - Comment fausser l'interprétation de vos résultats avec des dataviz
PDF
XebiCon'18 - Le développeur dans la Pop Culture
PDF
XebiCon'18 - Sécuriser son API avec OpenID Connect
PDF
XebiCon'18 - Structuration du Temps et Dynamique de Groupes, Théorie organisa...
PDF
XebiCon'18 - Spark NLP, un an après
PDF
XebiCon'18 - Utiliser Hyperledger Fabric pour la création d'une blockchain pr...
PDF
XebiCon'18 - Ce que l'histoire du métro Parisien m'a enseigné sur la création...
PDF
XebiCon'18 - La guerre des Frameworks n'aura pas lieu
PDF
XebiCon'18 - Orchestration : Conteneurs vs Musique
PDF
XebiCon'18 - Passage à l'échelle de mes applications Kafka-Streams
PDF
XebiCon'18 - Data Science Done Wrong
PDF
TEch4Exec - OUI.sncf propose des voyages moins chers grâce au Big Data et au ...
PDF
Tech4Exec - Pourquoi faut-il gérer votre projet (Big) data comme une start-up...
XebiCon'18 - L'algorithme de reconnaissance de formes par le cerveau humain
Xebicon'18 - IoT: From Edge to Cloud
XebiCon'18 - Modern Infrastructure
XebiCon'18 - La Web App d'aujourd'hui et de demain : état de l'art et bleedin...
XebiCon'18 - Des notebook pour le monitoring avec Zeppelin
XebiCon'18 - Event Sourcing et RGPD, incompatibles ?
XebiCon'18 - Boostez vos modèles avec du Deep Learning distribué
XebiCon'18 - Comment fausser l'interprétation de vos résultats avec des dataviz
XebiCon'18 - Le développeur dans la Pop Culture
XebiCon'18 - Sécuriser son API avec OpenID Connect
XebiCon'18 - Structuration du Temps et Dynamique de Groupes, Théorie organisa...
XebiCon'18 - Spark NLP, un an après
XebiCon'18 - Utiliser Hyperledger Fabric pour la création d'une blockchain pr...
XebiCon'18 - Ce que l'histoire du métro Parisien m'a enseigné sur la création...
XebiCon'18 - La guerre des Frameworks n'aura pas lieu
XebiCon'18 - Orchestration : Conteneurs vs Musique
XebiCon'18 - Passage à l'échelle de mes applications Kafka-Streams
XebiCon'18 - Data Science Done Wrong
TEch4Exec - OUI.sncf propose des voyages moins chers grâce au Big Data et au ...
Tech4Exec - Pourquoi faut-il gérer votre projet (Big) data comme une start-up...

XebiCon'18 - Architecturer son application mobile pour la durabilité