EL FIN DE UNA ERA: WinRAR dejará de vender licencias y se retirará del mercado en el 2017


Se cansaron de intentarlo. Burak Canboy, el CEO de WinRAR, ha anunciado hoy a través de medios oficiales, que en el 2017 interrumpirá la venta de licencias del conocido programa de compresión de archivos y será retirado del mercado.

En sentidas palabras, el directivo lamenta haber llegado al punto de verse forzado a tomar esta decisión: "No ha sido nada fácil, son 21 años en el desarrollo de este maravilloso software, pero creemos que ya es tiempo de dejarlo y dar paso a más innovadores proyectos que sobre todo, nos rindan utilidades".

Cuestionado por las principales razones de esta determinación, Canboy respondió: "Básicamente se debe a dos cosas; la primera, nadie a comprado una sola licencia desde el 10 de julio del 2015, nuestra última venta registrada. Estamos orgullosos de tener el software de PC más utilizado después de Microsoft Windows, pero nadie nos compra. Económicamente no es un buen modelo de negocio".

A esto agrega: "Nos esforzamos mucho en darle lo mejor a nuestros usuarios, incluso les dejamos utilizar WinRAR después de que el periodo de prueba de los 40 días haya caducado... Pero al parecer para ellos, no hacemos lo suficiente para que nos compren. Nuestros esfuerzos no son valorados".

El segundo motivo según Canboy, fue el hecho de ser el centro de burlas constantes en las redes sociales: "Cuando se hicieron públicos nuestros resultados históricos de ventas, fue devastador... Cuando salió a la luz que nuestra última venta en realidad fue un accidente porque nuestro cliente estaba ebrio, nos reventaron, no tuvieron piedad de nosotros... En efecto, todo ello fue verdad, pero nadie tenía por qué enterarse. Nunca pudimos superarlo".


Hoy se terminan 21 años de historia para una magnífica aplicación, y al igual que ustedes, aún no podemos asimilar esta terrible noticia. Sin más palabras, solamente nos queda decir: Hasta siempre, WinRAR.

NOTA: Hoy es 28 DE DICIEMBRE y falta casi nada para la llegada de un nuevo año, así que que aprovechamos la oportunidad para desearles lo mejor en este 2017 que se nos viene. Recuerden, es 28 DE DICIEMBRE, Día de los Inocentes, ¡día de leer todo con atención! A cuidarse de aquellos listillos que quieran sorprenderlos con imágenes o noticias falsas.

Las dificultades más comunes que enfrentan los programadores principiantes


Tan pronto como llegó a mí esta interrogante me puse a buscar un gran artículo que una vez leí sobre las cosas que nunca se le debe decir a un programador que recién está comenzando. No pude encontrarlo, pero lo más rescatable de éste era que a un programador principiante se le debe dar tiempo para hacer pequeños programas usando el lenguaje de programación que él mismo escoja. Desafortunadamente, en lugar de escuchar estímulos positivos, los programadores novatos comentan con frecuencia que les dicen que todo lo que hacen está mal: el lenguaje que escogieron, el editor que escogieron, el enfoque de su aprendizaje, etc. y que deberían haber hecho x, y ó z cosas.

Falta de confianza

Creo que la dificultad más común es la pérdida de confianza al principio del proceso de aprendizaje. En un mundo ideal más gente escribiría anécdotas divertidas acerca de sus muchos fracasos en la programación. Y no serían falsas ni las "típicas" historias de fracaso que solamente hacen que los novatos se sientan peor. La programación lleva tiempo y requiere perseverancia. Es una de las pocas áreas donde cometer errores es común y devastador. En un momento tienes un programa funcionando y al siguiente no tienes nada.

Duda sobre dedicar tiempo para aprender a utilizar un buen editor

Respecto a la segunda dificultad, puede sonar un poco extraño, pero se vincula al problema de la confianza. Si aprendes a adoptar un buen editor, te hará la vida más fácil y te ahorrará mucho tiempo, sin mencionar que se ve y se siente genial cuando realmente utilizas todos los atajos para guardar, tabular, comentar, ejecutar el código desde el editor en lugar de la línea de comandos, etc. Sin embargo, algunos estudiantes están tan abrumados con la sintaxis de sus códigos que se necesita tiempo para convencerlos de que explorar y conocer a fondo su editor vale cada minuto invertido en ello.

Ver los contratiempos como errores propios y no como eventos normales

La tercera dificultad es darse cuenta de que muchas cosas no funcionan predeterminadamente, en particular cuando se trata de instalar y usar paquetes/bibliotecas. Este último período tuve la oportunidad de enseñar un curso sobre programación de Python Intermedio. Podría haberme centrado en las estructuras de datos, pero en lugar de ello he tratado de centrarme en la resolución de problemas (tanto de software y hardware). Uno de los proyectos de la clase fue crear un programa Pygame. De los ochenta estudiantes, quizá un tercio fueron capaces de ejecutar el programa de demostración en su primer intento. El resto tenía una variedad de problemas que iban desde diferentes sistemas operativos hasta problemas en la instalación de paquetes. Un estudiante incluso tuvo que hacer un proyecto aparte porque nunca pudimos resolver todos sus problemas de instalación. Y eso está bien. Puede ser muy fortalecedor darse cuenta de que a veces cuando las cosas no funcionan, no es necesariamente por algo que hiciste mal.

Buscar el tipo equivocado de ayuda con preguntas

La cuarta dificultad tiene que ver con buscar ayuda. Recomiendo encarecidamente programar con un amigo, así como hacer el esfuerzo en evitar consultar inmediatamente código de otras personas para las tareas al principio del proceso de aprendizaje. Sé que es realmente difícil no ver otros códigos. Si estás pidiendo ayuda a otras personas, hazlo con lápiz y papel, no en frente de tu computadora o la de ellos. Para aprender a programar, es mejor hablar de tus problemas de perspectiva, no de líneas de código específicas.

Hay muchas otras maneras de caerse de los carriles (por ejemplo, no dedicar tiempo suficiente a un proyecto, programar para cumplir en lugar de programar para comprender, no seguir cuidadosamente las indicaciones, etc.). La mejor opción es crear un equipo de apoyo, trabajar juntos en una mismo lugar, ayudarse unos a otros con problemas de depuración e instalación, y recordar caminar de vez en cuando. Volver tras un pequeño descanso puede hacer una gran diferencia.

Vía | The Huffington Post

El estrés en los programadores está literalmente volviéndolos locos


Ser un programador en la actualidad, debe ser uno de los mejores empleos tanto en el aspecto monetario como en seguridad laboral, pero puede ser increíblemente dañino para la salud mental. Dos cosas están sucediendo que literalmente están volviendo locos a los programadores.

Lo primero es algo conocido como el síndrome del impostor. Esto ocurre cuando estás totalmente convencido de que todos los demás programadores con los que trabajas son más inteligentes, más talentosos y más habilidosos que tú. Vives con el miedo de que la gente descubrirá que tú en realidad eres un completo fraude y que tu inteligencia, tus habilidades o logros son simple apariencia.

Las mujeres programadoras confiesan frecuentemente que padecen el síndrome del impostor, y esto no es ninguna sorpresa. Este síndrome fue documentado por primera vez por los psicólogos Dr. Pauline Rose Clance y el Dr. Suzanne Imes como un problema particular de las mujeres exitosas. También es el tema central de una serie de libros de autoayuda orientados hacia las mujeres. Pero cada vez más programadores varones dicen sentirlo también.

Estas personas tienden a aplicar estándares extremadamente altos a sí mismos, pero no a los demás. El síndrome del impostor es común en las profesiones donde el trabajo es revisado por pares. Escribir software es tan sólo un campo de tantos, especialmente escribir software de código abierto donde cualquier persona puede ver el código y modificarlo.


Del 'Impostor' al 'Verdadero Programador'

La trampa del síndrome del impostor es que los programadores piensen que necesitan trabajar más para llegar a ser lo suficientemente buenos. Eso significa pasar más tiempo programando - todo el que sea posible - y asumir una cada vez mayor cantidad de proyectos.

Esa sensación se denomina el síndrome del verdadero programador, llamado asi a causa de un post que causó furor en Reddit. El verdadero programador vive sólo para programar. big_al11, autor del post, lo explica así:

¡Un verdadero programador es alguien que ama programar! Le encanta tanto que pasa todo su tiempo haciéndolo... El verdadero programador no lo considera realmente un "trabajo"...

Un programador no es un verdadero programador si no se ofrece a trabajar voluntariamente de 60 a 80 horas semanales (recuerda, sin compensación monetaria adicional) Simplemente, porque es "divertido"... Todo esto está arraigado en la cultura de esta industria.

Que de los programadores se espere que trabajen extenuantes largas horas no es algo nuevo. Pero la idea de que lo estén haciendo por su propia cuenta y gusto sí es nueva.

Por ejemplo, hace una década, durante la burbuja de Internet, un libro llamado "La Marcha de la Muerte" se convirtió en un best seller. Documentó cómo las excesivas horas de trabajo para los programadores los condujeron a problemas de salud. Se llegó a la conclusión de que la mala gestión de proyectos era la culpable.

En el 2004, programadores demandaron a Electronic Arts con respecto a sus horas extras y ganaron un acuerdo de $15 millones.

Años más tarde, en el 2010, se hizo viral la historia de una mujer casada con un programador que trabajaba para Rockstar Games. Se conoció cómo la empresa esperaba que sus programadores trabajaran 12 horas al día, 6 días a la semana durante meses o años, dañando la salud de algunos de ellos debido al estrés.

Para el 2011, el movimiento del verdadero programador ya estaba tomando fuerza. Ese año una discusión aparecida en la red social de programación StackExchange causó un revuelo tremendo, cuando un individuo preguntó: "Yo no programo en mi tiempo libre. ¿Esto me hace un mal desarrollador?"

La conclusión general fue que se puede ser un buen desarrollador si solamente se trabaja durante las horas normales de trabajo, pero que "los más grandes desarrolladores programan durante sus horas libres también".

