Category: Development

Resolviendo el error “literal-pointer@__OBJC@__cls” en XCode

Generalmente cuando uno es nuevo en el desarrollo de Mac empleado XCode/Cocoa se enfrenta a una seria de mensajes y errores poco comunes o que simplemente nunca habíamos visto. En un proyecto que estaba compilando en XCode casi al final de la compilación me salieron los siguientes errores:

“.objc_class_name_PTHotKey”, referenced from: literal-pointer@__OBJC@__cls_refs@PTHotKey in PomodoroController.o

“.objc_class_name_PTHotKeyCenter”, referenced from: literal-pointer@__OBJC@__cls_refs@PTHotKeyCenter in PomodoroController.o

ld: symbol(s) not found collect2: ld returned 1 exit status

simplemente WTF! parece una grosería del compilador!!

Después de pasar un muy buen rato investigando sobre este tipo de errores, que por equivocación se los atribuía al compilador, encontré en la ayuda de Apple y foros de que este error es ocasionado por el Linker al momento de ensamblar la aplicación y se debe a que en el código fuente se hace referencia a clases que no se encuentran incluidas en XCode, por ejemplo mediante #import, pero que probablemente físicamente existan en la ruta del proyecto pero no en XCode, por lo que no se encuentran los símbolos que requiere el Linker en el armado de la aplicación.

Por tanto la solución para esta situación es:

1. Agregar los archivos faltantes a XCode en la sección “Classes”.
2. En los “Targets” del proyecto agregar en “Compile Sources” los archivos faltantes agregado en el paso 1.
3. Aplicar un “Clean” / “Clean All Targets”.
4. Compilar la aplicación y listo!

Espero que este Tip sirva, ya que es poca la información que existe al respecto!

Acerca de las comunidades de desarrollo

Recientemente estuve organizando, con otros interesados en el tema, en revivir a una comunidad de desarrollo que últimamente estaba olvidada o nadie intentaba organizar algo interesante, durante este tiempo se cuestiono la dinámica que se buscaba en las reuniones, así como los temas que serían la base y elegir el lugar de reunión.

Durante este lapso pude darme cuenta de diferentes aspectos, al menos en mi caso me llamaron bastante mi atención:

a) Crear una comunidad requieren de convocar a personas con interes en común.
b) Es difícil encontrar personas dispuestas a invertir tiempo en la organización o que quieran participar.
c) Muchos se aburren rápidamente o pierden el interes sin proponer nada.
d) La más importantes: No sabemos participar o integrarnos a comunidades!.

Tomo el último punto para detallar mi perspectiva con respecto a las comunidades en nuestra cultura, una vez que me toco vivir lo que significa el crear una comunidad pude comprender muchas de las dificultades a las cuales toca enfrentarse y creo que muchas de las complicaciones son más de cultural que lo vuelve algo complicado y de mucha dedicación.

Primero en ocasiones (por no mencionar muy generalmente) se tiende a mal entender el propósito de las comunidades (cualquiera que sea el tema, en mi caso se refiero a las comunidades de desarrollo de software), muchas veces los asistentes solo logran sentirse atraídos solo si escuchan que por presentarse van a recibir regalos a cambio (comida, revistas, DVD, libros, etc), cuando el simple hecho de compartir conocimientos ya significa regalar algo!.

En otras ocasiones muchos van por “echar la fiesta” ó pasar un momento con los cuates, sin importar los temas a tratar y finalmente después de ir una o dos veces se olvidan o se aburren de la comunidad!.

Ante lo anterior me pregunto entonces: En verdad sabemos integrarnos a comunidades?

Si reviso la descripción de Comunidad en Wikipedia encuentro:

“Una comunidad es un grupo o conjunto de individuos, seres humanos, o de animales que comparten elementos en común, tales como un idioma, costumbres, valores, tareas, visión del mundo, edad, ubicación geográfica (un barrio por ejemplo), estatus social, roles. Por lo general en una comunidad se crea una identidad común, mediante la diferenciación de otros grupos…..”

