sábado, junio 23, 2018

Cibernética y lectoescritura como placer

Para mí —un programador de computadoras— es un deleite cada intento de poner por escrito mis pensamientos sobre lo que me interesa comunicar a una persona o, por otro lado, cada intento por controlar el comportamiento de una computadora al escribir líneas de código ejecutable. Escribir para procesadores basados en carbono (cerebros humanos) y escribir para procesadores basados en silicio (cerebros electrónicos: microprocesadores digitales) es algo muy delicioso para mí.

Ambas actividades tienen destinatarios muy diferentes. Aunque tienen en común un rasgo que las hace igualmente atractivas para mí: complejidad. En particular, un tipo de complejidad que no es accidental, sino que es parte inherente de su esencia. Pero no la esencia del acto de escribir, sino la esencia del destinatario hacia quien escribo. Una complejidad, por tanto, que no puede ser eliminada, tan sólo regulada o conducida.

En retrospectiva, fue hasta años después de haber terminado una carrera reglada por una institución académica que caí en cuenta de que el ejercicio de la cibernética –en un sentido amplio– es el nombre propio de lo me ha estado apasionando desde la adolescencia. Tal carrera tuvo la palabra “cibernética” en su título, aunque su contenido abarca muy muy poquito de cibernética —si se compara con el cuerpo de conocimiento científico actual sobre cibernética (en general, la comunicación y el control entre humanos, entre máquinas y entre sistemas complejos adaptativos diversos)—.

miércoles, julio 20, 2016

Abonar a la deuda técnica

¿Qué es «deuda técnica», de dónde proviene y cómo se puede gobernar?

Si regresamos a los básicos de diseño de software, entonces podemos constatar que «deuda técnica» no es algo nuevo sino una idea de moda para referir lo mismo que autores como Meilir Page-Jones y Larry Constantine decían desde hace tres décadas sobre cohesión y acoplamiento y sobre el costo incremental inherente al nivel de desorden (entropía) en un sistema. Si, además, regresamos a los básicos de la teoría general de sistemas (pensamiento sistémico aplicado en cibernética), entonces podemos constatar que la entropía no se puede evitar, solo administrar.

La «deuda técnica», en general, es el nivel de desorden en un sistema. Proviene de los cabos suelos presentes desde la definición de un problema hasta los cabos sueltos en los detalles de implementación de una posible solución.

¿Cuáles son las implicaciones de intentar ignorar la «deuda técnica» o de no gobernarla adecuadamente?

Un efecto típico de «deuda técnica» no gobernada es, entre otros, la decisión de descontinuar un sistema pues su costo de evolución se hace insostenible o porque su capacidad para ajustarse a nuevos requerimientos es demasiado pobre y costosa. Para un negocio basado en software ese efecto puede ser devastador. Por ejemplo, para la compañía Netscape Communications tal efecto contribuyó al declive de su producto comercial Netscape Navigator y, a fin de cuentas, a su bancarrota.

¿Cómo gobernar la «deuda técnica» en un sistema?

No dejar cabos sueltos desde la definición de un problema hasta la implementación de una posible solución. Uno de los cabos sueltos más frecuentemente ignorados es la administración de dependencias en un diseño de software; es decir, abandonar tal diseño a la tendencia natural hacia el espagueti (entropía). El gobierno de una «deuda técnica» incluye aplicar pagos o abonos constantes: esfuerzo explícito para administrar las dependencias en cada cambio al diseño en todos los niveles de abstracción involucrados en dicho cambio. Si no se abona a la deuda, ésta tan sólo crecerá.

Por supuesto, hacer un cambio a un diseño demanda contar con pruebas manuales y automatizadas pertinentes que ayuden a identificar el nivel de propagación de las consecuencias de dicho cambio.

En este contexto sugiero evaluar la siguiente aportación que recién publiqué. Se trata de un componente para administrar dependencias como medio para gobernar la deuda técnica en diseños de software que utilicen .NET Framework:

http://www.nuget.org/packages/TypeClassMapper/

Está basado en una idea básica de extensibilidad existente en Windows desde C++/COM/COM+ y también en .NET Framework. Dicho mecanismo sirve para concretar un patrón de diseño llamado Inversión de Dependencias o Inversión de control (Dependency Inversion Principle, DIP). El cual permite desacoplar por completo una interfaz de sus posibles implementaciones y ser enlazadas por separado en runtime por medio de configuración.

En años recientes muchos han empaquetado dicho principio en varias librerías. Algunas han cobrado alguna popularidad. Nunca he usado dichas librerías pues suelen agregar mucha funcionalidad que no necesito y que sólo las hace innecesariamente grandes; además de aumentar la complejidad del software que las usa.

Su documentación y ejemplos de uso están en el Project Site correspondiente.

