ObjectiveC


30
Oct 08

A vueltas con ObjectiveC

Sigo dándole vueltas al ObjectiveC, tengo que dejar atrás todos estos años de C++ y obligarme a pensar en ObjC para pillarle la esencia, la metodología para usar eficientemente este lenguaje.

Estaba dándole vueltas hoy a una técnica de optimización que se usa mucho en C++ llamada COW (Copy-on-write), o como la llama QT “Implicitly Shared Classes“. La esencia de esta técnica es que basándose en que una asignación de un objeto complejo ocupa tanto recursos de memoria como CPU, utiliza en lo posible copias compartidas (shared) en memoria y sólo se duplica la memoria del objeto cuando una instancia en concreto va a cambiar (va a escribirse en ella). Esta técnica no es propiedad exclusiva de C++, se usa tanto en memoria virtual de los sistemas operativos como en implementaciones de sistemas de ficheros (Ej. Ext3). En C++ los ejemplos clásicos son la clase “string” de la STL o los objetos de Qt. Se puede implementar fácilmente un objeto COW con un smart pointer, como la clase “auto_ptr” de la STL.

Toda esta discusión viene porque un smart pointer, como un “auto_ptr” es la forma que tiene C++ de atar, de encapsular el uso de la memoria para que, por una parte, no hayan errores con los punteros (memory leak) y por otra llevar un conteo de referencias para liberar la memoria cuando sea necesario (cuando ningún objeto “apunta” a un auto_ptr, éste libera la memoria automáticamente). Básicamente es un garbage collection, mejor bajo mi punto de vista. Con un auto_ptr sabes exactamente cuando se va a liberar la memoria: cuando el objeto pierde todas las referencias, ni antes ni después. Con un garbage collection como creo que usa C# y si no estoy equivocado también ObjectiveC, no tienes control sobre cuando se libera esa memoria. Usemos un ejemplo diferente, supongamos que el objeto que instanciamos usando un auto_ptr no es memoria, sino un recurso como un handle de fichero o un semáforo: a través de los constructores y destructores tenemos perfectamente controlado este recurso. Lo que quiero decir, y si algún “gurú” de ObjectiveC me lee por algún casual, es que me es extraño confiar en el mecanismo de [[obj alloc] init]  /  [obj dealloc]  para la construcción y destrucción de objetos.


20
Oct 08

Inicializando objetos en Cocoa

A vueltas con mi aprendizaje en ObjectiveC y la programación en Cocoa para iPhone, vuelvo a la carga con los “inicializadores”. Qué extraño me suena esto con respecto a C++.

En C++ todo es más “estático” en el sentido de que el mecanismo de construcción y destrucción forma parte del lenguaje: sabes exactamente cuando y como se llamarán a los constructores y destructores (inicializadores en terminología ObjectiveC). El puntero “this” existe siempre y es omnipresente, pero eso no parece ser el caso con ObjectiveC, en el que “self” es más manejable y voluble.

Por ejemplo, hay discusiones sobre cual es la mejor manera de inicializar un objeto, y por lo que puedo leer, tiene mucho más que ver que uses una librería (Foundation) u otra, como por ejemplo que los descendientes de NSManagedObject tengan siempre que asignar “self” mediante la llamada a [super init]. Esto también está relacionado con que se pueden instanciar clases, no sólo objetos con lo que se lía aún más la cosa…

Ya veremos si termino comprendiendo todo esto o tiro por la ventana todo lo relacionado con ObjectiveC… Keep in touch.


14
Oct 08

iPhone y la programación con ObjectiveC

Hacía muchos años que no veía ObjectiveC. Cuando digo muchos, digo muuuchos. :-) No me equivocaría si dijera que aún estaba en venta el NeXT…

Ahora he vuelto a verlo por el iPhone. La verdad es que es la primera vez que me acerco en serio a la programación para OSX. No me acordaba desde mis tiempos de universidad, y de eso ha llovido un poco. Lo más que me acuerdo es que era en C y con un Classic… cuando era actual, jajaja.