Desde esa perspectiva, ¿Resulta importante reservarse el derecho sobre quienes deberían de integrar una comunidad? a fin de que los integrantes compartan los mismo intereses en común y preservar su identidad?.

Incluso si revisamos a nivel internacional, cuando alguien se muda a vivir a otro país se tiende a buscar comunidades de la misma nacionalidad en busca de apoyo, compañía y ayuda, entonces porque nosotros no sabemos integrarnos así?

Tratar de encontrar las razones llevaría a intentar analizar un sin fin de motivos (ideologías, cultura, personalidad, etc, etc, etc….), más a pesar de lo anterior no me desanimo en conformar una, yo creo que aunque se cuente únicamente con 3 personas, significa un avance siempre y cuando sea uno constante, no tanto un compromiso pero si disposición y creo que un mucho de vocación por enseñar!, así que si alguien pretende pertenecer a una comunidad de desarrollo le recomiendo lo siguiente:

1. Disposición a participar.
2. Invertir tiempo personal en aprender (muy importante!).
3. Proponer y cuestionar, proporcionar retroalimentación.
4. No esperar regalos a cambio!.

Creo que es importante procurar ser participativos, buscar compartir el saber y no ser celosos de nuestros conocimientos, siempre va a existir alguien que le interese lo que sabemos o que le sirva para solucionar algún problema.

Hacer Unit Test != Aplicar TDD

Cada nuevo proyecto involucra el tener que interactuar con nuevos grupos de trabajo, nuevas personas y nuevos retos, pero recientemente algo que me ha  llamado mucho la atención es el hecho de que varias personas dicen conocer acerca de ciertas metodologías de desarrollo de software, no es que yo me considere una eminencia en todas las materias, pero si cuando no tengo mucha idea sobre un tema, primero escucho y después investigo de que trata.

Volviendo al inicio (“bottom line”), en una reciente plática con un equipo de trabajo, se estaba discutiendo el tema de las pruebas unitarias y el cómo se van a emplear en el proyecto, algunos mencionaron que nunca las habían empleado, otros habían solo leído o escuchado sobre de ellas y otros decían que tenían amplia experiencia y que incluso habían aplicado TDD (Test-Driven Development)…interesante punto!

Cuando les pedía a los que “habían” empleado TDD comentarán sobre sus experiencias y utilidad, surgieron los siguientes puntos:

-          Comentaban que su tiempo de implementación alargaba en tiempo de desarrollo del proyecto.

-          Que se hacía complicado cumplir con las coberturas de código.

-          Al final terminaban haciendo muchas pruebas unitarias.

-          Que el IDE ya generaba automáticamente las pruebas y aplicaba el TDD…..?

Después de escuchar los comentarios no pude evitar comentar: hacer pruebas unitarias NO es aplicar TDD!, decirle a un Wizard que tome nuestros componente y automáticamente genere las pruebas unitarias NO es TDD!. Muchas veces no se logran comprender los verdaderos beneficios (o desventajas) de aplicar tal o cual práctica ó nos mal acostumbramos al flujo de trabajo que sigue cierta herramienta y creemos que así es como esta se aplica (todo gracias a la mercadotecnia!).

TDD es una práctica que se encuentra enfocada en aplicar dos principios básicos: Escribir primero las pruebas unitarias  y Refactoring de código. Para la definición de las pruebas unitarias se requiere tener claramente definidos los requerimientos (punto importante!), y una vez que se tengan claros aplicar los siguientes puntos:

a)      Tomar un requerimiento (con su respectivo caso de uso) que sea factible de iniciar su implementación o que sea más representativo.

b)      Definir la prueba unitaria con un nombre que describe el requerimiento.

Ejemplo:  IniciarSesiónConTokenDeSeguridadTest().

