Software Design — 2ª edición

Nota a la 2ª edición: el siguiente texto lo redacté en el año 2001 . Puse por escrito algunas de mis nociones de aquella época y envié el texto a un colega quien ese año me preguntó mi opinión sobre cómo diseñar software. Por el momentola primera edición no está disponible en línea. En esta segunda edición me tomé la libertad de disminuir un poco el tufo dogmático de la primera edición . Además, agregué referencias a la fecha de algunas páginas en Internet que cambiaron; aunque mantuve las referencias anteriores , quizá por nostalgia . Esta segunda edición tan sólo contiene pequeñas adaptaciones a la primera edición. Muchos de los puntos requieren actualizaciones mayores.

——

Con respecto al diseño de software, que es el aspecto más fascinante para mí de lo que hacemos como programadores profesionales, permíteme comentarte mis impresiones y conclusiones actuales acerca de esta actividad. Por supuesto, estas conclusiones están sesgadas por mi enturbiado entendimiento, pero después de estudiar la experiencia de algunas luminarias en nuestro campo, e intentar practicar sus lecciones, encuentro que dichas conclusiones tienen sentido para mí.

I. El resultado de la actividad 'diseño'

El resultado material de la actividad de diseño debe ser algo ejecutable. Cualquier cosa menos que eso es pura estimulación mental.

II. Arquitectura de software

Todos los aspectos, de alto y bajo nivel, de nuestro diseño están expresados, implícita o explícitamente, en la arquitectura del software. Aunque “arquitectura de software” todavía es un término difuso, una exposición adecuada de arquitectura de software es la de Philippe Kruchten «The 4+1 View Model of Architecture».

The 4+1 View Model of Architecture

https://www.computer.org/csdl/mags/so/1995/06/s6042-abs.html

IEEE Software November 1995 (Vol. 12, No. 6)

https://www3.software.ibm.com/ibmdl/pub/software/rational/web/whitepapers/2003/Pbk4p1.pdf

https://www.rational.com/media/whitepapers/Pbk4p1.pdf

En resumen, la arquitectura de software considera 5 vistas o categorías, agrupadas por su naturaleza en:

Conceptual:

Vista Lógica (clases, módulos y subsistemas)

Vista Concurrente (procesos y threads)

Física:

Vista de Componentes (medios para empaquetar los elementos de la Vista Lógica: assemblies, DLLs)

Vista Distribuida (comúnmente llamada infraestructura de cómputo: servidores que contienen los elementos de la Vista de Componentes)

Funcional:

Vista de Casos de Uso. Ésta gobierna a todo lo que puede existir en las otras vistas; en otras palabras, nada debe existir si no aporta a soportar la funcionalidad del software

III. El código fuente es el diseño detallado del software

El diseño de alto nivel puede consistir de diagramas que expresen aspectos de las diferentes vistas de Kruchten, pero el diseño detallado es el código fuente. En software, nuestros planos detallados es un documento técnico llamado comúnmente «código fuente». Dichos planos de nuestro producto son entregamos al constructor del producto: el compilador o traductor a código ejecutable.

Philippe Kruchten, Jack W. Reeves y otros tienen algunas ideas al respecto:

What is Software Design? by Jack W. Reeves

https://www.bleading-edge.com/Publications/C++Journal/Cpjour2.htm

The Nature of Software: What's so Special About Software Engineering? by Philippe Kruchten

https://www.ibm.com/developerworks/rational/library/content/RationalEdge/oct01/TheNatureOfSoftwareOct01.pdf

https://www.therationaledge.com/content/oct_01/toc.html

From Craft to Science: Searching for First Principles of Software Development by Koni Buhrer

https://www.ibm.com/developerworks/rational/library/content/RationalEdge/dec00/TheRationalEdgeDec00Issue.pdf

https://www.ibm.com/developerworks/rational/library/content/RationalEdge/jan01/FromCraftToScienceJan01.pdf

https://www.therationaledge.com/content/dec_00/f_craftscience.html