Más no siempre es mejor

Esta idea tiene una validez cuestionable. Los estudiantes de Stanford calcularon cuánto tiempo una persona puede pasar programando de manera realmente productiva. Aunque no debería ser una sorpresa, determinaron que trabajar demasiado reduce la productividad. Los programadores con exceso de trabajo tendían a producir menos código de alta calidad, cuando trabajaban 60 horas por semana, en comparación a personal con poca carga de trabajo, cuando trabajaban 40 horas por semana.

Todo esto no ha impedido que el síndrome del Impostor/Verdadero Programador siga tomando fuerza. Y han habido algunas historias realmente tristes en el camino.

Por ejemplo, hace un año aproximadamente, el programador corporativo Kenneth Parker escribió un post en su blog, el cual tituló "Conocí a un programador que estaba completamente loco".

Hablaba de un compañero suyo que trabajaba tan duro, que tuvo "una crisis mental completa".

"Él era una de las personas que había visto trabajar más duro en esta industria. Con frecuencia se quedaba horas extras para trabajar en proyectos; siempre estaba disponible cuando gerencia necesitaba a alguien presto a trabajar todo el fin de semana... Su voluntad de esforzarse para hacer un trabajo es lo que más les gustaba. Sin embargo, su productividad no fue tan buena cuando fue a parar a un manicomio."

Recientemente, el ingeniero de software de New Relic, Nick Floyd, ha comenzado a escribir y hablar sobre algo que llama el Equilibrio de la Vida del Nerd. Después de confesar que una vez sufrió el síndrome del impostor, ahora cree que la felicidad del nerd se produce al encontrar un trabajo que ame realmente. Él escribe:

"Estar en New Relic es un desafío, duro y asombroso al mismo tiempo, pero nunca ha sido un trabajo para mí. Antes de unirme, había adoptado algunas creencias sobre que el trabajo siempre tenía que ser trabajo, que a menudo era frustrante, y que la vida era el escape de las frustraciones en el trabajo. ¡Pero era totalmente lo contrario! La vida es impresionante cuando esta cosa llamada 'trabajo' se convierte en otra manera de expresar las pasiones de tu vida."

Finalmente, el usuario de Reddit citado líneas arriba nos ofrece una conclusión al tema verdaderamente para enmarcar:

"Realmente deseo que viviéramos en una sociedad donde no nos definíéramos tan fuertemente por nuestros trabajos cotidianos y que donde trabajar hasta la muerte no fuese visto como una virtud."

Vía | Business Insider

Las computadoras, cada vez más cerca de dejar sin trabajo a los programadores


Es divertido imaginar el futuro de la inteligencia artificial (IA) con robots de servicio a domicilio, Dots de Amazon en cada habitación, drones de entrega y diagnósticos médicos más precisos sin salir de casa. Pero, si bien es natural que estas llamativas aplicaciones estén capturando la imaginación del público, existe una capacidad de la IA para transformar otra área que no recibe tanta atención: la posibilidad de que el software se desarrolle a sí mismo.

Imagínate lo que las computadoras podrían hacer si se comprendieran a sí mismas. Bueno, pronto lo harán. Y no estoy hablando de un futuro lejano; Estoy hablando de un futuro muy cercano, utilizando tecnología estándar que ya existe en la actualidad.

Hasta ahora, los expertos en aprendizaje automático han tendido a centrarse en aplicaciones de la IA altamente adaptadas a tareas específicas, como el reconocimiento facial, automóviles autodirigidos, reconocimiento de voz e incluso resultados de búsqueda en Internet. Pero ¿qué pasaría si esos mismos algoritmos pudieran entender su propia estructura de código -sin ayuda humana, interpretación o intervención- de la misma manera en que pueden reconocer y procesar el lenguaje humano y las imágenes?

Si el código empezara a analizarse a sí mismo, arreglando errores y mejorándose más rápido de lo que un humano podría hacerlo, los avances tecnológicos podrían ocurrir más y más rápido. Las posibilidades parecen infinitas: avances médicos, robots más accesibles, teléfonos más inteligentes, software con menos errores, menos fraude bancario, etc.

La inteligencia artificial tiene el potencial de resolver un viejo problema en el desarrollo de software. Si bien la capacidad del código de escribir o manipular otro código -un concepto conocido como metaprogramación- ha existido durante mucho tiempo (en realidad se originó a finales de los años cincuenta con Lisp), éste solamente puede abordar los problemas que un humano pueda imaginarse. Pero la IA puede cambiar eso.

Usando la IA, las computadoras podrían entender todo el código en el historial de un proyecto de software, mejorando y depurando líneas individuales de código en un instante, en cada lenguaje de programación concebible.

Incluso un programador inexperto o mediocre con una idea para una aplicación podría comenzar a describir la idea y la computadora podría construir la aplicación por sí misma. Esto podría significar la diferencia entre completar, por ejemplo, un proyecto de investigación sobre el cáncer en días o meses en lugar de años. Esto es un avance significativo.

Las tecnologías que eventualmente conducirán a estos dramáticos avances están en una etapa embrionaria al día de hoy, pero están empezando a salir de allí. Por ejemplo, el software de aprendizaje automático TensorFlow de Google permite a los desarrolladores crear funciones de redes neuronales directamente dentro de las aplicaciones, como la capacidad de reconocer personas y objetos en las fotos. Ya no necesitas un doctorado para trastear con estas ideas. Éste podría ser el avance más grande de la inteligencia artificial.

¿Crees aún que todo esto pertenece a un futuro muy lejano? Podrías sorprenderte al saber que las empresas ya están utilizando los conceptos de la IA en sus sistemas de gestión de proyectos internos, como Google, que construyó un programa de predicción de bugs que utiliza aprendizaje automático y análisis estadístico para determinar si un fragmento de código es potencialmente defectuoso o no. Ilya Grigorik, copresidenta del W3C, creó una versión de código abierto de esta herramienta llamada bugspots, que se ha descargado más de 20.000 veces.

Otro ejemplo es Viv, el sucesor de Siri. Viv no solamente hace reconocimiento de voz con un poco de procesamiento de lenguaje natural. Viv construye complejos programas de computadora adaptativos basados ​​en palabras inglesas. Código que escribe código. Debido a que el código escrito es preparado específicamente por los creadores de Viv, ésta no es una capacidad de escritura de código como la que estoy describiendo en este artículo, pero es un paso hacia esa dirección.

A medida que esta tecnología madure, las máquinas serán capaces de superar a los seres humanos en casi cualquier tarea: procesamiento visual, procesamiento de imágenes, juegos, y ahora también en la programación de otras computadoras.

Entonces, ¿por qué las computadoras no se entienden todavía? La respuesta es que solamente es cuestión de tiempo antes de que lo hagan. Y una vez que lo hagan, sólo se puede esperar ver los avances radicales en todos los campos donde el software es importante.

Vía | VentureBeat
Imagen | Ursa Major/Shutterstock

El Buscador de Código de GitHub, una verdadera mina de oro para los programadores


Aprender un nuevo lenguaje de programación o un framework puede a veces convertirse en un reto de mucha dificultad. El enfoque tradicional nos dice que debemos leer la documentación oficial, donde se explican todos los conceptos y donde podemos ver ejemplos sencillos. Por lo general esto es suficiente, pero hay algo de suma importancia que en la mayoría de casos no encontraremos en dicha documentación: ejemplos avanzados aplicados en proyectos de la vida real.

Al momento de toparse con un problema que no está contemplado dentro de la documentación, la mayoría de nosotros buscamos la solución en StackOverflow o buscamos en Google de mil maneras posibles hasta encontrar alguna pista. Sin embargo, suele ocurrir que, por ejemplo, la versión del lenguaje o framework en cuestión es demasiado reciente como para encontrar casos similares en StackOverflow, o que las búsquedas de Google arrojen pocos / ningún resultado a cada pregunta que se nos venga a la cabeza.

Casi con toda seguridad, te ha ocurrido que has estado atascado en un problema y te has dicho a ti mismo:

"¡Sé que alguien debe haber resuelto esto antes! ¿Por qué no hay ninguna solución en StackOverflow a este problema?"

Tienes razón, probablemente alguien en algún lugar del mundo ya lo ha resuelto. Y también es muy probable que dicha solución haya sido subida ya a GitHub. Ahora, solamente es cuestión de encontrarla. Motivados por la necesidad, los programadores tendemos más a resolver los problemas por nosotros mismos en lugar de preguntar a gente al azar en Internet.

Buscando código en GitHub

El buscador de GitHub es un medio que nos proporciona alternativas para consultar repos de varias maneras. Una de ellas es el buscador de código. Esta es una funcionalidad extremadamente poderosa. Cada línea de código escrita por cualquier persona puede ser encontrada con simples consultas. Lo "bueno" de GitHub es que los repos privados no son gratuitos, por lo que hay muchos proyectos implícitamente compartidos al público por personas que sólo quieren hacer una copia de seguridad de su código. ¡Esta es una mina de oro de información!

Ejemplos

A continuación algunos ejemplos donde muestro que el buscador de código de GitHub puede sernos de muchísima utilidad:

Aprendiendo una nueva API

Hace poco tuve la necesidad de usar Akka Streams para leer un enorme archivo y pasar resultados a otro archivo al instante. La documentación respecto a este tema es buena pero breve y debería tener más ejemplos.

Pero el buscador avanzado de GitHub vino al rescate. Después de unos cuantos clics encontré un pedazo impresionante de código que toma el archivo CSV, lo modifica y lo vuelca en otro archivo. ¡Justo lo que necesitaba!


Buscando proyectos que utilicen tecnologías de tu interés

Supongamos que deseas aprender Spring MVC, Hibernate y hacer testing con Spock. Puedes ir a la documentación de cada biblioteca, y aprenderlos uno por uno... o simplemente buscar un proyecto que los integre a todos ellos.