c)       Verificar que la prueba falla, se supone que en un principio esta se encuentra vacía y no tiene código.

d)      Implementar la prueba unitaria, es decir empezar a codificar a fin de realizar la implementación que cumpla con el propósito de la prueba unitaria.

e)      Ejecutar la prueba unitaria y verificar que funcione.

f)       Aplicar refactoring del código a fin de eliminar redundancias y reducir la implementación.

g)      Opcionalmente detectar posibles comportamientos que no se encontraban claramente especificados en el requerimiento implementado.

Revisando los puntos anteriores, el uso de este tipo de prácticas permite reducir la cantidad de errores y principalmente, permite al desarrollador confiar en su código al momento de la implementación de las pruebas unitarias, además de que las pruebas permiten mostrar el avance del trabajo y poder  demostrar escenarios de comportamiento que nuestros usuarios puedan revisar de forma simple.

Como toda práctica tiene sus ventajas y desventajas, por lo que su uso debe de estar condicionado a la experiencia de quienes lo van a implementar y se encuentren a gusto con trabajar de este modo. En mi caso lo he aplicado y me ha funcionado bastante bien, pero como siempre en gustos (y prácticas) se rompen géneros!

¿Qué valor aporta mi trabajo?

Durante la semana pasada el tema recurrente con el que me he visto involucrado es: ¿En verdad lo que estoy desarrollando genera algún valor?, ¿Cuánto tiempo va ser útil lo que se entregue del proyecto?

Lo anterior son una serie de preguntas que en la mayoría de los casos, toman relevancia en los momentos finales del proyecto,  en la entrega del resultado o más aun cuando nuestro cliente dice: “Esto que están entregando no es lo que esperábamos”, clásico pero muy cierto y recurrente.  

Casi siempre se tienda a caer en ambigüedades como querer emplear tecnologías “tan innovadoras” y “tan de moda” llenas de términos “rimbombantes” con tal de impresionar al cliente, es decir un típico escenario de proyecto  “buzzword compliance”: “Si implementamos SOA 2.0 vamos a apuntalar a los equipos de trabajo y capitalizaremos en valor de la empresa”, “Deberíamos subir nuestros servicios a la nube para así migrar todas las aplicaciones para que sean RIA al 100% y sean compatibles con Web 2.0“.

Otro escenario común es cuando en un proyecto nos asignan una pieza “compleja” un: “Generador  de notificaciones asíncronas mediante scheduler para ambiente mutithreading”, el cual debe de finalizarse el 2500 horas, donde dicha pieza fue definida en la etapa de arquitectura del proyecto por el “master architect” de soporte a pre-venta. Después de leer la especificación uno le indica al “manager”: Oye pero el requerimiento indica que el programa solo debe de mandar un correo al administrador cuando llegue un nuevo registro en la base de datos, que no basta con definir un job y ahorrarnos ese tiempo?….les parece familiar? o como decimos por acá, “para que tanto brinco estando el suelo tan parejo”.

Existen aspectos “primordiales”, antes de diseñar o codificar una pieza de software que es importante reflexionar:

a)      ¿Cuál es la finalidad del funcionamiento de esta pieza y quienes la van a utilizar?

b)      ¿Es necesario esta pieza dentro del “todo” del proyecto?

c)       ¿Están definidos y son claros los contratos de los componentes?

d)      ¿Es necesaria TODA la funcionalidad que estoy pensando implementar?

De tal forma que cuando se entregue nuestra pieza esta permita ser medida en función de los requerimientos e integración con los demás componentes, así como la funcionalidad comprendida sea única y estrictamente necesaria, recordar el YAGNI,  y de paso ahorrar tiempo de corregir nuestros errores, perdón mejor dicho “refactoring del código para mejorar performance” suena mejor.