IV. Decidir es diseñar

Diseñar requiere decidir constantemente, diseñar es decidir. Decidir sobre los aspectos del diseño detallado, decidir sobre los aspectos de diseño de alto nivel, e incluso decidir que no vamos a decidir nada todavía sobre alguna propiedad particular del software; es decir, vamos a diferir dicha decisión.

Martin Fowler habla acerca del diseño en:

Is Design Dead?

https://martinfowler.com/articles/designDead.html

What's a Model For?

https://www.martinfowler.com/distributedComputing/purpose.pdf

https://martinfowler.com/articles/purpose.pdf

V. Diseño estable y emergente

Diseñar requiere consideración de los principios que gobiernan y sustentan la arquitectura de software; como dice Bertrand Meyer, los aspectos a gran escala de la arquitectura de software se encomiendan o están sustentados en los aspectos de bajo nivel o escala detallada (código fuente). Si estos aspectos no obedecen a principios coherentes y de estilo, entonces difícilmente se logran los aspectos a gran escala.

Existe un cuerpo de conocimiento importante acerca de diseño orientado a objetos, con reglas que representan esos principios coherentes y de estilo:

Principles Of Object Oriented Design

https://c2.com/cgi/wiki?PrinciplesOfObjectOrientedDesign

Las recomendaciones del maestro Stroustrup agregan perspectivas importantes:

Bjarne Stroustrup's C++ Style and Technique FAQ

https://www.stroustrup.com/bs_faq2.html

https://www.research.att.com/~bs/bs_faq2.html

Las prácticas básicas son esenciales. Steve McConnell, ex-programador de Microsoft, tiene buen material al respecto:

Code Complete: A Practical Handbook of Software Construction

https://www.stevemcconnell.com/cc.htm

Rapid Development: Taming Wild Software Schedules

https://www.stevemcconnell.com/rd.htm

La técnica de factorización representa una excelente forma para mantener un diseño estable y flexible:

Refactoring

https://www.refactoring.com

VI. Control empírico del proceso de diseño

Un método de diseño es intrínsecamente iterativo e incremental. Se adhiere a un proceso 'gestalt'; es decir, no puedes terminar de diseñar software si primero no lo programas, y al mismo tiempo no puedes programar software si primero no lo diseñas.

Existen métodos sistemáticos de diseño y programación, Martin Fowler habla acerca de algunos métodos actuales:

The New Methodology

https://martinfowler.com/articles/newMethodology.html

Continuous Integration (no daily build)

https://martinfowler.com/articles/continuousIntegration.html

VII. Método sistemático de diseño

Un método sistemático de programación consiste de al menos tres partes:

a. Una notación — el énfasis aquí es contar con un conjunto de conceptos de diseño que guarden coherencia y que puedan ser expresados por medio de dicha notación. Actualmente está de moda UML y es importante tener mentalmente disponibles sus conceptos para comunicar la arquitectura de software. Pero para el diseño detallado (código fuente) la notación más eficiente y efectiva sigue siendo el lenguaje de programación seleccionado.

En otras palabras, todo lo que se puede expresar en un diagrama de clases en UML se puede expresar en el código fuente; y mientras las herramientas de generación de código carezcan del nivel de abstracción suficiente para eliminar la necesidad de modificar el código generado, el diseño detallado seguirá siendo el código fuente en sintaxis del lenguaje de programación.

En el futuro, seguramente habrá las herramientas para expresar todos los aspectos del diseño detallado en una notación como UML, y entonces eso será nuestra nueva forma de código fuente.

b. Un proceso — actividades, roles y artefactos. Los mejores procesos son los que incluyen un ciclo cerrado de retro-alimentación que se ajusta a la naturaleza 'gestalt' del software.

Los artículos en el siguiente sitio tienen información relevante acerca de los procesos que varios programadores profesionales han sintetizado:

https://www.extremeprogramming.org

https://www.agilealliance.org

¿Qué es «Software craftsmanship»?