La mayoría de las plataformas tienen algún tipo de herramienta de administración de dependencias. En el caso de Java usualmente es Maven, que almacena todas la
información de dependencias en el archivo pom.xml.

Por lo tanto, puedes utilizar palabras clave y nombres de archivo para encontrar los proyectos que te interesan:

spring hibernate spock filename:pom.xml

Este método también es genial si estás buscando proyectos en los que quieres contribuir.



Integrando servicios externos

¿Estás buscando una forma rápida de integrarte con la API de GitHub usando tu lenguaje favorito? No hay problema, solamente busca los repos con la url de la API y filtra por lenguaje:

api.github.com language:scala


Configuraciones

Tampoco sería mala idea poder echar un vistazo a los archivos de configuración de proyectos grandes de la vida real, ¿verdad? Esto podría ser extremadamente útil, especialmente en el caso de utilizar frameworks con relativamente poca madurez.

Echemos un vistazo a cómo configurar el clúster akka. Dicha configuración debe contener la palabra clave ClusterActorRefProvider y residir en un archivo con extensión .conf (por lo general es application.conf):

ClusterActorRefProvider extension:conf


Conclusiones

El buscador de GitHub aún es muy poco valorado, pero ya hemos visto que es una herramienta extremadamente poderosa para aprender acerca de nuevas APIs, solucionar problemas y encontrar repos que te puedan interesar. Ésta es una manera genial de empezar rápidamente con nuevos frameworks, ¡encontrar fragmentos de código similares a lo que deseas programar nunca había sido tan fácil! También te hace sentir menos solo con los problemas que se te presentan, es muy probable que alguien ya los haya resuelto antes. De la misma manera, descubrir proyectos interesantes con este motor de búsqueda es sólo cuestión de minutos.

Vía | Jakub Dziworski
Imagen | GitHub

Mark Zuckerberg programó su propio Jarvis de Iron Man, la inteligencia artificial que ahora controla su casa


Mark Zuckerberg, CEO de Facebook, ha revelado lo que hace cuando no está al mando de una de las compañías más grandes de tecnología en el mundo - él escribe código. Específicamente este 2016, ha estado escribiendo código para un asistente virtual controlado por computadora que maneja cosas dentro de su casa como las luces y la música. Zuck le puso de nombre al asistente Jarvis, tal como el asistente de inteligencia artificial en la serie de películas de Iron Man.

"Mi desafío personal para el 2016 es construir una IA sencilla para hacer funcionar mi casa y ayudarme con mi trabajo. Puedes pensar en algo como Jarvis en Iron Man", anunció el multimillonario en un post de Facebook el 3 de enero último. "Voy a empezar explorando la tecnología que ya tenemos, luego comenzaré a enseñarle a entender mi voz para controlar todo en nuestra casa: música, luces, temperatura, etc."

Hoy, después de casi un año de trabajo, Zuckerberg ha revelado las proporciones de su creación. Funcionando por medio de una aplicación personalizada iOS que se parece mucho a Facebook Messenger, el Jarvis de Zuck puede reproducir música, encender y apagar su sistema de iluminación e incluso ver quién está en la puerta.


"Esto utiliza varias técnicas de inteligencia artificial, como por ejemplo procesamiento de lenguaje natural, reconocimiento de voz, reconocimiento de rostros y aprendizaje de refuerzo, está escrito en Python, PHP y Objective-C", explica Zuckerberg.


Antes de que pudiera dedicarse a elaborar la IA como tal, primero necesitaba escribir código para conectar estos sistemas, los cuales se comunican entre sí con diferentes lenguajes y protocolos. "Tuve que hacer ingeniería inversa de las APIs de algunos de ellos para llegar al punto en el que podría emitir un comando desde mi computadora para encender las luces o reproducir una canción. Además, la mayoría de los aparatos ni siquiera están conectados a Internet", comenta Mark.


Lo que se viene

Aunque el reto que él mismo se impuso para este 2016 ya esté cumplido, Zuckerberg aclara que no todo acabará aquí: "Estoy seguro de que voy a seguir mejorando Jarvis ya que lo uso todos los días y siempre estoy encontrando nuevas cosas que añadirle. A corto plazo, lo que sigue es hacer una aplicación para Android, colocar terminales de voz Jarvis en más habitaciones de la casa y conectar más aparatos domésticos. A más largo plazo, me gustaría profundizar en cómo enseñarle a Jarvis aprender nuevas habilidades por sí mismo, en lugar de tener que enseñarle cómo realizar tareas específicas".

Finalmente, Mark dice que con el tiempo sería interesante encontrar alguna forma de hacer esta tecnología disponible para todo el mundo. "Consideré en algún momento hacer este software de código abierto, pero actualmente todo está muy estrechamente vinculado a mi propia casa, mis aparatos y la configuración de mi red. Si alguna vez construyo una capa que abstraiga la funcionalidad de automatización de la casa, puedo liberar eso. Y por supuesto, esto podría ser una gran base para desarrollar un nuevo producto", concluye.

Vía | Mirror
Más información | Mark Zuckerberg

Los lenguajes de programación que tienes que aprender este 2017

A medida que la industria tecnológica continúa desarrollándose y creciendo, es importante saber cómo elegir un lenguaje de programación, cuál es la mejor manera de aprender este lenguaje y cómo esta elección puede afectar las  perspectivas de conseguir el trabajo adecuado. A lo largo de este artículo, vamos a tratar de averiguar cuáles son los lenguajes de programación preferidos por los programadores y lenguajes que son más demandados en la industria de TI.

C++, MATLAB y Java siempre han sido los favoritos para la enseñanza en instituciones educativas y la mayoría de los graduados egresan con amplio conocimiento sobre estos lenguajes. Pero ¿y si el lenguaje de programación que aprendieron no cubre exactamente las habilidades requeridas por la industria? ¿O qué pasa si dicho lenguaje se encuentra en declive?

Decidimos analizar datos de sitios web de índices de lenguajes y plataformas donde la mayoría de los desarrolladores perfeccionan sus habilidades de programación. También investigamos en portales globales como Indeed y Glassdoor para identificar los lenguajes de programación que las compañías tecnológicas están buscando.

El Índice TIOBE

El índice de la comunidad de programación TIOBE es una medida de popularidad de los lenguajes de programación, creada y mantenida por la empresa TIOBE, con sede en Eindhoven, Holanda. TIOBE significa "The Importance Of Being Earnest". TIOBE clasifica los lenguajes de programación en función del número de consultas en los motores de búsqueda que contienen el lenguaje como una palabra clave.

TIOBE indexa sólo los lenguajes Turing Completo, por lo tanto no son considerados SQL ni HTML. Según el índice de noviembre de 2016, Java sigue siendo el lenguaje más popular, C y C++ mantienen su popularidad en los índices de búsqueda con las posiciones 2 y 3, respectivamente. Sorprendentemente, Visual Basic y Python obtuvieron posiciones más altas en comparación con Javascript, y el lenguaje ensamblador se encuentra dentro del top 10.


GitHub

Antes de su conferencia anual en septiembre de 2016, Github compartió la lista de tendencias en lenguajes dentro de su plataforma. Fue sorprendente ver su escala con más de 19,4 millones de repositorios activos y más de 5,8 millones de usuarios activos en los últimos 12 meses. Sin embargo, no fue una gran sorpresa ver a Javascript encabezando dicha lista.


Lenguajes para aprender en el 2017

Mientras que Java y Javascript tal vez sigan siendo los favoritos de la industria con sus servicios basados ​​en la web, el futuro de GO de Google ha sido prometedor desde hace algunos años y será un gran lenguaje que aprender este año. Ruby sigue siendo el favorito entre las startups y no parece que su popularidad se vaya a reducir en el corto plazo.

Entre las tendencias para este año encontramos a RUST, un lenguaje de programación compilado, de propósito general y multiparadigma que está siendo desarrollado por Mozilla. Es un lenguaje de programación multiparadigma, esto quiere decir que puede soportar programación funcional pura, por procedimientos, imperativa y orientada a objetos.

Por otro lado, tenemos a Hack, un lenguaje de programación de alto nivel para la Máquina Virtual HipHop (HHVM), creado por Facebook como un dialecto del PHP. Hack permite a los programadores utilizar tanto tipado dinámico y tipados estáticos. A este tipo de sistema de tipos se le llama tipificación gradual.

Tanto RUST de Mozilla como HACK de Facebook (más del 90% del código de Facebook está escrito en él) están llamados a ser protagonistas durante este año y a futuro, sin embargo no se proyecta un gran impacto de estas tecnologías por lo menos dentro de la primera mitad del 2017.

Otros lenguajes de programación de los que se puede esperar un considerable crecimiento en el 2017 son:

• R - Con la creciente obsesión del mundo por las estadísticas y el análisis de datos, R es el lenguaje que necesitas para agregar a tu portafolio. No sería exagerado decir que R podría ser el lenguaje más buscado en el 2017 si tomamos en cuenta el creciente número de ofertas de empleo relacionados a R anunciados en los portales de trabajo.

• MATLAB - Siendo en otros tiempos un duro lenguaje para matemáticos y científicos, MATLAB ahora vuelve al escenario dado el creciente interés en la analítica y las estadísticas. Más desarrolladores están regresando a MATLAB conforme se incrementa la complejidad del análisis matemático en sus proyectos.

• SQL - A medida que más y más personas consumen tecnología a diario; las bases de datos aumentan exponencialmente. Si estás interesado en administrar bases de datos, SQL está hecho para ti. Se utiliza casi en todas partes donde se requiere administración de bases de datos. Aunque no es un lenguaje de programación como tal, SQL es un gran lenguaje para aprender durante los próximos años.

• Arduino - El Internet de las Cosas (IoT) vino para quedarse, y la programación de microcontroladores también será un factor clave en este aspecto. Arduino no se trata de un lenguaje nuevo; puesto que está conformado por un conjunto de funciones de C y C++. Sin embargo, con una cada vez mayor cantidad chips esperando a ser programados, aprender Arduino será una nueva habilidad que podemos desarrollar en el 2017.

