Reutilización del código versus comunalidad accidental

Uno de los errores más desagradables y críticos para el consenso (CVE-2018-17174) se descubrió recientemente en el software Bitcoin Core, que antes de ese punto tenía una historia casi inmaculada. Jimmy Song ha escrito un excelente desglose de este error.

El breve resumen del error es que hay 4 casos en los que el software Bitcoin Core necesita verificar el doble gasto. Los 4 casos inicialmente compartieron el mismo flujo de ejecución de código. Después de algunas iteraciones sutiles del código durante varios años, se omitió uno de los 4 casos ("single-tx-double-gasto-en-un-bloque"), lo que permitiría a un minero engañar a algunos nodos para que acepten un bloque eso infla el suministro de Bitcoin.

La naturaleza de este error me recuerda el conflicto constante entre:

(a) la necesidad de reutilización y optimización del código

(b) el peligro de caer en lo que yo llamo comunidad accidental: cosas que no son similares por diseño, sino por accidente

La similitud accidental crea un terreno fértil para la refactorización de pesadillas y posibles errores como CVE-2018-17144.

Comúnidad accidental

Algunos antecedentes, si no está familiarizado con la ingeniería de software:
 
En el software existe esta gran visión de que los componentes de software son perfectamente modulares, similares a sus contrapartes de ingeniería física. Hay una buena razón por la que no tiene que llevar un tipo diferente de cargador o cable USB donde quiera que vaya.

Por lo tanto, siempre ha habido un fuerte impulso para la reutilización del código. Escribir código redundante a menudo está mal visto. ¿Por qué hacer el mismo trabajo dos veces cuando puedes hacerlo una vez?

También hay una larga historia de reinvención de la rueda en el software que le da a la reutilización del código una prioridad aún mayor en la lista de prioridades. La reutilización del código a menudo se considera una de las "mejores prácticas" de la industria. Un aspirante a desarrollador de software junior podría estar inclinado a pensar que no hay inconveniente en la reutilización del código.

Pero existe un peligro oculto, y no creo que esto se enseñe correctamente en las escuelas, de la extrema reutilización del código.

La reutilización extrema del código significa colapsar dos piezas de código de aspecto similar en una, independientemente de sus casos de uso y su intención original.

Que muchas veces terminan con un código que tiene un carácter común accidental.

Puede que no sea obvio por qué la similitud accidental es mala, pero uno solo tiene que mantener un proyecto de software lo suficientemente grande durante un largo período para comprender por qué.

Es malo porque los requisitos del producto cambian y el software es un producto en constante evolución y nunca terminado.

Este problema del objetivo de movimiento constante es algo bastante exclusivo del software. Si usted es un ingeniero estructural, no se espera que convierta una casa en un rascacielos de 20 pisos o un automóvil en un platillo volador. Sin embargo, en software constantemente hacemos esto.

Cuando los requisitos del producto y los casos de uso cambian, las suposiciones subyacentes para las que se escribió inicialmente el software podrían dejar de ser aplicables.

Por lo tanto, esa orgullosa pieza de código común que refactorizó (pero que ahora ha olvidado por completo) ya no funciona de la manera que cree.

He perdido la cuenta de cuántos proyectos de refactorización dolorosa o errores desagradables que he visto que son el resultado directo de la optimización prematura o la similitud accidental, hasta el punto en que ahora evito cosas como la Herencia como una plaga.

Las cosas que tienen un carácter común accidental revelarán rápidamente sus diferencias cuando evolucionen más allá de su estado inicial. Cualquier rigidez en el código común sería una ruina masiva de la que deshacerse.

Cuantas más capas de comunalidad accidental haya en el código, más campo de minas tendrá que navegar. CVE-2018–17144 es un ejemplo perfecto de eso.