Date post: | 13-Jul-2015 |
Category: |
Software |
Upload: | idealistaimasd |
View: | 2,641 times |
Download: | 0 times |
Algunas claves
● Entendible● Extensible● Mantenible● Actitud● Refactorizar como parte del desarrollo● Programas pequeños
/¿qué es cream code?
Spaghetti Code
● Estructura compleja● Difícil de entender● Difícil de testear
/¿qué no es cream code?
Código duplicado
● Propenso a errores● Difícil de mantener● Oculta el propósito
del código
/¿qué no es cream code?
Código complejo
● Difícil de entender● Difícil de mantener● Propenso a errores
/¿qué no es cream code?
Métodos con responsabilidad múltiple
● Difícil de mantener● Difícil de entender● Código muy acoplado● Difícil de testear
/¿qué no es cream code?
Sin tests
● Código no probado● Errores difíciles de
localizar● Producto final “no
deseado”
/¿qué no es cream code?
Código de calidad
● Modularizado, Extensible● DRY (Don’t repeat yourself)● KISS (Keep It Simple, Stupid)● Con tests● S.O.L.I.D.
/si es cream code
S.O.L.I.D. (buenas prácticas)
● Responsabilidad única● Abierto a extensiones, cerrado a modificaciones● Clases derivadas no modifican comportamiento
de su clase base● Varias interfaces pequeñas es mejor que sólo
una grande● Uso de abstracciones
/si es cream code
Robert C. Martin
Potingue vergonzoso… /View Controller
● Difícil de entender● Difícil encontrar código● Difícil de modificar / extender● Difícil de mantener● Imposible de testear● Conflictos
View Controller cajón desastre
/View Controller/Responsabilidades
View Controller
Necesita saber lo que está pasando
Sabe qué hacer en cada momento
Eventos servidor
Interacción de usuario
Feedback de usuario
Modifica el modelo
Peticiones al servidorCambios del modelo
Necesitamos crema de la buena
● Adelgazar nuestros View Controllers● Inyección de dependencias● Testing (Unit testing, UI...)● Patrones de diseño● Libros y enlaces de interés
/Crema de la buena
Necesitamos crema de la buena
● View & View Controller● MVC● Model View View Model● Lógica de dominio● Data Sources● Lógica de Servicios● View Controller Containment
/View Controllers a dieta
● El controlador maneja una vista
● Sabe qué mostrar, no cómo mostrarlo
● La vista implementa los detalles de presentación (jerarquía, animaciones...)
View Controller
View
eventos de usuario
feedback
/View & View Controller
/MVVM
View ControllerViewView ModelNSDateFormatter
NSStringWithFormat...
Model
tiene
tiene actualiza
actualiza
/Lógica del dominio
@implementation PropertyViewController
- (void)loadPropertyPictures
{
self.pictures = [self.property getPictures];
}
@end
@implementation Property (Extension)
- (NSArray *)getPictures
{
NSString *strPredicate = @"type == %@";
NSPredicate *pred = [NSPredicate predicateWithFormat:formatString, @"
picture"];
return [[self.multimedias filteredSetUsingPredicate:pred] allObjects];
}
@end
View Controller
Property
getPictures
Property +Extension
/Data source
@implementation DataSource
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id cell = [tableView dequeueReusableCellWithIdentifier… forIndexPath:indexPath];
self.configureCellBlock(cell, [self itemAtIndexPath:indexPath]);
return cell;
}
- (NSObject *)itemAtIndexPath:(NSIndexPath *)indexPath
{
return self.items[indexPath.row];
}
Table View Controller
Table View
Data Source
● El VC no debe contener lógica de Web Services
● El controlador no sabe de dónde salen los objetos
● La obtención de objetos debe ser asíncrona
● Se comunicará a través de delegados, notificaciones o bloques
/Web Service
View Controller
Service
getObjects
● Disponible a partir de iOS 5● [VC1.view addSubView:VC2.view] ???
● viewWillAppear, rotaciones…
● Nuevos métodos● addChildViewController● didMoveToParentViewController● removeFromParentViewController
View Controller Containment
/Controller Containment
● El padre define las vistas contenedoras
● Los hijos son notificados cuando son añadidos
● El padre realiza las transiciones
● Los hijos deben tener sentido por sí mismos
View Controller Container
View Controller(Child)View Controller
(Child)
/Controller Containment
View Controller Container
View ControllerView Controller
View ControllerView Controller(Child)Child Delegate
crea
implementa
define
● Dependencia: A depende de B, cuando A necesita de B para hacer su trabajo
● Inyección: El objeto que usa A le dice a A quien es B
Inyección de dependencias
Necesitamos crema de la buena
● Inyección por constructor● Inyección de propiedades● Inyección en métodos● Extraer método y sobreescribir la
llamada
/Inyección de dependencias
@implementation Example
- (NSString *)getFormattedDate:(NSDate *)date{ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"es"]]; dateFormatter.dateFormat = @"dd MMM"; return [dateFormatter stringFromDate:date];}
@end
/Ejemplo
/Inyección por constructor
@interface Example ()@property(nonatomic, strong) NSDateFormatter *dateFormatter;@end
@implementation Example
- (instancetype)initWithDateFormatter:(NSDateFormatter *)dateFormatter{ self = [super init]; if (self) { _dateFormatter = dateFormatter; } return self;}
- (NSString *)getFormattedDate:(NSDate *)date{ return [self.dateFormatter stringFromDate:date];}
@end
/Inyección de propiedades
@interface Example ()@property(nonatomic, strong) NSDateFormatter *dateFormatter;@end
@implementation Example
- (NSDateFormatter *)dateFormatter{ if (!_dateFormatter) { _dateFormatter = [[NSDateFormatter alloc] init]; [_dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"es"]]; _dateFormatter.dateFormat = @"dd MMM"; } return _dateFormatter;}
- (NSString *)getFormattedDate:(NSDate *)date{ return [self.dateFormatter stringFromDate:date];}
@end
/Inyección en métodos
@implementation Example
- (NSString *)getFormattedDate:(NSDate *)date withDateFormatter:(NSDateFormatter *)dateFormatter{ return [dateFormatter stringFromDate:date];}
@end
/Extraer y sobreescribir
@interface Example ()
@property(nonatomic, strong) NSDateFormatter *dateFormatter;
@end
@implementation Example
- (NSString *)getFormattedDate:(NSDate *)date
{
return [[self dateFormatter] stringFromDate:date];
}
- (NSDateFormatter *)dateFormatter
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setLocale:[NSLocale localeWithLocaleIdentifier:@"
es"]];
df.dateFormat = @"dd MMM";
return df;
}
@end
@interface TestingExample : Example
@end
@implementation TestingExample
- (NSString *)getFormattedDate:(NSDate *)date
{
return [[self dateFormatter] stringFromDate:date];
}
- (NSDateFormatter *)dateFormatter
{
// Devuelve lo que quieras!!!
}
@end
● Test unitarios (XCTest, OCmockito)● Test de integración (KIF)● Test de aceptación (UIautomation)● Jenkins (Integración continua!!!)● Test manuales (QA)
/Testing
● Model View Controller● Model View View Model● Singleton (AppDelegate)● Delegado (@Protocol)● Observer (NSNotificationCenter, KVO...)● Command (NSInvocation)● Factory, state, decorator...
/Patrones
● www.objc.io● www.nshipster.com● www.raywenderlich.com● www.keyvanakbary.com● www.agbo.biz● www.ironhack.com
/Enlaces de interés
● Más legible● Fácil de modificar● Fácil de testear● Roles dentro del equipo● Menos conflictos● Y en general… más apetecible
El resultado
Gracias!!!jobs: www.idealista.com/creamcode
Javier Aznar de los Ríos@JaviAznar1
Enrique Fau de Casa Juana@kikefau