• Swift - Cuando Apple, en respuesta a las quejas de los desarrolladores, decidió lanzar Swift para reemplazar a Objective-C, este lenguaje estaba destinado a ser uno de los favoritos entre los desarrolladores. Hoy por hoy, los desarrolladores de iOS están generando código tan rápido como en otros lenguajes más populares y ello se está viendo reflejado en su participación de mercado, el cual no para de crecer. Si las plataformas móviles y de escritorio de Apple te llaman la atención, entonces aprender Swift será una de tus mejores decisiones en el 2017.

Esto no significa que el resto de los lenguajes van a ser considerados "muertos" de cara al futuro o no tendrán ningún protagonismo en el 2017. Sólo significa que en general el viento podría soplar en otra dirección. Más vale estar preparados para lo que pueda suceder, ¿verdad?

Vía | ETtech

Diagramas de Casos de Uso

Un caso de uso es un resumen de un escenario particular, que describe la forma en que los elementos externos (usuarios u otros sistemas) interactúan con el software que se está modelando. UML permite crear diagramas para modelar casos de uso, que resultan de gran utilidad para documentar y para negociar con los usuarios y clientes sobre la funcionalidad que tendrá el software una vez implementado.

En los diagramas de caso de uso, intervienen actores y casos de uso. Los actores son cualquier elemento que puede interactuar con el software (usuarios, organiza- ciones o sistemas). Los casos de uso son secuencias de acciones que proveen al- gún tipo de valor para los actores. Los casos de uso se dibujan mediante óvalos con su nombre adentro, mientras que los actores se representan mediante hombreci- tos. Opcionalmente, puede dibujarse un rectángulo para indicar los límites del sistema y así dejar bien claro cuáles son las responsabilidades que se asumirán a la hora de la implementación (todo lo que está fuera de los límites, se asume que no será responsabilidad de los desarrolladores).

En la siguiente figura, se aprecia cómo el gerente de personal interactúa con el sistema de sueldos, tanto renovando contratos de personal como generando liquidaciones de sueldos. Además del gerente, un sistema que pertenece al estado interactúa con el sistema de sueldos solicitando el cálculo de los impuestos para controlar el estado impositivo de los empleados. Observemos también que un caso de uso no es independiente, sino que puede utilizar a otro para cumplir su tarea (representado en la figura como una línea que une Generar Liquidaciones con Calcular Impuestos).

 El diagrama de casos de uso especifica cómo se relaciona el sistema con el mundo exterior.

RECURSOS EN LA WEB En Internet hay una gran cantidad de información sobre UML, desde detalles básicos hasta ejemplos completos y de gran complejidad. Sin duda, el sitio de cabecera es el oficial de UML (en inglés): www.uml.org.
Otra página de gran interés, también en idioma inglés, que se puede visitar es Agile Modeling (www.agilemodeling.com/artifacts), que cuenta con una sección completa dedicada a diagramas y modelos UML.

CONCLUSIONES
A lo largo de esta entrega, vimos algunos de los diagramas que permite crear UML y su aplicación en el ciclo de vida del desarrollo de software, sobre todo para documentar las primeras etapas (análisis y diseño). Si bien, al ser visual, UML resulta bastante fácil de aprender, es recomendable familiarizarse primero con las técnicas y conceptos generales de la orientación a objetos y luego dedicarse a aprender UML, de manera de poder sacarle el mayor provecho posible a este poderoso lenguaje de modelado. También será imprescindible la lectura del libro UML Distilled, de Martin Fowler (traducido al español como  UML gota a gota).

Diagrama de Secuencia

Varias veces dijimos que la programación orientada a objetos se basa en la representación en software de los objetos que intervienen en el dominio de la aplicación junto con las relaciones e interacciones entre ellos. Mediante el diagrama de clases, UML permite especificar de manera estática las clases del modelo y sus relaciones. Para expresar la forma en que los objetos (no las clases) interactúan para llevar a cabo su objetivo dentro de la aplicación y solucionar un problema, UML provee el diagrama de secuencia, que permite especificar los mensajes que intercambian los objetos, el orden en que lo hacen y cómo reacciona cada objeto ante la llegada de un mensaje proveniente de otro.

ELEMENTOS DEL DIAGRAMA DE SECUENCIA

A diferencia del diagrama de clases, en el diagrama de secuencia intervienen instancias, es decir, objetos concretos que pertenecen a una determinada clase. Los ob- jetos se representan simplemente como rectángulos con su nombre y la clase a la que pertenecen dentro de él, separadas por dos puntos (:). En caso en que no inte- rese la identidad de una instancia en particular, se puede omitir el nombre, colo- cando sólo el nombre de la clase a la que pertenece, precedida por los dos puntos. Otro elemento de este diagrama son los mensajes. Desde el punto de vista de la implementación, podemos considerar los mensajes como invocación a métodos: cuando un objeto A envía un mensaje B a un objeto C, podemos traducir como que el objeto A invoca el método B del objeto C. Los mensajes se representan me- diante flechas simples, con el nombre del mensaje escrito sobre ellas.

Por último, dado que para representar una secuencia debemos especificar el or- den en que los mensajes son enviados, UML permite indicar una línea de tiem- po, que se coloca en el diagrama de manera vertical, y que consiste en una línea punteada por cada una de las instancias que intervienen en el diagrama.

Para entender cómo funciona el diagrama de secuencia, imaginemos que tene- mos que representar un escenario de matriculación de un alumno en un curso. Tenemos una clase Alumno, una clase Curso y una clase Facultad. La clase Facul- tad tiene la capacidad de determinar si un alumno puede inscribirse en un curso (porque conoce las correlatividades y las asignaturas aprobadas por el alumno). Cuando un alumno quiere inscribirse, hace la solicitud al curso (mediante un mensaje), y el curso consulta con la universidad si se cumplen las condiciones. Si todo está bien, el curso acepta la inscripción del alumno.

La siguiente figura representa este escenario mediante un diagrama de secuencia.

 El diagrama de secuencia muestra la interacción entre los objetos en un determinado escenario.

Como observamos en el diagrama, el objeto Alumno envía un mensaje SolicitarInscripcion al objeto Curso. Luego, éste envía un mensaje VerificarCorrelatividades al objeto de clase Universidad, quien contesta afirmativamente. Ante la llegada de la respuesta de la universidad, el objeto Curso le confirma la inscripción al objeto Alumno. Observemos que el tiempo corre hacia abajo, por lo que el orden en que aparece cada mensaje en el diagrama es cronológico.

En la Figura, hay algunos detalles que aún no mencionamos. Los mensajes de línea punteada corresponden a las respuestas de un objeto a un mensaje determinado. Los rectángulos delgados sobre las líneas de tiempo corresponden a instancias particulares, esto es, cada rectángulo en la línea de tiempo de un objeto corresponde a una instancia particular.

UML: Relaciones entre Clases

Las relaciones entre clases también están contempladas en UML, dado que, durante el diseño, es muy útil especificar claramente cualquier relación, que deberá ser traducida luego al código.

Composición
En UML, la composición se representa mediante una línea que une las dos clases, pero colocando un pequeño rombo del lado de la clase que se compone a partir de la otra. Opcionalmente, se puede indicar el nombre de la propiedad que representa la composición, pero no es muy habitual hacerlo, sobre todo en las etapas iniciales del análisis.

En la figura, vemos que una Escuela se compone de Aulas. Observemos los pequeños números debajo de la línea. Estos números indican la multiplicidad, es decir, cuántos elementos pueden existir de cada lado. El asterisco (*) indica muchos, sin especificar cuántos. Según esto, el diagrama deja bien claro que una escuela se compone de muchas aulas. Del mismo modo, si leemos la multiplicidad en sentido inverso, podemos entender que un aula está sólo en una escuela.

UML permite especificar la relación de composición, indicando además
cuántos elementos de una clase componen a la otra.

Además, sobre la línea que indica la relación, se puede colocar un texto aclaratorio sobre el tipo de composición. En el ejemplo, hemos especificado Posee como nombre de la relación. Si bien es opcional, el nombre de la relación ayuda mucho a la claridad del diagrama y a su posterior implementación en un lenguaje de programación.

Asociación simple
Anteriormente vimos que, si el tipo de dato de una propiedad es una clase, podemos escribirlo directamente o bien utilizar una relación de asociación. Hay una tercera opción que es usar ambos al mismo tiempo, pero no la veremos ahora.
La relación de asociación se representa de manera similar a la composición, pero sin utilizar el rombo; simplemente se coloca una línea entre las dos clases asociadas y una flecha que indica el sentido de la asociación. Al igual que en la composición, puede agregarse el nombre de la relación para aumentar la riqueza del modelo.

La relación de asociación es similar a la composición,
pero se utiliza una flecha para indicar el sentido de la relación.

PROGRAMACION Y DISEÑO Los conceptos introducidos por la POO como forma de trabajo, no sólo se aplican a la programación propiamente dicha, sino que también se puede hacer análisis orientado a objetos, y diseño orientado a objetos. UML está pensado para la creación de diagramas usando este paradigma.

Herencia
La relación de herencia también tiene su forma particular dentro del lenguaje UML. La representación de la herencia consiste en una flecha con la punta sin rellenar (en blanco). Lo más común es colocar las clases derivadas debajo de la clase base, de manera que la flecha que representa la herencia tenga sentido de abajo hacia arriba, generando un diagrama tipo árbol. Si la clase base es abstracta, se debe colocar el nombre con letra itálica (por ejemplo, Figura). Aunque parezca una obviedad (dada la definición de herencia) tengamos en cuenta que, en el diagrama de las clases derivadas, no es necesario volver a indicar las propiedades y los métodos heredados.

La herencia se representa mediante flechas sin relleno, apuntando hacia la clase base.

