Migration vers le patron
« Collection Pipeline »
en Objective-C
Mathieu Godart — @MonsieurDart
Jeudi 10 septembre 2015 @ CocoaHeads
L’INSPIRATION
• Martin Fowler
• Refactoring with Loops and Collection Pipelines



http://martinfowler.com/articles/refactoring-pipelines.html
• Many use cases in the article
• Here, only one case, translated into ObjC
L’IDÉE SOUS-JACENTE
• Traitement des collections d’objets :
• La boucle est la méthode la plus basique
• Mais ce n’est pas la seule : approche en « pipeline »
[Liste initiale] — fonction —> [Liste filtrée]
• Pas seulement pour la programmation fonctionnelle…
L’IDÉE SOUS-JACENTE
• ObjC (et Swift) possèdent ce qu’il faut pour ça :
• Lambdas : pour nous les blocs
• Bibliothèques : pour nous YOLOKit ou BlocksKit
BRIQUES DE BASE
• Les bibliothèques YOLOKit ou BlocksKit
• Fonctions de filtrage sur collections (NSArray, NSSet…)
• Autres fonctions de manipulation avec des blocs
• Chaînage des appels généralisé
CODE DE DÉPART
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
for (MGAuthor *a in authors) {
if ([a.company isEqual:company]) {
var handle = a.twitterHandle;
if (handle != null)

[result addObject:handle];
}
}
return [NSArray arrayWithArray:result];
}
CODE DE DÉPART
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
for (MGAuthor *a in authors) {
if ([a.company isEqual:company]) {
var handle = a.twitterHandle;
if (handle != null)

[result addObject:handle];
}
}
return [NSArray arrayWithArray:result];
}
VARIABLE TEMPORAIRE
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
NSArray *loopStart = authors;
for (MGAuthor *a in loopStart) {
if ([a.company isEqual:company]) {
var handle = a.twitterHandle;
if (handle != null)

[result addObject:handle];
}
}
return [NSArray arrayWithArray:result];
}
PREMIER FILTRAGE
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
NSArray *loopStart = authors
.select(^(MGAuthor *a){ return [a.company isEqual:company];});
for (MGAuthor *a in loopStart) {
if ([a.company isEqualToString:company]) {
var handle = a.twitterHandle;
if (handle != null)

[result addObject:handle];
}
}
return [NSArray arrayWithArray:result];
}
CE DONT ON A BESOIN
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
NSArray *loopStart = authors
.select(^(MGAuthor *a){ return [a.company isEqual:company]; })
.map(^(MGAuthor *a){ return a.twitterHandle; });
for (NSString *handle in loopStart) {
var handle = a.twitterHandle;
if (handle != null)

[result addObject:handle];
}
return [NSArray arrayWithArray:result];
}
CODE DE DÉPART
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
NSArray *loopStart = authors
.select(^(MGAuthor *a){ return [a.company isEqual:company]; })
.map(^(MGAuthor *a){ return a.twitterHandle; })
.select(^(NSString *h){ return h != null; });
for (NSString *handle in loopStart) {
if (handle != null)

[result addObject:handle];
}
return [NSArray arrayWithArray:result];
}
NETTOYAGE FINAL
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
return authors
.select(^(MGAuthor *a){ return [a.company isEqual:company]; })
.map(^(MGAuthor *a){ return a.twitterHandle; })
.select(^(NSString *h){ return h != null; });
for (NSString *handle in loopStart) {

[result addObject:handle];
}
return [NSArray arrayWithArray:result];
}
TA DA !
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
return authors
.select(^(MGAuthor *a){ return [a.company isEqual:company]; })
.map (^(MGAuthor *a){ return a.twitterHandle; })
.select(^(NSString *h){ return h != null; });
}
TA DA !
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
return authors
.select(^(MGAuthor *a){ return [a.company isEqual:company]; })
.map (^(MGAuthor *a){ return a.twitterHandle; })
.select(^(NSString *h){ return h != null; });
}
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
return authors
.select(^(MGAuthor *a){ return [a.company isEqual:company]; })
.map (^(MGAuthor *a){ return a.twitterHandle; })
.select(^(NSString *h){ return h != null; });
}
- (NSArray *)twitterHandles:(NSArray *)authors

forCompany:(NSString *)company

{
NSMutableArray *result = [NSMutableArray new];
for (MGAuthor *a in authors) {
if ([a.company isEqual:company]) {
var handle = a.twitterHandle;
if (handle != null) [result addObject:handle];
}
}
return [NSArray arrayWithArray:result];
}
ENCORE PLUS CONCIS EN SWIFT
-(阵列*)的⼿手:(阵列*)作者公司:(字符串*)公司 {
返回作家
。选择(^(作者* A){返回[公司是平等:公司];})
。地图(^(作者* A){返回⼀一个句柄;})
。选择(^(字符串* H){返回H =空;});
}
AUTRE FONCTIONS UTILES
• select, map, slice
• groupBy
• first, any, sort
• flatMap
• …
DU POUR ET DU CONTRE…
• Philosophie ou manière de penser différente
• Lourde barrière à l’entrée, mais peut s’avérer plus claire :
• À l’écriture, à la relecture et à la maintenance
• Favorise les variables immuables (immutable)
• Vous ouvre au fonctionnel… et au map-reduce
DES QUESTIONS ?
DES REMARQUES ?
DES AVIS ?
MERCI LES AMIS…
Mathieu Godart — @MonsieurDart
Jeudi 10 septembre 2015 @ CocoaHeads
Collection pipeline par  Mathieu Godart

