Objective C Style Guide – Guía de Estilo Objective C

Autor: | Última modificación: 22 de noviembre de 2022 | Tiempo de Lectura: 5 minutos
Temas en este post:

Esta guía de estilo está parcialmente basada en la de gitHub y en mi experiencia propia. Su objetivo es evitar grandes desvíos en estilo y fomentar buenas prácticas.

Clean code that works. — Ward Cunningham

Así que esta Objective C Style Guide se hace pública para que sirva de ayuda a otros equipos, a padawans que están empezando y generar polémica fomentar el intercambio de ideas.

Diseño

mandorla-carlos-balbas
La programación es ciencia y arte, y en ambas la belleza y elegancia son fundamentales. Mandorla II por Carlos Balbás.
  • KISS: Keep it Simple, Stupid.
  • Lo explícito es preferible a lo implícito.
  • El código claro es preferible al código «guay».
  • Si además, es elegante, mejor.
  • Si tu diseño es difícil de explicar, es por que es malo.
  • Tu código se va a leer mil veces y compilar unas pocas: la legibilidad es vital.
  • No extiendas si puedes delegar.
  • Ante la duda, plagia a Cocoa.
  • Usa la autodelegación para comportamiento por defecto.
  • Usa la expresiones literales para crear NSArray y NSDictionary.
  • No uses la nueva sintaxis de corchetes para indexar colecciones. Envía mensajes. Bastantes corchetes tenemos ya.
  • Para Apps universales, procura detectar el User Idiom al arrancar y configura la App para uno u otro, de manera que el resto del código cambie lo menos posible. Esto reduce la complejidad ciclomática del código y sigue el principio DRY.

MVC

Objective C Style Guide - Guía de Estilo Objective C
El «Orden en Casa» no es sólo una sección del Ikea.
Foto de Três Studio Decoración.

No hay atajos para el MVC, el MVC es el atajo. Be MVC, my friend. Síguelo a rajatabla.

UIViewController

No dejes que tus subclases de UIViewController se hagan excesivamente grandes. Si supera un tamaño razonable, refactoriza y saca funcionalidades a nuevas clases. Ni el Controlador es una God Class, ni MVC significa Massive View Controller.

Modelo y Código de Red

El código de acceso a red (sincronización y demás) NO debe de ir dentro del modelo, sino en un NetworkController. Ver comentario anterior.

Indentado

Usa tabulaciones, espacios, lo que sea, siempre y cuando seas coherente en un mismo proyecto. Una buena opción por defecto es la que implementa Xcode (espacios para el indentado y un «ancho» de 4).

Llaves

Objective C Style Guide
Mientras las uses siempre, ponlas donde te apetezca.

Usa llaves siempre, incluso en ifs y bucles de una sola linea. Esta medida defensiva impide que al añadir una nueva linea, el código deje de funcionar.

Por el nombre de Jobs, pon la llave inicial donde te salga de los corchetes. Eso sí, sé coherente en un mismo proyecto.

Propiedades y variables de instancia

  • Usa siempre propiedades, a no ser que tengas una muy buena razón para ello.
  • Para los modificadores de las propiedades, sigue los Mandamientos de la Propiedades, tal y como se explica en el curso.
  • Sólo usa @synthesize para aquellos casos en que es absolutamente indispensable.
  • Las variables de instancia siempre llevan un guión bajo como prefijo, por ejemplo _firstName.

Métodos de clase

Los métodos de clase que crean instancias, deben de devolver instancetype.

Constantes

Usa constantes de «estilo C»

// Header file
extern NSString *const AGTWidgetTurboMode;

// Implementation file
NSString * const AGTWidgetTurboMode = @"AGTWidgetTurboMode";

con el prefijo de clase seguido del nombre de la clase con la cual está asociada y el verbo apropiado.

Si prefieres, usa métodos de clase para las constantes, en la clase a la cual está asociada:

// In AGTWidget class
+(NSString *) turboMode{
    return @"AGTWidgetTurboMode";
}

Elige el que quieras y luego sé coherente en el proyecto.

No uses #define, si puedes usar cualquiera de las alternativas anteriores.

Nomenclatura

Objective C Style Guide - Guía de Estilo Objective C
La Nomenklatura sigue mandando, no te equivoques.

Prefijo de clases

Toda clase, y ficheros derivados como Xibs, lleva el prefijo AGT.

Ni que decir tiene, que si no trabajas para Agbo, NO uses AGT. Invéntate el tuyo, gracias.

  • Nombres de clase, variables, métodos, constantes, comentarios y commits a git se escriben siempre en Inglés. Sin excepciones.
  • Si un método necesita un comentario, es porque el nombre no es lo bastante largo y explícito. En serio.
  • Usa siempre el camelCase. Sin excepciones.

Notificaciones

Todos los métodos que responden a una notificación deben empezar con el prefijo notify, y llevar el nombre de la notificación como comentario. Por ejemplo:

// CharacterDidChange
-(void) notifyThatCharacterDidChange: (AGTStarWarsCharacter *) aCharacter;

Esto facilita enormemente buscar e identificar quién puñetas responde a una notificación en un proyecto complejo.

Delegados

  • Los nombres de protocolos de delegado serán siempre <nombre de la clase><delegate>.
  • Los nombres de los métodos de delegado seguirán el patrón did, will, should de Cocoa y pasan el remitente como primer parámetro.
  • Sin excepciones.