En el caso de las interfaces, UML prevé una forma de representarlas, como así también una notación especial para indicar la implementación de una interfaz por parte de una clase. Para indicar que se trata de una interfaz y no de una clase, en el diagrama de clases se debe colocar el indicador interfaz sobre el nombre, en la primera división del rectángulo que representa en este caso la interfaz. Además, si bien desde el punto de vista del polimorfismo la implementación de interfaces resulta similar a la herencia, no es lo mismo, por lo que UML hace la distinción correspondiente. Para especificar que una clase implementa una interfaz, se debe colocar una flecha de punta hueca apuntando hacia la interfaz, pero con línea punteada. En la Figura se aprecia una interfaz (IComunicador) y una clase, la que implementa (ComunicadorPorModem). Notemos que, a diferencia del diagrama de herencia, aquí sí debemos especificar en la clase todos los métodos y propiedades de la interfaz, ya que al aceptar el contrato que la interfaz nos impone, debemos implementarlo completamente (caso contrario ni el modelo ni el código serán válidos).

Al modelar la implementación de una interfaz, debemos volver a indicar
todas las propiedades y métodos en la clase que la implementa.

Diagrama de Clases

El diagrama de clases se utiliza para modelar las clases que intervienen en la solución, con sus propiedades, sus métodos y las relaciones entre ellas. Es un diagrama de tipo estático, en el sentido que modela entidades que se mantienen constantes durante la ejecución. Recordemos que las clases son fijas, y lo que varía son las instancias, o sea, los objetos.

El diagrama de clases resulta muy útil tanto para especificar los requerimientos como para documentar los detalles del diseño. Además, mediante técnicas de ingeniería directa, permite generar el código de las clases, no sólo la definición, si- no también las propiedades y el esqueleto de los métodos. Veremos a continuación las principales características del diagrama de clases, para empezar, cómo y cuándo utilizarlo.

CLASES
Las clases se representan mediante un rectángulo dividido horizontalmente en tres partes. En la primera parte, se coloca el nombre de la clase; en la segunda, las propiedades; y en la tercera, los métodos. Recordemos que UML es un lenguaje y, por lo tanto, debemos respetar sus nomenclaturas y estándares, o el modelo que definamos no será un diagrama UML válido.

En el diagrama de clases, cada una se representa mediante un rectángulo con el nombre de la clase en la parte superior.

De las tres partes, sólo es obligatorio el nombre de la clase en la primera; las otra dos pueden quedar vacías. Además, no es necesario especificar todas las propiedades y operaciones de la clase, sólo las que resultan útiles para el modelo.

Para darle más precisión al modelo, se puede especificar el tipo de dato de cada propiedad, separándolo del nombre de la propiedad con dos puntos (Nombre: String). Si el tipo de dato de una determinada propiedad es otra clase, estamos ante un caso de composición, que tiene una forma específica en UML (que veremos luego), sin embargo, en casos en que no haya lugar a dudas es posible indicarlo como si fuese un tipo de dato básico.

Si bien es un caso de composición, a veces, podemos usar clases como tipo de las propiedades.

Visibilidad
En UML, se puede especificar la visibilidad de cada elemento de una clase (propiedad o método). Si bien la visibilidad es algo más relacionado a la implementación en un lenguaje particular, es importante indicarla en el modelo de diseño, ya que permite dejar definidas ciertas normas de encapsulamiento que el analista o el diseñador detectan durante las primeras fases del proyecto. Si bien UML prevé notaciones para los tipos de alcance básicos, el lenguaje está abierto y permite utilizar modificadores propios del lenguaje que se utilice luego para la implementación.

