Si a una cinta de Möbius le unimos por su borde un círculo obtenemos un plano proyectivo, si unimos por su borde dos cintas de Möebius obtenemos la botella de Klein.
La botella de Klein no tiene un interior ni un exterior, ni es estrictamente una botella. No tiene bordes y es una superficie cerrada.
Si se quiere hacer el modelo en el espacio tridimensional, tendrá que pasar a través de sí misma.
Buscar este blog
lunes, julio 02, 2012
Code as Design: Three Essays by Jack W. Reeves
Por alguna razón tengo en la recámara desde hace meses una versión alternativa del artículo sobre La programación como proceso de diseño. Y como creo que es bastante diferente del "original", además de que siempre es buena idea hablar sobre desarrollo de software, lo añado a continuación.
Estos ensayos con casi veinte y diez años de antiguedad, siguen siendo una verdad como un templo y comenta cosas que la mayoría de las personas en el mundo del software, ignoran (y olvidamos) con consecuencias negativas a corto, medio y largo plazo.
El punto clave del ensayo es que desarrollar código, es un proceso de diseño, y es uno muy complicado.
Siempre se compara el desarrollo de software con otras ingenierías donde se diseña y construye algo físico. Pero es incorrecto. Si hacer aviones se pareciese a hacer software, entonces pulsando un botón, los planos y especificaciones de un Boeing 747 se convertirían en un avión real y en pleno vuelo en cuestión de segundos o minutos a coste cercano a cero. Si se tratase de hacer puentes, el F5 nos permitiría levantar un puente para comprobar cuanto peso aguanta con pilares de un material u otro en el mismo tiempo y al mismo coste.
La naturaleza de las ingenierías "normales" es construir algo en base a unas especificaciones. Algo caro de diseñar, pero muchisimo más caro de construir (tiempo, recursos, gente). En software la "build", es decir el producto final construido, es cuestión de un compilador y un par de minutos (o segundos). Lo realmente caro es el diseño, y el diseño (especificaciones, planos...) es el código. Construir en base al diseño es labor del compilador y al contrario que en todas las demás ingenierías, tiene un coste en tiempo y dinero cercano a cero.
Partiendo de esa premisa, es fácil de donde vienen ciertos problemas, como las especificaciones mutantes, el scope creep, etc.
A continuación dejo algunas citas interesantes.
Revelation number two: it is cheaper and simpler to just build the design and test it than to do anything else. We do not care how many builds we do—they cost next to nothing in terms of time, and the resources used can be completely reclaimed later if we discard the build. Note that testing is not just concerned with getting the current design correct, it is part of the process of refining the design. Hardware engineers of complex systems often build models (or at least they visually render their designs using computer graphics). This allows them to get a "feel" for the design that is not possible by just reviewing the design itself. Building such a model is both impossible and unnecessary with a software design. We just build the product itself. Even if formal software proofs were as automatic as a compiler, we would still do build/test cycles. Ergo, formal proofs have never been of much practical interest to the software industry.
The overwhelming problem with software development is that everything is part of the design process. Coding is design, testing and debugging are part of design, and what we typically call software design is still part of design. Software may be cheap to build, but it is incredibly expensive to design. Software is so complex that there are plenty of different design aspects and their resulting design views. The problem is that all the different aspects interrelate (just like they do in hardware engineering).
[...] no other modern industry would tolerate a rework rate of over 100% in its manufacturing process. A construction worker who can not build it right the first time, most of the time, is soon out of a job. In software, even the smallest piece of code is likely to be revised or completely rewritten during testing and debugging. We accept this sort of refinement during a creative process like design, not as part of a manufacturing process. No one expects an engineer to create a perfect design the first time. Even if she does, it must still be put through the refinement process just to prove that it was perfect.
The software design is not complete until it has been coded and tested. Testing is a fundamental part of the design validation and refinement process. The high level structural design is not a complete software design; it is just a structural framework for the detailed design.
It would be nice if high level software design could be a more rigorous engineering process, but the real world of software systems is not rigorous. Software is too complex and it depends on too many other things. Maybe some hardware does not work quite the way the designers thought it did, or a library routine has an undocumented restriction. These are the kinds of problems that every software project encounters sooner or later. These are the kinds of problems discovered during testing (if we do a good job of testing), for the simple reason that there was no way to discover them earlier. When they are discovered, they force a change in the design. If we are lucky, the design changes are local. More often than not, the changes will ripple through some significant portion of the entire software design (Murphy's Law). When part of the effected design can not change for some reason, then the other parts of the design will have to be weakened to accommodate. This often results is what managers perceive as "hacking", but it is the reality of software development.
As just a small point, all programmers know that writing the software design documents after the code instead of before, produces much more accurate documents. The reason is now obvious. Only the final design, as reflected in code, is the only one refined during the build/test cycle. The probability of the initial design being unchanged during this cycle is inversely related to the number of modules and number of programmers on a project. It rapidly becomes indistinguishable from zero.
The generally accepted definition is that a “specification” states the what, which is followed by a design document that details the how. While there is a certain amount of flexibility allowed of the compiler in determining the how of object code, there is certainly no creativity involved. And that is where I draw the line. When the document is detailed enough, complete enough, and unambiguous enough that it can be interpreted mechanistically, whether by a computer or by an assembly line worker, then you have a design document. If it still requires creative human interpretation, then you don’t.
Back to software. We in the software industry also refine our designs, only we don't get to call it engineering. We call it "testing and debugging". This phase of the software lifecycle takes a long time. All too often it takes longer than planned. Unfortunately, it is often not enough and the final designs that we turn into deliverable software are still not as good as they should be. This seems like a fact of software life. Many people lament it and ask why we software developers do not "engineer" our designs better? Many explanations are offered, but never the one most obvious to me -- simple economics. Software is dirt cheap to build.
I suspect that most engineers in other disciplines haven't a clue about what percentage of their time is spent actually creating a design and what is spent on testing and debugging the result. Some industries are probably better than software. I am pretty sure that other industries are actually much worse. Consider what it must take to "design" a new airliner.
I get somewhat testy when people start making gratuitous comparisons between software design and other engineering disciplines. Major microprocessors have been shipped with bugs in their logic, bridges have collapsed, dams broken, airliners fallen out of the sky, and thousands of automobiles and other consumer products recalled - all within recentmemory and all the result of design errors.
The bottom line is that my design must be correct, or every piece of software built from it will be erroneous. Therefore I concentrate on doing it right, and it takes mental effort and skill, just like any other creative design activity.
Even the best of the traditional approaches continue to try to break software design into disjoint steps with separate notations and products, and then they continue to wonder why they have problems getting a final software product that is correct.
Same thing. Likewise, Warner-Orr diagrams, Booch diagrams, object diagrams, you name it. Each has its strengths, and a single fundamental weakness - it really isn't a software design. Ultimately, improvements in programming techniques are overwhelmingly more important to software development than anything else.