https://blogs.msdn.microsoft.com/destreza/2017/03/19/que-es-software-craftsmanship/

El potencial de los métodos ágiles de diseño está en la esencia del desarrollo cooperativo:

-Control empírico del proceso de desarrollo

-Comportamiento emergente o adaptativo

-Auto-organización

c. Herramientas — que soporten el conjunto de conceptos disponibles en la notación.

En la práctica, lo más eficiente y efectivo, si el objetivo es obtener software ejecutable, es usar las herramientas más simples que ayuden con la comunicación entre las personas en el equipo de desarrollo y entre los individuos y la computadora.

En otras palabras, una simple hoja de papel y lápiz, o un pizarrón, son más efectivas que costosas herramientas CASE. No menos importante, el compilador es la mejor herramienta para verificar el aspecto estático de tu diseño detallado, el compilador hará un análisis preciso de tus decisiones de diseño y te dirá invariablemente toda inconsistencia con su sistema de tipos.

Además, para verificar los aspectos dinámicos de tu diseño, un contexto de pruebas unitarias (unit-testing framework) te ayudará a obtener la retroalimentación para evolucionar tu diseño de forma coherente y concreta, satisfaciendo los aspectos de la Vista de Casos de Uso de tu arquitectura.

Kent Beck y Erich Gamma exponen el diseño de un contexto de pruebas aquí:

JUnit Cookbook

https://junit.sourceforge.net/doc/cookbook/cookbook.htm

JUnit A Cook's Tour

https://junit.sourceforge.net/doc/cookstour/cookstour.htm

Como dice Martin Fowler: «Never in the field of software development was so much owed by so many to so few lines of code».

https://www.junit.org

Contextos de pruebas para varios lenguajes de programación están disponibles aquí (incluyendo la versión en C++Builder que hice del CppUnit de Michael Feathers):

https://www.xprogramming.com/software.htm

En general, el material en este sitio provee buen material para el diseño y desarrollo de software:

https://butunclebob.com/

https://www.objectmentor.com/resources/articles

Los mejores métodos sistemáticos de diseño y programación actuales se derivan del trabajo de las siguientes luminarias:

Profesor Edsger Wybe Dijkstra

https://www.cs.utexas.edu/users/EWD/

Kristen Nygaard

https://www.mn.uio.no/ifi/english/about/kristen-nygaard/

https://www.ifi.uio.no/~kristen/

Ole-Johan Dahl

https://www.mn.uio.no/ifi/english/about/ole-johan-dahl/

https://www.ifi.uio.no/%7Eolejohan/

Alan Turing

https://www.turing.org.uk/turing/

Niklaus Wirth

https://www.inf.ethz.ch/personal/wirth/

https://www.cs.inf.ethz.ch/~wirth/

Donald E. Knuth

https://www-cs-faculty.stanford.edu/~knuth/

Bjarne Stroustrup

https://www.stroustrup.com/

https://www.research.att.com/~bs/homepage.html

Barbara Liskov

https://www.pmg.csail.mit.edu/~liskov/

https://www.objectmentor.com/resources/articles/lsp.pdf

David Lorge Parnas

https://www.computer.org/web/awards/mills-david-parnas

https://www.crl.mcmaster.ca/SERG/parnas.homepg

Tom DeMarco

https://www.systemsguild.com/tdm.htm

https://www.atlsysguild.com/GuildSite/TDM/Tom_DeMarco.html

Gerald M. Weinberg

https://www.geraldmweinberg.com

Larry Constantine

https://wiki.c2.com/?LarryConstantine

https://www.foruse.com/

Edward Yourdon

https://yourdon.com/

Meilir Page-Jones

https://www.construx.com/Employees/Meilir_Page-Jones/

Grady Booch

https://researcher.watson.ibm.com/researcher/view.php?person=us-gbooch

James Rumbaugh

https://en.wikipedia.org/wiki/James_Rumbaugh

Ivar Jacobson