La visibilidad se expresa mediante un signo a la izquierda del nombre de la propiedad o del método, y los utilizados son el signo más (+) para los elementos públicos, el signo menos (-) para los privados y el numeral (#) para los protegidos. Recordemos que los elementos protegidos sólo son visibles por la clase y por sus descendientes, mientras que los privados sólo son visibles dentro de la clase.

INGENIERÍA DIRECTA E INVERSA Cuando se habla de modelos y, sobre todo de UML, es muy común mencionar a la Ingeniería Directa y a la Ingeniería Inversa. Mediante la ingeniería directa, se puede generar el código fuente que implemente el modelo, mientras que, a través de la ingeniería inversa, se puede obtener un modelo completo o parcial a partir de código fuente ya escrito.

UML

Hemos visto distintas formas de expresar algoritmos, como el pseudocódigo y los diagramas de flujo. Estas herramientas resultan muy útiles, pero fueron pensadas para expresar procedimientos y, por lo tanto, tienen su aplicación más popular en la programación estructurada. Con la llegada de las técnicas de POO, se buscaron nuevas formas de expresar detalles
del problema por resolver ya que, en la programación orientada a objetos, sólo nos concentramos en los objetos del dominio y en los mensajes entre ellos.

¿QUÉ ES UML?

UML es la sigla de Unified Modeling Language, o Lenguaje Unificado de Modelado. Como su nombre lo indica, UML es un lenguaje. Pero no un lenguaje de programación como los que vimos durante todo el libro, sino uno de modelado: su propósito principal consiste en definir modelos. Por modelo, se entiende una representación simplificada de la realidad. Además, UML es un lenguaje visual, es decir, toda su expresividad se basa en gráficos.


El lenguaje UML nació en 1995 como resultado del trabajo en conjunto de Rumbaugh y Booch, dos investigadores en el área de Metodología, que comen- zaron a trabajar juntos en Racional, una compañía fundada por Booch. Luego se les sumó Jacobson, quien aportó más ideas para desarrollar lo que se convirtió en la primera versión de UML. Hasta entonces, se habían desarrollado unos cuantos mecanismos de modelado de software, pero como ninguno fue formalizado correctamente ni estandarizado, cada ingeniero de software los aplicaba como sa- bía y como le convenía. Esto trajo como consecuencia que los modelos desarrollados fueran incomprendidos por los programadores, perdiendo su efectividad y, por lo tanto, su utilidad. UML fue aprobado como un estándar, lo que lo con- vierte en una herramienta fundamental para los analistas, diseñadores y arquitectos de software, que necesitan transmitir a los programadores, de forma clara y precisa, los detalles del software por implementar.

UML consiste en un conjunto de diagramas de distintos tipos. Cada uno está destinado a cubrir alguno de los aspectos del software, y se pretende que con UML se puedan modelar absolutamente todos los elementos de una aplicación. Hay diagramas para modelar los objetos, sus interacciones, las interacciones del sistema con el mundo exterior (ya sean usuarios u otros sistemas). El objetivo principal de UML es el de proveer una herramienta de comunicación precisa y sin ambigüedades. En la actualidad, existen numerosas herramientas que no sólo ayudan a construir los diagramas en UML, sino que además permiten validar el modelo construido contra la especificación del lenguaje e incluso generar código sobre la base del modelo.

A lo largo de este apartado, estudiaremos los principales conceptos de algunos de los tipos de diagrama más importantes de UML y veremos cómo se relaciona con los conceptos de orientación a objetos que ya hemos aprendido.

Polimorfirsmo

El polimorfismo es una técnica que permite tratar a un objeto de una clase derivada como si fuese de la clase padre. Polimorfismo significa muchas formas, y justamente se usa este término, porque permite que una variable tenga múltiples formas. La definición misma de la relación de herencia brinda la posibilidad de contar con el polimorfismo, esto es, como una clase derivada es una clase base, siempre que necesitemos una clase base podremos usar una clase derivada. Por ejemplo, si tenemos un método que recibe un objeto de clase Figura, podremos pasarle un objeto de clase Rectángulo o de clase Círculo, ya que tanto el rectángulo como el círculo son figuras. Los lenguajes actuales permiten polimorfismo tanto por herencia como por implementación de interfaces.


La mayor utilidad del polimorfismo radica en que permite programar en un nivel de abstracción superior, ya que podemos especificar los contratos (es decir, qué esperamos en un método o propiedad) utilizando clases abstractas, interfaces o clases base de una gran jerarquía de herencia. Además, como veremos a continuación, mediante el polimorfismo, se logra el máximo nivel de extensibilidad del código, ya que permite encapsular las responsabilidades de los objetos dentro de los objetos mismos y desde afuera trabajar con su abstracción o clase base.

EARLY BINDING VS LATE BINDING El término Binding hace referencia al enlace entre el tipo de dato de una variable y el de su valor. Cuando el tipo de dato que tendrá un valor queda establecido en tiempo de codificación, se denomina EarlyBinding, mientras que cuando el tipo de dato real se conoce recién en tiempo de ejecución, hablamos de Late Binding (enlace tardío). Cuando se explota la técnica de polimorfismo, se usa siempre Late Binding, ya que una variable se declara de una clase, pero en ejecución puede ser de una clase derivada.

Para ilustrar la utilidad del polimorfismo, supongamos que tenemos que escribir un procedimiento que imprima la superficie de una figura, pero sin trabajar con orientación a objetos. Para hacerlo, necesitaremos conocer el tipo de figura y escribir una sentencia de tipo select case para calcular la superficie según el tipo de figura. Veamos algo de código (en C#).

switch(tipoFigura)
{
  case “Cuadrado”:
      Console.WriteLine(base*altura);
      break;
  case “Triangulo”:
      Console.WriteLine((base*altura)/2);
      break;
  case “Circulo”:
      Console.WriteLine(3.14*radio*radio);
      break;
}

El problema con esta porción de código reside en que, cuando agreguemos un nuevo tipo de figura, tendremos que agregar también el caso para hacer el cálculo correspondiente.

Si utilizamos objetos, podemos tener una clase abstracta Figura, con un método abstracto CalcularSuperficie() y sendas clases derivadas para modelar los distintos tipos de figuras. Cada clase derivada es responsable de redefinir el método CalcularSuperficie para adaptarlo a su fórmula de cálculo. De este modo, nues- tro procedimiento para imprimir la superficie se reduce a esto:

public void Imprimir(Figura f)
{
    Console.WriteLine(f.CalcularSuperficie())
}

Cuadrado c;
...
Imprimir( c ); // un cuadrado es una figura

Con esto, cuando necesitemos agregar un nuevo tipo de figura, bastará con escribir la clase correspondiente (heredando de Figura) e implementar el método CalcularSuperficie como corresponda, y no deberemos modificar el procedimiento de impresión.

La técnica de polimorfismo es un poco difícil de entender al comienzo, pero una vez asimilada se convierte en el arma más poderosa de la orientación a obje- tos. El secreto está en entender que, cuando codificamos la llamada a un método de una clase base, debemos tener presente que en ejecución se llamará al método correspondiente de una clase derivada.

LA MAGIA DEL POLIMORFISMO El polimorfismo abre las puertas a un nivel más de abstracción, en el que podemos escribir funcionalidad sin interesar mucho cómo se va a utilizar luego. Un ejemplo claro de esto es el manejo de secuencias de bytes en .Net. El Framework .Net posee una clase llamada Stream, que representa una secuencia de bytes. Luego, hay clases derivadas para leer y escribir de distintos medios, como archivos y llamadas http, y otros. Lo bueno es que muchos métodos reciben como parámetro un Stream, pero podemos pasarle lo que necesitemos. Éste es un claro ejemplo de Poli-
morfismo, con una aplicación práctica en el mundo real.

CONCLUSIONES

La programación orientada a objetos, bien usada, puede ayudarnos a construir software con las características más deseables por todo programador: facilidad de escritura, facilidad de mantenimiento, extensibilidad y reutilización de código. La extensibilidad es la clave para escribir aplicaciones altamente flexibles, ya que permite agregar o modificar comportamiento con muy poco esfuerzo. Es muy importante aprender algunos patrones de diseño e incorporar correctamente los conceptos de abstracción, encapsulamiento y polimorfismo, para no caer en el error de utilizar un lenguaje orientado a objetos para escribir código estructurado.

Tipos de Herencia

Hasta hora vimos ejemplos de herencia donde una clase derivada hereda sólo de una clase base. Sin embargo, en la práctica pueden presentarse casos en que una clase herede de más de una clase padre. Por ejemplo, imaginemos que tenemos una clase Empleado, con una propiedad Sueldo, y una clase Músico con una propiedad InstrumentoQueToca y queremos definir una clase EmpleadoDeOrquesta. Como los empleados de orquestas son músicos (tocan un instrumento) y además son empleados (perciben un sueldo), podemos heredar de ambas clases para reutilizar el código de cada una. Este tipo de herencia se denomina Herencia Múltiple.

HERENCIA MÚLTIPLE La mayoría de los lenguajes actuales no soportan herencia múltiple, ya que en general este tipo de herencia presenta más problemas que soluciones. Uno de los problemas de la herencia múltiple es cómo resolver casos en que un método o propiedad existe en más de una clase base, entonces, ¿cuál es el que recibe la clase derivada? Tanto los
lenguajes de .Net como Java no permiten herencia múltiple.

CLASES ABSTRACTAS
En el ejemplo de las figuras geométricas que vimos al comienzo, definimos una clase Figura con un método CalcularSuperficie. Ahora bien, esa clase, es una abstracción de todas las posibles figuras geométricas y, por lo tanto, no le podemos definir el cálculo de superficie, ya que depende de cada tipo de figura. Afortunadamente, para resolver cuestiones como ésta desde el diseño, tenemos la posibi- lidad de crear métodos abstractos: métodos que están declarados, pero que no tienen implementación. La implementación de un método abstracto queda rele- gada a las clases derivadas. Una clase que contiene al menos un método abstrac- to se denomina abstracta.

INTERFACES
Las interfaces son un derivado de las clases abstractas. En particular, una in- terfaz es esencialmente igual a una clase con todos sus métodos abstractos. Una clase que herede de una interfaz (en realidad para hablar correctamente debe- mos decir que la clase implementa una interfaz) está obligada a implementar todos sus métodos y propiedades. Las interfaces se utilizan para proveer una abstracción de algún comportamiento. Además, los lenguajes modernos como Java y los lenguajes de .Net permiten que una clase implemente varias interfaces, proveyendo así una especie de herencia múltiple.

Las interfaces permiten abstraer comportamientos y, a la vez, heredar de otra clase,
proveyendo un tipo de herencia múltiple.

CLASE ABSTRACTA O INTERFAZ Una decisión que muchas veces tendremos que tomar es si optar por una clase abstracta o por una interfaz. La diferencia radica en dos puntos: si usamos una clase abstracta, tendremos la posibilidad de escribir algo de código (métodos no abstractos), para no tener que escribirlo en cada clase descendiente. Con las interfaces, tendremos abierta la posibilidad de heredar de otra clase.

INSTANCIA En .Net, cuando definimos una variable que es una instancia de una clase, en realidad, lo que estamos guardando en la variable no es el objeto completo sino la dirección de memoria (en el HEAP) donde se encuentra el objeto. Cuando pasamos un parámetro por valor, lo hacemos por referencia, y cualquier modificación del parámetro, la haremos sobre el objeto original.

Redefinir Comportamiento y Extender Clases

Es muy común que una clase que hereda de otra no se comporte exactamente igual, aun para el comportamiento heredado. Veamos un ejemplo real: entre las herramientas que provee el Framework .Net para crear aplicaciones basadas en ventanas, tenemos clases para crear componentes visuales, como botones y listas. Supongamos que debemos crear botones, pero que sean redondos, y no rectangulares como los botones normales. Si no tuviéramos la herencia, deberíamos crear una clase BotonRedondo y escribir absolutamente todo el código. Sin embargo, podemos hacer que nuestra clase herede de la clase Button de .Net y redefina un método llamado OnPaint (que es el encargado de dibujar el botón en la pantalla) para dibujarlo como necesitamos. Tendremos así un nuevo tipo de botón que se dibuja como queremos, pero que posee todo el comportamiento y las propiedades de cualquier otro botón (por ejemplo, reacciona ante un clic con el ratón).

Una clase puede redefinir un método heredado para personalizarlo según su propio comportamiento.

EXTENDER CLASES

La extensión es un mecanismo para agregar comportamiento y propiedades a una clase, es decir, a todas las características que se heredan de la clase padre, se le agregan otras propias de la clase derivada. Por ejemplo, si tenemos una clase Persona y de ella derivamos una clase Empleado, podemos aplicar extensión agregando las propiedades Jefe y Sueldo. Si miramos este ejemplo pensando en la relación es-un, podemos decir que un Empleado es-una persona que además posee un sueldo y un jefe, es decir, es una extensión.

La extensión es una de las aplicaciones más utilizadas y naturales de la herencia, ya que sienta las bases de un buen diseño que derive en código claro, mantenible y robusto.

La extensión se puede combinar con la redefinición, para reutilizar aun más el código heredado. Esto es, podemos redefinir un método de manera tal que se comporte exactamente igual al método heredado del padre, pero que además haga algo extra. Volviendo al ejemplo del Botón, imaginemos que queremos hacer un botón tal que, cuando el cursor del ratón pase por encima, cambie de color. Deberemos entonces definir una nueva clase, que herede de Button y redefinir el método OnPaint, pero en vez de escribirlo todo desde cero, llamamos al método de la clase padre para dibujar el botón, y luego, si el cursor está sobre el rectángulo que comprende el botón, le cambiamos el color. ¡Nos vemos en la próxima entrega!

Herencia

La herencia es un tipo muy importante de relación entre objetos. En una relación de herencia, una clase recibe las propiedades y comportamiento de otra como si fuesen suyas y, al mismo tiempo, puede agregar las propias.

Veamos esto con un ejemplo. Supongamos que estamos desarrollando una aplicación que necesita hacer cálculos de superficie sobre distintas figuras geométricas, es decir, vamos a tener objetos como Círculo, Cuadrado, Trapecio, etcétera. Dado el requerimiento que tenemos, todos los objetos presentarán un comportamiento en común: calcular su superficie. Lo que podemos hacer entonces es definir una clase llamada Figura y establecer una relación de herencia entre esta clase y cada una de las figuras particulares. Le asignamos el método de cálculo de superficie a la clase Figura y, mediante la relación de herencia, las demás clases tendrán este comportamiento como heredado. Decimos entonces que las clases Cuadrado, Trapecio, etcétera, heredan de la clase Figura.

Así como el uso define una relación usa-a, y la composición define una relación se-compone-de, la herencia se conoce como una relación es-un. Siguiendo con el ejemplo de las figuras, decimos que un círculo es una figura, un cuadrado es una figura, y así con todos. Cuando una clase B hereda de una clase A, se dice que la clase A es la clase padre o clase base, y la clase B es la clase hija, heredera o deri- vada. En el ejemplo anterior, entonces, la clase Figura es la clase base, y las de- más, sus clases derivadas.

DISEÑAR PENSANDO EN OBJETOS La herencia tiene una gran potencia para escribir código reutilizable, flexible y mantenible. Por eso, durante el análisis del problema y durante el posterior diseño de las clases, se debe prestar especial atención a identificar relaciones de herencia para aprovechar sus virtudes. Conocer algunos patrones de diseño puede ayudar también a identificar relaciones de herencia, aun en clases no concretas.

La relación de herencia no se limita a un solo nivel, es decir, que una clase deriva- da de otra puede a su vez ser la base de una tercera clase, formando así una estructura jerárquica o de árbol. Además, en escenarios de múltiples niveles, la relación de herencia es transitiva, esto es, si una clase C hereda de B, que a su vez hereda de A, todo el comportamiento y las propiedades de A pertenecen también a C.

A partir del ejemplo anterior, podemos apreciar que la relación de herencia provee un mecanismo para lograr uno de los objetivos más importantes de la programación orientada a objetos, la reutilización de código. ¿Cómo se entiende esto? Supongamos que de la clase Figura hereda una clase Cuadrilátero, que tiene propiedades para representar la longitud de cada uno de los lados. Si de la clase Cuadrilátero derivan Rombo, Trapecio y Rectángulo, en estas nuevas clases ya no tendremos que escribir el código de la propiedad, es decir, hemos reutilizado código que ya estaba escrito.

Mediante la herencia, podemos definir una jerarquía de clases, donde cada clase derivada hereda el comportamiento y las propiedades de su clase base.

Además de la reutilización de código, la herencia provee otras aplicaciones útiles, como son la extensión y la redefinición de clases. Veamos de qué se trata, en nuestra próxima entrega.

Relaciones entre clases

En el mundo real, y dentro del contexto de una aplicación que debemos implementar, los objetos no están solos. Todo objeto se relaciona en cierta medida con alguno de los otros objetos (sea de la misma clase o no). En el ejemplo de alquiler de autos que estudiamos anteriormente, los clientes (que son objetos) se relacionan con los autos (que también son objetos) mediante la operación de alquiler. Del mismo modo, los formularios de alquiler se relacionan con los autos y con los clientes. Una buena regla adicional para la identificación de objetos a partir de un requerimiento es que, si un objeto no se relaciona con ningún otro, es probable que no sea necesario tenerlo en el sistema o deba ser revisado para ver si no nos faltó considerar algún aspecto del requerimiento.Un objeto puede relacionarse con otro de distintas maneras, como por ejemplo, enviándose mensajes entre sí. Durante el análisis, una vez que determinamos los objetos y definimos las clases, debemos prestar atención a las relaciones entre los objetos, ya que deberán ser modeladas para que luego se encuentren disponibles en ca- da instancia. Entre las relaciones más importantes, podemos mencionar: uso, agregación y herencia. Veamos las dos primeras ahora y dejemos la herencia para después, ya que es muy importante y merece un tratamiento aparte.

POO PURA Muchos puristas de la orientación a objetos sostienen que Smalltalk y Eiffel son de los pocos lenguajes
realmente orientados a objetos. El argumento se basa en que otros lenguajes (como los presentes en la plataforma .Net) poseen aún muchos conceptos de la programación estructurada (como por ejemplo las estructuras de control) y eso atenta
contra la definición formal de orientación a objetos.

RELACIÓN DE USO

En una relación de uso, un objeto A usa un objeto B, en el sentido de utilizar algún servicio provisto por B. En cualquier aplicación, es muy común encontrar que un objeto necesita algún servicio de otro, como pedirle que haga una deter- minada tarea. Si retomamos el ejemplo de la validación de tarjetas de crédito que vimos cuando tratamos el tema de los patrones, podemos observar que el objeto ValidadorTarjetaCredito brinda un servicio que alguien más, por ejemplo un objeto RegistradorDeAlquiler puede usar para completar su función. En la bibliografía de POO, se suele llamar relación Usa-A a la relación de uso.

Cuando un objeto A solicita una tarea a un objeto B, se dice que el objeto A usa el objeto B.

RELACIÓN DE AGREGACIÓN

Muchas veces, un objeto se compone de otros. Este tipo de relación se denomina agregación. En una relación de agregación entonces, un grupo de objetos (de la misma clase o de clases distintas) se agrupan para formar un objeto más complejo. Por ejemplo, un carrito de compras se compone de uno o más productos que el cliente ha comprado. Si bien los objetos producto son independientes, el objeto carrito necesita de ellos para existir. La relación de agregación puede ser recursiva, es decir, un objeto que está compuesto por otros, a su vez, puede ser parte de un objeto más grande, definiendo así una estructura jerárquica. Por ejemplo, una universidad puede estar compuesta de facultades, cada facultad se compone de departamentos, y cada departamento, de profesores y de alumnos.

Composición
La composición es un caso especial de agregación en el que los objetos agrega- dos a otro, sólo pertenecen a él. Por ejemplo, un automóvil está compuesto de un motor, un chasis, una carrocería y otros elementos, pero cada uno de ellos sólo puede pertenecer a ese auto. Un motor que está en un auto no puede estar en otro. La distinción entre agregación y composición depende directamente del problema por resolver y, en un buen modelo de objetos, debería reflejar exactamente la realidad.

En una relación de agregación, los objetos se agrupan para formar un objeto más complejo.

RELACIONES Desde el punto de vista de la implementación, tanto las relaciones de agregación como las de composición suelen representarse como propiedades o atributos de las clases agregadas o compuestas. Por ejemplo, la clase Carrito puede tener una propiedad que sea la lista de objetos de la clase Producto que ella contiene.

MÉTODOS Y PROPIEDADES DE CLASE Normalmente, los métodos y propiedades corresponden a cada instancia de una clase (a cada objeto). Sin embargo, muchas veces hay características que son comunes a todas las instancias. En estos casos, podemos definir métodos o propiedades compartidos, que pertenecen a la clase y se pueden invocar directamente sobre ella.

Pensar en Objetos

La forma de solucionar problemas utilizando técnicas de Orientación a Objetos es muy distinta de la forma tradicional o estructurada. Cuando nos presentan un requerimiento de una nueva aplicación y queremos emplear los conceptos de la Programación Orientada a Objetos, como primer paso nos concentraremos en identificar los objetos que intervienen en el problema. Deberemos, entonces, analizar cuidadosamente el requerimiento, hablar con los usuarios y prestar especial atención a los elementos que mencionan. Una técnica muy usada consiste en leer el requerimiento escrito (que deberá ser lo más claro y completo posible) y subrayar todos los sustantivos, tanto concretos como abstractos. Luego, de entre todos los sustantivos subrayados, descartamos aquellos que no son propios del problema por resolver. Una vez realizada esta primera actividad, habremos identificado una buena parte de los objetos del dominio de la aplicación.

Por ejemplo, imaginemos que necesitamos implementar una aplicación de alquiler de autos, y nos presentan el siguiente requerimiento (resumido): La empresa dispone de autos para alquilar a sus clientes. Cuando se alquila un auto, el cliente firma una póliza de seguro. En un formulario de alquiler, se registra la fecha, el nombre del cliente, el número de su registro de conductor y el número de tarjeta de crédito.

Si aplicamos la técnica de los sustantivos, podremos identificar rápidamente tres objetos fundamentales para la aplicación: auto, cliente y formulario de alquiler. Dependiendo del tipo de análisis y diseño que queramos hacer, podríamos considerar como objetos la tarjeta de crédito e, incluso, el alquiler.

Como decíamos al principio, los objetos poseen propiedades y comportamiento. Para identificar las propiedades aplicamos una técnica similar a la de los sustantivos, pero buscando cualidades o adjetivos de los objetos que ya hemos identificado. Siguiendo con el ejemplo del alquiler de autos, podemos ver que el formulario de alquiler tiene propiedades como la fecha, el nombre del cliente, etcétera.

Una vez que hemos identificado los objetos y sus propiedades, estamos en condiciones de definir clases para agruparlos y abstraer todas las posibles instancias de ellos. Hemos alcanzado así el fin de la primera etapa en el proceso de solución de problemas mediante técnicas de orientación a objetos.

Con las técnicas de análisis, identificamos los objetos del mundo real; luego abstraemos sus propiedades para agruparlos en clases.

TOMARLO CON CALMA
Muchas veces, no lograremos identificar con claridad todos los objetos en una primera lectura. Será necesario hacer una segunda pasada (incluso más) sobre el texto del requerimiento para encontrar objetos ocultos, despejar ambigüedades o
eliminar falsos objetos que no son esenciales para la solución concreta del problema.

PATRONES DE DISEÑO

Si bien el proceso de análisis y diseño orientado a objetos se centra en la identificación de los objetos propios del dominio del problema, a menudo es necesario crear objetos ficticios. Éstos colaboran con los objetos reales en la solución del problema o en proveer mecanismos de flexibilidad, extensibilidad o claridad del código, y ayudan a separar los intereses y responsabilidades de cada objeto. Un ejemplo muy común de estos escenarios son los requisitos no funcionales.

Para entender un poco mejor este aspecto, retomemos el ejemplo del sistema de alquiler de autos e imaginemos que se nos exige que el sistema valide la tarjeta de crédito, pero que además el código esté preparado para adaptar el sistema a nue vos mecanismos de validación. Una posible solución es definir una clase llamada ValidadorTarjetaCredito, con un método que reciba un número de tarjeta y un importe, y valide que se puede cobrar ese importe a esa tarjeta. Luego, utilizando la herencia y el polimorfismo (que veremos luego), se pueden crear nuevas clases que empleen diversos mecanismos de validación.

A lo largo de los años, los desarrolladores reconocieron que muchas de las solu- ciones que encontraban a los problemas no funcionales con orientación a objetos comenzaban a repetirse o tenían elementos en común y que, además, funcio- naban (es decir, cumplían su propósito). Actualmente, a estas soluciones proba- das a problemas comunes, se las llama patrones. Hay distintas clasificaciones de patrones según la familia de problemas que atacan, siendo los más comunes los denominados Patrones de diseño.

El principal objetivo de los Patrones de diseño es el de proveer un catálogo de elementos de diseño que ayuden a los programadores en su tarea diaria, evitando que tengan que buscar nuevas soluciones cada vez que se enfrentan con un problema común. Además, los Patrones de diseño facilitan la comunicación entre los programadores, como así también la comprensión del código escrito por otro. Obviamente, los patrones no pretenden eliminar el trabajo del desarrollador, ya que éste debe ser capaz de identificar las características de cada problema y tener un dominio de los principales patrones para asociarlos con el problema y aplicarlos.

LA BANDA DE LOS CUATRO
El tema de los patrones ha generado gran cantidad de bibliografía. Quizá el libro más popular a la hora de aprender sobre patrones es  Design Patterns. Elements of Reusable Object-Oriented Software . Los patrones que en él se presentan, se conocen como patrones GoF, sigla de  Gang of Four (la Banda de los Cuatro), en alusión a sus cuatro autores, autoridades absolutas en este ámbito (Gamma, Helm, Jonson y Vlissides).

Clases y Objetos

Cuando se analiza un problema para resolverlo mediante las técnicas de programación estructurada, nos enfocamos en identificar los datos que debemos manipular y las transformaciones que sufren como parte de la solución. Con el paradigma de orientación a objetos, la tarea de análisis se centrará en la identificación de objetos, de sus características y de cómo se relacionan entre sí para resolver el problema. Ya dentro del contexto formal de la teoría de Orientación a Objetos, podemos definir un objeto (parafraseando la definición de James Rumbaugh) como un concepto, abstracción o elemento con significado claro dentro del problema en cuestión (por ejemplo, un empleado). Como tal, un objeto se caracteriza por tener un estado, que es el conjunto de valores de sus propiedades en un momento del tiempo (por ejemplo, el nombre de un empleado, o el monto del sueldo que percibe). Además, todo objeto tiene un comportamiento, es decir, las acciones que puede realizar y que modificarían su estado (por ejemplo, un empleado puede ascender o completar tareas). Por último, un objeto se caracteriza por tener identidad propia, esto es, por más que dos objetos tengan el mismo comporta- miento y el mismo estado, resultan totalmente diferentes e identificables.

Según el diccionario, una clase es un grupo de elementos de un conjunto que tienen características comunes. Las técnicas de orientación a objetos se centran en la identificación de esos elementos comunes entre los objetos para poder agruparlos en clases y, así, manipularlos fácilmente. Podemos decir que una clase es una abstrac- ción de un grupo de objetos, porque no existe por sí sola.

Por ejemplo, pensemos en una mesa. Hay mesas rectangulares, mesas redondas, de madera, de metal, incluso de diferentes colores. Todas son mesas distintas e identificables, es decir: objetos. Sin embargo, podemos verificar que todas tienen los mismos atributos, aunque con distintos valores. Todas tienen un color, un material, una forma; por lo tanto podemos agruparlas bajo un mismo concepto: la mesa. Desde el punto de vista de la orientación a objetos, podemos decir que mesa es una clase.

Una clase es una abstracción de las principales propiedades de los objetos reales.

CLASES E INSTANCIAS
En el mundo de la orientación a objetos, hay dos términos muy usados: clases e instancias. Como vimos, una clase es una abstracción de un objeto de la realidad. La clase es un modelo estático, por lo tanto, para poder interactuar con otros elementos, debemos crear instancias que representen a cada uno de los objetos particulares que, agrupados, forman la clase.

PROPIEDADES Y MÉTODOS

Como decíamos, los objetos poseen atributos y comportamiento. Ya desde el punto de vista de la programación, los atributos de los objetos se traducen en propiedades de las clases que los modelan. El comportamiento en cambio, está representado por procedimientos y funciones dentro de la clase. En la jerga de la programación orientada a objetos, los procedimientos y funciones que creamos dentro de una clase se denominan métodos, y representan el conjunto de actividades que un objeto puede realizar, es decir, su comportamiento. Los libros más puristas dicen que los objetos se relacionan intercambiando mensajes, por lo que el comportamiento de un objeto está determinado por los mensajes que puede enviar y por los que puede aceptar desde otros objetos. Volviendo a la definición de método, justamente, podemos decir que los métodos son los encargados de interceptar y de enviar mensajes desde y hacia otros objetos y, al mismo tiempo, alterar el estado actual del objeto.

Programación orientada a objetos

La orientación a objetos es una de las técnicas más utilizadas en la actualidad en el mundo  del desarrollo: en el ámbito académico, como herramienta de aprendizaje y, en lo profesional, para solucionar toda clase de problemas.

LOS OBJETOS

Si miramos a nuestro alrededor, vemos que estamos rodeados de objetos. Y cuando debemos desarrollar un nuevo software para resolver un problema, verificamos que los elementos que componen el problema son objetos. Pensemos en un sistema de gestión de negocios. Al analizar las características del problema, nos encontramos con que tenemos objetos como productos, facturas, remitos, depósitos, clientes, etcétera. Y no sólo objetos concretos, sino también abstractos, como ser vencimientos o impuestos.

La programación orientada a objetos es un paradigma basado en la identificación de los objetos inherentes al problema y en la escritura de código que modele esos objetos, sus propiedades, sus comportamientos y la forma en la que se relacionan para resolver el problema. Visto de esta manera, la programación orientada a objetos resulta opuesta a la programación imperativa clásica, donde los programas son secuencias de instrucciones.

ORIGEN
Según algunos autores, el primer lenguaje en usar objetos fue Simula 67, creado en la década del 60 para hacer simulaciones. Cuenta la historia que en el Centro de Cómputo Noruego, en Oslo, trabajaban en simulaciones de barcos, y la cantidad de combinaciones de cualidades entre los diferentes barcos, y cómo unas afectaban a otras, produjo gran confusión en los científicos que estaban escribiendo los programas. Entonces, se les ocurrió organizar los diversos tipos de barcos en clases de objetos; cada clase sería responsable de definir y de administrar sus propios datos y su comportamiento.

Más tarde, el lenguaje Smalltalk fue el primero en introducir el término orientación a objetos para referirse al uso de objetos y de mensajes entre ellos como base del diseño y la programación de aplicaciones. Sin embargo, el auge de este paradigma comenzó en la década del 80, con el lenguaje C++. La tecnología de objetos fue agregada a muchos lenguajes ya existentes, pero este agregado artificial condujo a problemas de diseño y de compatibilidad que no hicieron más que ensuciar los len- guajes existentes. Por otro lado, los lenguajes orientados a objetos puros (como Smalltalk) no eran muy aceptados, porque carecían de características a las que estaban acostumbrados los programadores del momento. Se hicieron muchos intentos por crear lenguajes orientados a objetos, pero con algunas características imperativas y estructuradas; el único que sobrevivió fue el lenguaje Java. En la actualidad, los lenguajes de la plataforma .Net están diseñados de esta manera, es decir, se basan en la definición de clases y de objetos, pero conservan características de la programación imperativa.

 Smalltalk fue uno de los primeros lenguajes completamente orientados a objetos.

VENTAJAS DE LA POO
La programación orientada a objetos (POO) posee algunas ventajas frente a la programación estructurada clásica. La POO consiste en una evolución de la programación estructurada y cuenta con la experiencia adquirida a lo largo de años de desa- rrollo de software, lo que constituye su principal ventaja. Además, conduce a un modelo mental del problema mucho más cercano a la realidad, lo que favorece el análisis, la implementación y el posterior mantenimiento del software. Otra ventaja es que la POO permite lograr un mayor grado de encapsulado, ya que el comporta- miento y los datos propios de cada clase quedan contenidos en la definición de ella. Por último, mediante técnicas que estudiaremos luego, la POO permite reutilizar mucho código, favoreciendo la escritura de nuevos programas.

El estilo de programación: Comentarios

Muchas veces, nos encontramos con que hemos escrito una expresión muy compleja. Al momento de escribirla, tenemos bien claro qué es lo que hace, porque acabamos de idearla, pero luego de un tiempo, cuando volvemos a leerla puede que no entendamos muy bien qué es lo que quisimos hacer. Para solucionar casos de este tipo, es aconsejable el uso de comentarios y dejar una explicación del razonamiento que hicimos para obtener ese código, o cualquier otro mensaje que resulte útil para quien lo lea.

El uso correcto de comentarios, nombres significativos e indentación favorecen la claridad del código.

Nombres significativos

Cuando creamos un procedimiento o una función, el objetivo es realizar un cálculo o tarea específica, por lo que el nombre que le demos al subprograma creado debe revelar de la mejor manera posible el objeto de su existencia. A la hora de darles nombres a los procedimientos y funciones, se aconseja usar palabras completas y frases que indiquen cuál es la tarea que el subprograma realiza, evitando las abreviaturas. También es recomendable usar verbos que representen la acción por realizar.

// C# - Forma incorrecta de nombrar subprogramas
void calcRet(string fac)
int MCM(int a, int b)

// C# - Forma correcta de nombrar subprogramas
void CalcularRetenciones(string numeroFactura)
int MaximoComunDivisor(int numeroA, int numeroB)

Consistencia de formato
Quizá lo más importante a la hora de escribir código fácil de mantener sea lograr un estilo consistente y estandarizado, y mantener ese estilo en todo el programa. Esto significa que, si escribimos los nombres de variables locales con minúsculas, las constantes con mayúscula y los nombres de los procedimientos usando mayúscula para la primera letra de cada palabra, debemos repetir esa convención siempre. Así, si somos consistentes, alguien que esté familiarizado con la nomenclatura, al leer un identificador, podrá saber fácilmente si se trata de una variable, una constante, o un procedimiento.
Del mismo modo que es bueno adoptar convenciones de nomenclatura, resulta importante la consistencia en el uso de líneas en blanco, de espacios entre los operandos y los operadores en las expresiones, y en la cantidad de espacios usados para las tabulaciones.

COMENTARIOS VS NOMBRES CLAROS
En la actualidad, existe una discusión sobre si se deben usar o no comentarios para explicar qué es lo que hace un procedimiento o función. Algunos sostienen que resulta necesario colocar un comentario, mientras que otros insisten en que, si se necesita explicar una porción de código, es porque resulta muy compleja, y aconsejan reescribirla para que sea más sencilla, separándola en otros procedimientos o funciones si fuera necesario. La segunda postura lleva a un código mucho más claro y mantenible.

Los entornos de programación modernos permiten definir reglas de codificación y luego modifican el código automáticamente a medida que escribimos, de manera que se cumplan las reglas.

CONCLUSIONES

En este capítulo, hemos aprendido uno de los conceptos fundamentales de la programación: la modularización. Como programadores, debemos tener siempre presentes estos conceptos y usarlos al máximo posible. Es preferible tener muchas funciones y procedimientos a tener grandes bloques de código de cientos de líneas. Muchos programadores (entre los que me incluyo) tienen esta regla de oro: si un procedimiento o función no cabe en una página del editor que estamos usando, entonces será necesario dividirlo en procedimientos y funciones más pequeños, porque se está volviendo demasiado largo y, por lo tanto, demasiado complejo.