Toda valoración crítica, reporte de defectos, solicitudes de funcionalidad, o de cambios, y contribuciones abiertas son bienvenidas.

sábado, diciembre 05, 2015

Una entrevista

¿Por qué escogí dedicarme a la programación de computadoras?

Para cuando tomé la decisión, en quinto de bachillerato, ya hacía unos tres años de haber escrito mi primer programa. Mis opciones fueron ingeniería electrónica (hardware) o ingeniería en sistemas computacionales (software). Decidí dedicarme a lo que ya era mi hobbie (pasatiempo) pues era algo que disfrutaba mucho y, además, era con lo que pronto conseguí mis primeras ganancias (escribí un programa para llevar la contabilidad básica de un negocio pequeño con una IBM PC y tal programa se vendió en repetidas ocasiones).

Programar una computadora para mí siempre ha sido sinónimo de diversión: la mayoría de mis primeros programas fueron juegos para mi propio disfrute. Además, la idea de que me pagaran por hacer lo que para mí es esparcimiento me sorprendió y no me desagradó.

¿Me ayudó en el campo laboral lo que me enseñaron durante la universidad?

Gran pregunta. En parte, sí, claro. Pero –ya se sabe– la pregunta clave es si yo aproveché las oportunidades a mi alcance en la universidad; es decir, lo que termina sirviendo de los sistemas escolares depende, en su mayor parte, del aprendiz, no de la institución. En otras palabras, lo que sirve es lo que aprendes por interés propio, no tanto lo que enseñan. Por supuesto, si en el camino uno se topa con una luminaria de maestro –caso esporádico en mi recorrido– entonces preguntar mucho es lo debido. Lo que sí tuvo una importancia capital es tener acceso sin restricción a todo el equipo de cómputo disponible en la institución: diversos tipos de computadoras y sus dispositivos periféricos, sistemas operativos, lenguajes, e incontables tomos de documentación de dichos sistemas. Me ofrecí de voluntario en el centro de cómputo de la escuela de ingeniería, me dieron copia de las llaves y todo el acceso sin restricción –aunque en alguna ocasión escribí un programa para conseguir la contraseña hacia un sistema que otros intentaron monopolizar, ¡los insulsos! (años después supe que ese tipo de programa le llaman “troyano”.)

Otro factor clave fue aprovechar el acervo bibliográfico disponible. Como sugiere Shelby Foote: «A university is just a group of buildings gathered around a library.» Una institución suele tener recursos para comprar ejemplares que no están al alcance de un joven aprendiz. Para mí, ahí encontré las bases de las que habla la gente, no en las aulas —el aula, en su mayor parte, es el espacio laboral del gremio magisterial; es decir, su objetivo es la enseñanza, no el aprendizaje, este último está principalmente en las manos del individuo con el gusto por indagar—. Sin embargo, cuando dicho acervo no fue suficiente, entonces averigüé en otros acervos: al no encontrar algún libro en la biblioteca de la universidad, entonces viajaba y pasaba horas en la biblioteca de ingeniería de la UNAM, en Ciudad Universitaria (por cierto, esa biblioteca también resultó ser una mina de oro).

No tardé en tomar conciencia de que el contenido académico oficial, para mi caso, era tan sólo una pequeña parcialidad del panorama teórico-práctico ya disponible. Este panorama, y no sólo aquella parcialidad, representa en realidad las bases de una profesión actual en cómputo. Por cierto, a decir del perfil teórico-práctico de los egresados que llegan a pedir trabajo hoy, sospecho que la misma toma de conciencia también se puede aplicar a muchos contenidos oficiales universitarios hoy en día. En cualquier caso es pertinente tomar nota de la respuesta de David Parnas ante la pregunta “What are the most exciting/promising software engineering ideas or techniques on the horizon?”: «I don’t think that the most promising ideas are on the horizon. They are already here and have been here for years but are not being used properly.»

¿Qué futuro veo para la carrera de tecnologías de información?

La revolución informática está en sus inicios, por lo que hay mucho por pensar y por practicar al respecto en diversidad de profesiones. En específico, las habilidades para programar computadoras y saber aplicar atinadamente las teorías del cómputo concurrente y distribuido para lograr sistemas confiables y robustos seguirán siendo habilidades y conocimientos muy importantes para la sociedad:

¿Por qué creo que son necesarias en la vida diaria las tecnologías de la información?