Collection pipeline par Mathieu Godart

  • 1.
    Migration vers lepatron « Collection Pipeline » en Objective-C Mathieu Godart — @MonsieurDart Jeudi 10 septembre 2015 @ CocoaHeads
  • 2.
    L’INSPIRATION • Martin Fowler •Refactoring with Loops and Collection Pipelines
 
 http://martinfowler.com/articles/refactoring-pipelines.html • Many use cases in the article • Here, only one case, translated into ObjC
  • 3.
    L’IDÉE SOUS-JACENTE • Traitementdes collections d’objets : • La boucle est la méthode la plus basique • Mais ce n’est pas la seule : approche en « pipeline » [Liste initiale] — fonction —> [Liste filtrée] • Pas seulement pour la programmation fonctionnelle…
  • 4.
    L’IDÉE SOUS-JACENTE • ObjC(et Swift) possèdent ce qu’il faut pour ça : • Lambdas : pour nous les blocs • Bibliothèques : pour nous YOLOKit ou BlocksKit
  • 5.
    BRIQUES DE BASE •Les bibliothèques YOLOKit ou BlocksKit • Fonctions de filtrage sur collections (NSArray, NSSet…) • Autres fonctions de manipulation avec des blocs • Chaînage des appels généralisé
  • 6.
    CODE DE DÉPART -(NSArray *)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; for (MGAuthor *a in authors) { if ([a.company isEqual:company]) { var handle = a.twitterHandle; if (handle != null)
 [result addObject:handle]; } } return [NSArray arrayWithArray:result]; }
  • 7.
    CODE DE DÉPART -(NSArray *)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; for (MGAuthor *a in authors) { if ([a.company isEqual:company]) { var handle = a.twitterHandle; if (handle != null)
 [result addObject:handle]; } } return [NSArray arrayWithArray:result]; }
  • 8.
    VARIABLE TEMPORAIRE - (NSArray*)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; NSArray *loopStart = authors; for (MGAuthor *a in loopStart) { if ([a.company isEqual:company]) { var handle = a.twitterHandle; if (handle != null)
 [result addObject:handle]; } } return [NSArray arrayWithArray:result]; }
  • 9.
    PREMIER FILTRAGE - (NSArray*)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; NSArray *loopStart = authors .select(^(MGAuthor *a){ return [a.company isEqual:company];}); for (MGAuthor *a in loopStart) { if ([a.company isEqualToString:company]) { var handle = a.twitterHandle; if (handle != null)
 [result addObject:handle]; } } return [NSArray arrayWithArray:result]; }
  • 10.
    CE DONT ONA BESOIN - (NSArray *)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; NSArray *loopStart = authors .select(^(MGAuthor *a){ return [a.company isEqual:company]; }) .map(^(MGAuthor *a){ return a.twitterHandle; }); for (NSString *handle in loopStart) { var handle = a.twitterHandle; if (handle != null)
 [result addObject:handle]; } return [NSArray arrayWithArray:result]; }
  • 11.
    CODE DE DÉPART -(NSArray *)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; NSArray *loopStart = authors .select(^(MGAuthor *a){ return [a.company isEqual:company]; }) .map(^(MGAuthor *a){ return a.twitterHandle; }) .select(^(NSString *h){ return h != null; }); for (NSString *handle in loopStart) { if (handle != null)
 [result addObject:handle]; } return [NSArray arrayWithArray:result]; }
  • 12.
    NETTOYAGE FINAL - (NSArray*)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; return authors .select(^(MGAuthor *a){ return [a.company isEqual:company]; }) .map(^(MGAuthor *a){ return a.twitterHandle; }) .select(^(NSString *h){ return h != null; }); for (NSString *handle in loopStart) {
 [result addObject:handle]; } return [NSArray arrayWithArray:result]; }
  • 13.
    TA DA ! - (NSArray*)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { return authors .select(^(MGAuthor *a){ return [a.company isEqual:company]; }) .map (^(MGAuthor *a){ return a.twitterHandle; }) .select(^(NSString *h){ return h != null; }); }
  • 14.
    TA DA ! - (NSArray*)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { return authors .select(^(MGAuthor *a){ return [a.company isEqual:company]; }) .map (^(MGAuthor *a){ return a.twitterHandle; }) .select(^(NSString *h){ return h != null; }); }
  • 15.
    - (NSArray *)twitterHandles:(NSArray*)authors
 forCompany:(NSString *)company
 { return authors .select(^(MGAuthor *a){ return [a.company isEqual:company]; }) .map (^(MGAuthor *a){ return a.twitterHandle; }) .select(^(NSString *h){ return h != null; }); } - (NSArray *)twitterHandles:(NSArray *)authors
 forCompany:(NSString *)company
 { NSMutableArray *result = [NSMutableArray new]; for (MGAuthor *a in authors) { if ([a.company isEqual:company]) { var handle = a.twitterHandle; if (handle != null) [result addObject:handle]; } } return [NSArray arrayWithArray:result]; }
  • 16.
    ENCORE PLUS CONCISEN SWIFT -(阵列*)的⼿手:(阵列*)作者公司:(字符串*)公司 { 返回作家 。选择(^(作者* A){返回[公司是平等:公司];}) 。地图(^(作者* A){返回⼀一个句柄;}) 。选择(^(字符串* H){返回H =空;}); }
  • 17.
    AUTRE FONCTIONS UTILES •select, map, slice • groupBy • first, any, sort • flatMap • …
  • 18.
    DU POUR ETDU CONTRE… • Philosophie ou manière de penser différente • Lourde barrière à l’entrée, mais peut s’avérer plus claire : • À l’écriture, à la relecture et à la maintenance • Favorise les variables immuables (immutable) • Vous ouvre au fonctionnel… et au map-reduce
  • 19.
    DES QUESTIONS ? DESREMARQUES ? DES AVIS ?
  • 20.
    MERCI LES AMIS… MathieuGodart — @MonsieurDart Jeudi 10 septembre 2015 @ CocoaHeads