Odio la programación en ObjectiveC. Puedo comprender las razones de Apple por elegir un lenguaje así en su época, pero no para mantenerlo. Es cierto que usar C/C++ para programación de entornos de usuario hay malos ejemplos, aunque se puede hacer bien, o hacer muy bien. También podía haber hecho su propio lenguaje, o ampliar uno ya existente. Ya puestos, por qué no usar directamente SmallTalk.

Dejemoslo claro, esto es una opinión personal. Si alguien lee esto que es defensor a ultranza de ObjectiveC le daré la razón. Simplemente quiero decir que no se piense que es una opinión de “Newbe”, llevo programando en entornos de usuario desde que me compré el número 1 del MSJ (Microsoft System Journal).

De hecho, lo malo no es el entorno de desarrollo, el Xcode lo considero fenomenal, un entorno de desarrollo que ya quisiera en Windows. No. Lo malo es con el lenguaje.

En cuanto a la sintaxis es lo de menos, al final te acostumbras aunque duramente por tantos años llamando a las funciones.con().parentesis(). Lo malo de la sintaxis de ObjectiveC es justamente lo lioso de leer y de entender para los no iniciados. Te [puedes [perder facilmente:@"en la" [maraña init]]]

Para mi lo peor es que es un lenguaje orientado a objetos sobre uno que no lo es, como C. Aunque en ObjectiveC++ se pueden mezclar clases de C++ con ObjectiveC, esto no arregla el problema. Esta diferencia de conceptos ha llevado a un lenguaje que no tiene constructores y destructores, no tiene sobrecarga de operadores ni polimorfismo, entre otras cosas.

Ahora que hay más movimiento en la programación ObjectiveC por el iPhone, se oyen voces de programadores contra el sistema, y se necesitan posts como este simplemente para decir cómo se tiene que construir un puto objeto en cocoa! Simplemente esto no me parece serio, y voy a dar una razón que creo de peso: no es de recibo que un lenguaje orientado a objetos, por mucho recolector de basura que tenga, sea tan propenso a equivocaciones.

El ejemplo de los constructores. En ObjectiveC no hay constructores ni destructores. Punto. Los objetos se inicializan si el programador se acuerda de hacerlo. Todo esto sin contar que toda la jerarquía de objetos que estás construyendo depende de que tu llames a [objeto init]. Me suena a tremendo WTF!. Si hablamos de destructores, la cosa se complica. Es el programador el que tiene que llamar a “dealloc” para destruir un objeto. No, espera, ¿o mejor llamar a “release”? Mmhh… Depende. Es a estas cosas a las que me refiero, el lenguaje no permite una construcción robusta de librerías. No basta con poner en negrita en rojo con fondo fosforito en la documentación: “Llama al puto release cuando quieras liberarme”, es la clase la que debería asegurarse de liberar sus recursos.

Me recuerdo ahora un post que leí en un blog, no recuerdo el nombre si no lo pondría, que venía a decir algo así con respecto a los destructores:

“En ObjectiveC no hace falta destruir un objeto, normalmente es más sencillo y mejor que el sistema operativo libere la memoria cuando sale del programa, excepto si el objeto tiene recursos ocupados como ficheros abiertos.”.

En resumiendo venía a decir algo así. Para mi mente tan Stroustruptiana, simplemente no cabe en la cabeza que algún programador (quizás yo mismo) me deje recursos sin liberar. Llamalo memoria, en tal caso viene la basura y me la recoje, pero llámalo fichero abierto, llámalo socket conectado o peor aún, llámalo semáforo activo y verás el problema.

Este es uno de los posts que iré poniendo conforme vaya descubriendo ObjectiveC, quizá los siguientes sean más compasivos, pero mientras tanto, y si vas a escribir un comentario negativo, resuelve esta cuestión:

¿Cual es la forma más correcta de inicializar un objeto?

Forma número 1:

1
2
3
4
5
6
- (id)init {
    if ((self = [super init])) {
        // inicializar el objeto.
    }
    return self;
}

Forma número 2:

1
2
3
4
5
- (id)init {
    if (![self init]) return nil;
 
    // Inicializar el objeto
}