Los productos de la técnica informática abarcan más y más el territorio de lo cotidiano, y parece que tal tendencia continuará. Pero la aplicación técnica necesita enfocarse principalmente a resolver problemas reales en la sociedad, no sólo a crear necesidades artificiales que distraen nuestra atención hacia aquellos problemas. Por ejemplo, un problema real es el analfabetismo multifuncional de muchos de nosotros que con frecuencia no somos capaces de lograr una lectura básica de comprensión, ya sin mencionar una lectura crítica habitual (un epítome de tal analfabetismo se puede observar en algunos así llamados “líderes” políticos en posiciones de cabeza de gobierno de todo un país). Ya ni siquiera mencionar la habilidad de redactar claramente por escrito alguna idea relevante. Por otro lado, los productos de la técnica parecen avivar una info-adicción por la cual la atención cotidiana no parece estar en discutir temas relevantes en la sociedad sino sólo estar distraídos con los chismes del día a través de dispositivos electrónicos portátiles.

¿Cuánto tiempo tardé en encontrar trabajo después de egresar?

En mi caso, empecé a ejecutar proyectos de desarrollo de software como profesional pagado desde el segundo semestre de la carrera. He sido empleado y también me he desempeñado ofreciendo mis servicios profesionales con mi propia empresa de consultoría. Por fortuna, en general, no me han faltado proyectos de desarrollo de software, aunque en ocasiones tardan en concretarse pues busco ejecutar proyectos con un enfoque distinto al enfoque que tiene saturado al mercado.

¿Cuál es el salario que puede aspirarse?

El salario puede variar mucho pues depende de varios factores como la geografía, el tipo de mercado, el tipo de actividad profesional dentro las diversas áreas de tecnologías de información, el tipo de proyecto y su modelo de negocio, etc. La revista Software Gurú suele publicar estudios de salarios; por ejemplo: Estudio de Salarios 2014.

domingo, noviembre 08, 2015

¿Qué es redactar?

¿Cuán símil o disímil es redactar en un lenguaje natural, e.g., castellano o inglés, que redactar en un lenguaje artificial, e.g., Visual C# o Go?

Si redactar es la acción de ordenar ideas en nuestra mente con el propósito de ponerlas por escrito, entonces escribir software en un lenguaje de programación también implica redacción. Lo cual de igual forma implica que las habilidades para escribir mejor software están directamente relacionadas con las habilidades para redactar mejor.

Por supuesto, no es exactamente lo mismo redactar un texto narrativo que un texto argumentativo o uno descriptivo. Asimismo, no sería lo mismo redactar un texto expositivo que redactar un texto fuente como expresión de un diseño detallado de software (también conocido como «código fuente») pues cada tipo de texto asume un conjunto de expectativas diferentes por parte de su audiencia. Además, la redacción de software no sólo tiene por audiencia a procesadores basados en carbono (cerebros humanos), sino también a procesadores basados en silicio (cerebros electrónico-digitales).

Crear software es una actividad reciente en la historia de la humanidad con apenas aproximadamente 70 años de recorrido histórico. Un profesional de desarrollo de software requiere reflexionar sobre qué es esta actividad y cuáles tipos de habilidades se requieren para practicarla cada vez mejor. Desde 1968 se ha sugerido que podría ser una disciplina de ingeniería, y sí comparte ciertos atributos con ese grupo de disciplinas. Pero no sólo es eso sino que también comparte rasgos con otras disciplinas tanto puramente intelectuales como performativas –disciplinas que dependen de constantes ensayos para lograr un cierto nivel de calidad en su desempeño, el cual será necesario repetir en cada entrega.

Una disciplina puramente intelectual es, por ejemplo, la formulación matemática que sirve para explicar y predecir fenómenos físicos. Tal formulación se realiza una vez y si el resultado es correcto entonces puede ser utilizada posteriormente múltiples veces sin requerir el mismo tipo de esfuerzo intelectual que fue necesario para la formulación inicial. Por otro lado, el despliegue artístico coreográfico en un escenario requiere ser realizado con el mismo tipo de esfuerzo, cada vez. Crear software no-trivial requiere de una síntesis entre ambos tipos de disciplinas pues un proyecto para crear software no-trivial suele encontrarse en un escenario o contexto con oportunidades nuevas y restricciones distintas en cada ocasión.

sábado, septiembre 19, 2015

Pruebas unitarias como actividad de diseño

Hace ya como quince años que escribí una librería muy sencilla que llamé AutoTest. La escribí en Visual C# 1.0 y .NET Framework 1.0 por ahí entre 2000 y 2001. Me hizo falta pues en ese tiempo no supe de la existencia de ninguna librería para pruebas unitarias en .NET. Me hizo falta para diseñar software pues desde esa época ya estaba yo «infectado de pruebas». La infección, como a muchos otros diseñadores de software de aquella época, me ocurrió al exponerme a dos experiencias: (1) la lectura del artículo por Kent Beck y Erich Gamma con las palabras «Test infected» en el título, (2) la lectura y participación en las campales discusiones en la lista de distribución por correo electrónico de Object Technology User’s Group (OTUG) hospedada por la ya desaparecida Rational Corp. Discusiones donde personajes como Grady Booch, Kent Beck, Robert C. Martin, Steve Mellor, etc., polemizaban sobre métodos sistemáticos de análisis y diseño, sobre eXtreme Programming en general y Test-first programming en particular (ahora mejor conocida como Test-Driven Development, TDD), y sobre otras escuelas de pensamiento en diseño profesional de software.