Categorías

  • Los nombres de las categorías  deben siempre indicar qué funcionalidad añaden.
  • Los nombres de los métodos deben de llevar siempre el prefijo de clase en minúsculas. Por ejemplo agtWrappedInNavigationController:
  • Esto nos protege en caso de que Apple en el futuro invente un método con ese mismo nombre (wrappedInNavigationController:).

 Constantes

Las constantes deben de empezar siempre por el prefijo de clase, por ejemplo AGT. No llames tus constantes con un prefijo k (kSoyUnaConstanteDelAnnoDelPedo). Es anticuado y da a entender que se trata de C y código de bajo nivel en general.

Nomenclatura Húngara

No uses la nomenclatura húngara en Objective C.

#define

Siempre en mayúsculas. Sin excepciones. Si puedes usar una constante normal y corriente, no uses un define.

Ficheros de Clases

Objective C Style Guide - Guía de Estilo Objective C
Tener clase no es opcional.

No pongas más de una clase por fichero, esto no es C++.

Fichero de cabecera

  • KISS: Keep it Simple, Stupid. Pon en él solo lo indispensable. Todo aquello que sea irrelevante para el usuario de la clase, debe de estar en una class extension en el fichero de implementación.
  • Sigue el orden @property, class methods, instance methods, empezando por los inicializadores.
  • Si usas ObjectiveC++, jamás podrá aparecer NADA de código C++ en el fichero de cabecera (esto «contaminaría» a todos los ficheros que lo importen).
  • Usa siempre que posible @class en vez de #import para tus propias clases.

Fichero de Implementación

Empieza con la class extension y luego el grupo @implementation.

Usa #pragma mark – para agrupar los métodos por su funcionalidad:

  • Life cycle (init, viewDidAppear, etc…)
  • Acciones
  • Propiedades (getters or setters personalizados)
  • Métodos de delegado
  • Handlers de notificaciones
  • Métodos «privados»
  • Métodos «públicos»
  • Etc…

Tipos y Enums

Objective C Style Guide - Guía de Estilo Objective C
Tipos de todos los tipos.
  • Usa siempre los typedef del sistema en vez del tipo «desnudo». Por ejemplo, NSInteger en vez de int, CGFloat en vez de float, BOOL en vez de bool, etc… Esto te protege cuando hay cambios en el tamaño de los tipos, como al pasar de 32 bits a 64 bits.
  • Usa NSEnum para las enumeraciones.

Personalización de UI

Objective C Style Guide - Guía de Estilo Objective C
Baccus, la App que se construye a lo largo del Curso Online de Programación iOS de Agbo

Usa siempre el proxy de Appearance en un método del AppDelegate (configureAppearance) y haz TODA la personalización ahí a no ser que resulte totalmente imposible. El código de personalización debe de estar centralizado en este único punto.

Librerías externas

Objective C Style Guide - Guía de Estilo Objective C
Las dependencias nunca han sido una buena idea…

No uses librerías externas mastodónticas (tipo AFNetworking) si sólo vas a usar una ínfima parte de las funcionalidades que aporta. En esos casos, examina el código que te interesa, entiende su funcionamiento y róbalo. En caso contrario estarás incorporando una enorme caja negra a tu proyecto y reduce tu comprensión del mismo. Para cajas negras, nos basta Cocoa.

No introduzcas dependencias externas innecesarias.

TDD

TDD by Darth Vader
Usa mal TDD y serás arrastrado al Lado Oscuro.

Con mesura. Como herramienta para diseñar sistemas complejos y de forma reactiva ante bugs. No te vuelvas loco y te dediques a testarlo todo. No harás otra cosa.

Core Data

Objective C Style Guide - Guía de Estilo Objective C
Una para persistirlos, otra para gestionar sus grafos, otra para deshacer sus cambios y una framework para dominarlos a todos.
  • Usa Core Data hasta para ir al baño.
  • Usa mogenerator para generar tus subclases de NSManagedObject.
  • Añade métodos de clase para crear instancias de tus subclases de NSManagedObject. Los objetos de Core Data deben de parecer objetos «normales» de Cocoa.
  • Usa KVO en vez de setters o getter personalizados en la subclases de NSManagedObject.

Macros

Objective C Style Guide - Guía de Estilo Objective C
«Dejad, los que aquí entrais, toda esperanza»
Dante Alighieri

No las uses jamás: interfieren el el code completion y dificultan la depuración.

Comunicación entre objetos

Objective C Style Guide - Guía de Estilo Objective C
¿Mande?

Usa siempre le mecanismo más sencillo posible: target action -> delegate -> notifications.

Bloques

Objective C Style Guide - Guía de Estilo Objective C
Bloques en Objective C: el mejor juguete que nos han regalado en años…

Oculta el código GCD puro y duro en métodos que reciben bloques como parámetros.

Usa los bloques para reducir la complejidad de tu código:

  1. eliminar delegados
  2. aplazar tareas
  3. abstraer código redundante y repetitivo.
  4. y más usos de bloques en Objective C

Cosas chachis y nuevas

Objective C Style Guide - Guía de Estilo Objective C
No es oro todo lo que reluce…
  1. Storyboards: NO. En serio.
  2. @import: espera hasta que se resuelvan los problemas actuales (por ejemplo con MapKit)
  3. Auto Layout: Opción por defecto. Solo uses el sistema anterior si absolutamente indispensable.