En resumen es importante siempre entregar un resultado que al final genere un “valor” y que cumpla con las expectativas de nuestros usuarios o clientes finales, que los haga sentirse conformes con su inversión y lo consideren como algo “valioso” y “útil” o simplemente “vale la pena su costo”, es importante tener en cuenta que en términos de software es difícil cuantificar su valor.

.Net Unit Test: Realizar pruebas unitarias de clases internas

En algunos escenarios de implementación de .Net se hace uso de clases de tipo Internal, es decir clases que solo pueden ser accedidas por miembros del mismo ensamblado, por lo que al momento de definir las pruebas unitarias de nuestras clases, estas no pueden acceder a la definición de las clases internas debido a sus restricciones. Para solucionarlo se debe agregar el atributo InternalsVisibleTo en el archivo AssemblyInfo.cs del proyecto, de la siguiente forma:

//Se agrega el atributo en AssemblyInfo.cs
[assembly: InternalsVisibleTo("MyProjectTest")]

Para el caso en que el ensamblado se encuentre firmado, se debe de obtener la clave pública del archivo .snk con el que se realizó la firma, para obtener la clave se ejecuta la siguiente instrucción desde línea de comandos:

sn -tp myKeyFile.snk

en donde el resultado del comando pueder ser algo similar a:

Public key is

0021000004800000920000000602000000240000525341310004000001000100cfb8bc23b86a08
e70d021dd53d3b0293e716e71015870bdcc58a0231a4228618851a83e06077f5a44f42beb2baf3
56ad2d345521a96b0081ed0f25f9227523e3625eda524efe1cf2e1e5e41f3693a76ec52347684b
8129a4bb2d5fc49681adf33da0eecc4f81f011af4539d12abe1b4e760b5ce32d766db1012d4402
8381f0b7

Por último se agrega la información de la clave pública a la etiqueta InternalsVisibleTo, de la siguiente forma:

[assembly: InternalsVisibleTo("MyProjectTest, PublicKey =0021000004800000920000000602000000240000525341310004000001000100cfb8bc23b86a08
e70d021dd53d3b0293e716e71015870bdcc58a0231a4228618851a83e06077f5a44f42beb2baf3
56ad2d345521a96b0081ed0f25f9227523e3625eda524efe1cf2e1e5e41f3693a76ec52347684b
8129a4bb2d5fc49681adf33da0eecc4f81f011af4539d12abe1b4e760b5ce32d766db1012d4402
8381f0b7")]

Una vez finalido lo anterior ya se podrá realizar referencias a las clases internas desde el proyecto de pruebas definido en el atributo InternalsVisibleTo, bastante útil este atributo en mi caso me ha sacado de bastantes apuros.

Git on Windows

Reciente he empezado a emplear GIT como herramienta personal de control de versión en MacOSX, ya que considero que una de las buenas prácticas para realizar nuestro trabajo y aquellos proyectos de tipo personal, es siempre tratar de emplear una herramienta de Control de Versiones (nunca se sabe cuando el gato se comerá nuestro código).

Platicando con otros colegas sobre los diferentes herramientas de control de versiones  y GIT,  les intereso mucho el tema, hasta que  surgieron las siguientes preguntas : ¿Porqué cambiar Subversion?, ¿ Pero …funciona en MS Windows?…. interesante!

Primero mi intención no es decir cual es mejor que la otra, las dos son opciones bastante útiles y han demostrado su eficacia, así que más que basarse en recomendaciones, así como las metodologías, es cuestión de gustos!

Pasando a la segunda pregunta, en mis primeros días con Git recuerdo haber leído sobre algunos esfuerzos para emplearlo en SO Windows, y unos de los proyectos que más avance tiene en ese tema es msysgit, el cual permite proporcionar el ambiente necesario para la ejecución en MS Windows.

Por default Git proporciona una herramienta visual llamada Git GUI, pero es una versión bastante limitada y en ocasiones no “muy amigable de usar” y en ocasiones usar Git desde línea de comandos puede ser todo una “ciencia oscura”, por lo cual otra herramienta útil para cuestiones de integración con el SO y consulta visual es TortoiseGit, un versión basada en la excelente herramienta para Subversion TortoiseSVN.

Incluso he realizado pruebas de instalación y uso de las herramientas en Windows 7 y funcionan a la perfección, recomiendo a quienes les interese dar un “test-drive” con Git, una vez que lo conozcan seguro les agradará o al menos con el fin de conocerlo y criticarlo.

Applying agile methodologies: Software art

En esto días me he encontrado leyendo algunos artículos (Post1,Post2) de Marco Dorantes, en donde describe el desarrollo de software y las implicaciones de la adopción de metodologías agiles en los proyectos en los cuales trabajamos día con día y que al final terminan siendo todo MENOS AGILES!.

Desde mi perspectiva y experiencia, el éxito o fracaso de la adopción de metodologías agiles depende en gran grado de las cuestiones culturales o  ”costumbres, manías” que hayamos fomentado durante nuestra vida laboral y dado el “proceso de desarrollo de software“, que más que un proceso es un “arte“, a pesar de que mucho insistan en cuadrarlo con un proceso de producción o manufactura. Entonces ¿cómo alinear el proceso con una cuestión artística?  Existen variedad de metodologías y parte de sus mejores resultados en que los integrantes del equipo, implicados en el desarrollo (los “cerditos” como define Ken Schwaber),  partan de criterios comunes de confianza y compromiso de forma que todos tengan conciencia de que el adoptar la metodología A o B dependerá “solo de ellos” el éxito al final del camino, es como algo parecido en el futbol  independientemente de la estrategia de juego (4-4-2, 3-5-2), al final quienes ganan o pierden son los jugadores!.

Ahora en cuestiones de resultados, en mi caso ha funcionando perfectamente la combinación del uso de SCRUM, como proceso de control de la evolución de software y TDD como mecanismo de desarrollo y refactoring, al final resulta bastante ágil y permite mostrar resultados inmediatos así como reportar avance. Pero comento mucho depende de los gustos y afinidades, al final solo nuestro “arte” prevalecerá!.

Creación de Prototipos en Línea

Creo que el algún momento de los que nos dedicamos al desarrollo de aplicaciones hemos tenido que diseñar prototipos, muchas de las veces se empieza en papel o directamente sobre el designer del ambiente de desarrollo, en fin recientemente me tope con una excelente herramienta RIA llamada “Mockups”, la cual te permite realizar prototipos para aplicaciones tanto Web como de escritorio.

El bastante sencillo su uso y permite realizar bosquejos muy claros, así como importar o exportar el resultado en formato XML.

Otro punto importante es que se trata de una aplicación basada e Adobe AIR lo cual permite que sea multiplataforma.

Un ejemplo del resultado:
myImage-2.png

CocoaHeads México

Tal vez algunos conozcan el grupo de desarrollo cocoaheads el cual tiene como próposito principal discutir sobre temas relacionados con el framework de desarrollo de cocoa. No hace mucho se formo el grupo cocoaheads México por lo que para los que estan interesados en el desarrollo para Mac OSX y iPhone está es una muy buena opción para iniciarse.

Las fechas de las reuniones y lugar los pueden consultar en http://www.cocoaheads.org

Syntax Highlighter for WordPress

Durante este tiempo he estado buscando algún plug-in decente que me permitierá publicar ejemplos de codigo fuente en un post, despues de realizar algunas pruebas he decido usar SyntaxHighlighter Plus,y debo decir que es bastante comodo de usar y muy simple, realizando pruebas en varios navegadores.

Este es un ejemplo usando el plug-in en wordpress:

//ejemplo en C#
int x=Convert.ToInt32("1010");

//ejemplo en javascript
var someObject=document.getElementById("someId");

//ejemplo en Java
String someString=parameter.toString();

WordPress Themes