AutoTest fue mi herramienta en ese tiempo para escribir pruebas unitarias a priori automatizas en .NET y con ello expresar varios tipos de expectativas de mis diseños. Expectativas que verificaba por demanda de manera ejecutable y automática. A esa técnica luego empecé a llamar: la realización de una «especificación funcional ejecutable».

Antes de AutoTest ya había ocurrido mi infección por escribir pruebas unitarias como un medio para diseñar software; es decir, a priori: no como validación y verificación de algo ya existente (a posteriori) sino como medio para empezar a pensar el diseño de la interfaz pública del software que aún no existe. Tiempo antes mi infección ya me había hecho tomar la versión CppUnit para Visual C++ de Michael Feathers —a su vez inspirada en la versión inicial de JUnit de Erich Gamma y Kent Beck— y adaptarla para el Borland C++Builder 4.0 de aquel 1999.

Con “contagio” o “infección” me refiero a que una vez que entendí y experimenté la técnica de diseñar software por medio de pruebas unitarias, entonces decidí de manera irrevocable que no había vuelta atrás pues me había topado con algo para lograr un siguiente nivel de calidad y profesionalismo en diseño de software. Además, el artículo «Test infected», ya mencionado, se refiere más o menos a esto mismo.

Olvidé que en ese tiempo había publicado una breve nota al respecto de AutoTest. La escribí antes de que existiera Blogger.com y en aquel entonces la publiqué en mi primer espacio en Internet: AutoTest - Unit testing framework.

En un proyecto personal en la actualidad salió el tema de los riesgos de confiar demasiado en herramientas que intentan “hacer todo por ti” y, por supuesto, salió a colación el manuscrito del Profesor Edsger Wybe Dijkstra donde mencionó algo al respecto. No tenía a la mano mi colección base de referencias, así que hice una búsqueda para localizar en Internet dicho manuscrito y en los resultados apareció mi nota de hace casi quince años.

viernes, junio 26, 2015

¿Más lenguajes de programación?

Así como se contempla un atractivo y alejado paraje al mismo tiempo que crece un vehemente anhelo de muchas y variadas vivencias en dicho paraje, así quisiera yo entender lo que Ludwig Wittgenstein quiso decir en la proposición 5.6 de su obra «Tractatus logico-philosophicus: Die Grenzen meiner Sprache bedeuten die Grenzen meiner Welt (los límites de mi lenguaje significan los límites de mi mundo).»

Quizá la enorme diversidad de formas de expresión humana sea un indicio de lo mucho que los humanos pretendemos expresar. Si es verdad que algunas formas de pensamiento filosófico sólo pueden ser expresadas a cabalidad en determinado lenguaje, entonces quizá eso sugiera algunas diferencias entre un espacio conceptual y un espacio lingüístico. Por ejemplo, la diferencia de amplitud; es decir, hay un número mucho mayor de conceptos en comparación con el número de palabras a la fecha para expresar todos esos conceptos. Otro ejemplo, la diferencia diacrónica; es decir, la precedencia en el tiempo del concepto –que ocurre por primera vez en alguna mente humana– con respecto a la expresión lingüística para dicho concepto –que surge como necesidad de expresar el concepto.

Me pregunto si algo así aplica para el caso de los lenguajes artificiales que aspiran a ser medio para expresar intenciones computacionales.

Quizá un lenguaje artificial usado para adiestrar a una computadora (o el adiestrado resulta ser uno mismo), en general, sería un medio para expresar una forma particular de computación digital en un determinado nivel de abstracción; digamos, no es lo mismo pensar CLR via C# que pensar Windows via C++ (como lo explica Jeffrey Richter), o no es lo mismo la actitud racional hacia el diseño de programas que alude Alexander Stepanov en su «From Mathematics to Generic Programming» que el énfasis visual de Scratch, ofrecido por MIT.

Entonces, por ejemplo, en el caso de Rust o de Go, o de muchos otros lenguajes de programación de computadoras, no veo otra más que conocer e intentar masticar las formas de expresión propias de un lenguaje artificial (o natural) para luego evaluar con cuál puedo expresar diferentes formas de computación. ¡Al parecer la diversión no termina, sino apenas empieza!

Por lo que sí tiene sentido preguntarse: What is code?