https://www.ivarjacobson.com/

Bertrand Meyer

https://www.eiffel.com

VIII. Dimensiones en desarrollo de software

Los factores para la calidad del diseño y desarrollo de software se pueden agrupar en cuatro dimensiones:

a. Personas - el aspecto más importante y que aporta en general los factores determinantes para la calidad del software

El trabajo de Tom DeMarco y Tim Lister habla de esto desde hace ya muchos años

https://www.systemsguild.com/tdm.htm

First-Order Components in Software Development (People-oriented programming, non-linear response) de Alistair Cockburn

https://alistair.cockburn.us/Characterizing+people+as+non-linear,+first-order+components+in+software+development

https://crystalmethodologies.org/articles/panlc/peopleasnonlinearcomponents.html

Las personas en el diseño y programación orientada a objetos, de un servidor:

https://sg.com.mx/content/view/338

https://www.rosenblueth.mx/InterFAR/Vol1Num3/doc/Vol1Num3-48.htm

b. Proceso - las secciones VI y VII arriba.

c. Arquitectura de Producto - las secciones II, III, IV y V arriba.

Si un producto de software es correcto y robusto, es porque su código fuente tiene una adecuada administración de dependencias internas y conserva un adecuado sentido de estética y orden entre sus componentes; si un producto de software es modular y extensible es porque su código fuente tiene esas propiedades.

De ninguna otra manera es posible conseguir la calidad externa del software si no se atiende desde el principio la calidad interna. De esto trata el siguiente artículo de Bertrand Meyer:

Factores de la calidad del software

https://www.angelfire.com/dc/marcodorantes/Docs/CalidadDelSoftware.doc

d. Tecnología - aquí va todo el conocimiento específico de una plataforma de cómputo

IX. Pensamiento sistémico

Patrones y la teoría general de sistemas para el futuro (que ya paso) - existe material importante y un cuerpo de conocimiento fundamental que, sin importar lo que diga la mercadotecnia, es indispensable dominar para ser relevante en desarrollo de software ahora y siempre. Se trata de los patrones o mecanismos análogos de la teoría general de sistemas.

Comúnmente se escucha de patrones de diseño; sin embargo, esos pertenecen a una categoría, pero los hay por todos lados: patrones de proceso, patrones organizacionales, patrones arquitectónicos, patrones de implementación (idioms), patrones de análisis. Esto equivale a lo que la teoría general de sistemas estudia como situaciones análogas en relación a los procesos de pensamiento en los seres humanos.

Las herramientas de pensamiento para diseño moderno de software están disponibles y serán las bases para el software que estaremos usando en el cual se utilizan múltiples paradigmas para su diseño.

Algunas referencias al respecto:

•Patrones

Pattern Languages of Programs

https://hillside.net/conferences

https://jerry.cs.uiuc.edu/~plop/

Euro-Plop

https://www.europlop.net/

https://www.argo.be/europlop/Papers/Final/

Portland Pattern Repository

https://c2.com/cgi/wiki?PortlandPatternRepository

Patrones organizacionales de James Coplien

https://amzn.com/0131467409

https://www.bell-labs.com/cgi-user/OrgPatterns/OrgPatterns?CoplienOrganizationPatterns

•Diseño multi-paradigma

Generative Programming

https://amzn.com/0201309777

https://www.generative-programming.org/

https://www.prakinf.tu-ilmenau.de/~czarn/generate/engl.html

Aspect-Oriented Programming

https://www2.parc.com/csl/groups/sda/

https://aosd.net

Intentional Programming

https://www.intentionalsoftware.com

https://www.c2.com/cgi/wiki?IntentionalProgramming

Generic Programming

https://www.lafstern.org/matt/

•Acerca de la teoría general de sistemas

Cybernetics and Systems Theory

https://pespmc1.vub.ac.be/CYBSYSTH.html

«Este no es el final, ni siquiera es el comienzo del final; tal vez, tan sólo es el final del comienzo» —Winston Churchill