En este artículo, te diré, utilizando la evolución de mi proyecto como ejemplo, la historia de la transición y la visión de la programación por contrato.
Al principio quería nombrar el artículo: "Programación de contratos", en la medida en que el enfoque utilizado es dividir toda la lógica de negocios en contratos de datos y clientes de servicios que usan estos contratos e interactúan entre ellos a través de estas estructuras de datos, de modo que La estructura se procesa con éxito en diferentes servicios.
Algo que describiré en mi propio idioma.
La historia de mi transición a la programación por contrato comenzó con el hecho de que tenía un proyecto heredado con un gran conjunto de funcionalidades diferentes dentro de la misma área de negocios. Además, todo esto seguía siendo multiproceso y personalización para diferentes clientes. Específicamente, el área de negocios fue el intercambio de documentos electrónicos legalmente relevantes entre el sistema de contabilidad, el archivo y los servicios en la nube.
En el proceso de desarrollo del sistema, aparecieron nuevos requisitos comerciales y, como resultado, el proyecto se desarrolló rápidamente y se complicó por la nueva funcionalidad, que en algún momento condujo a una situación en la que la arquitectura del proyecto comenzó a parecerse a varias aplicaciones separadas con funcionalidad relacionada. Solo se implementó esta funcionalidad, no de elementos comunes, sino de estructuras similares pero implementadas de manera diferente en diferentes ensamblados y espacios de nombres.
Visualmente, dicha arquitectura se puede representar como varias verticales de funcionalidad

Un rasgo característico de dicha arquitectura era que si aparecía algún requisito adicional o error, entonces se requería implementar dicha tarea en todos los "módulos funcionales" del sistema, y no en un área. Otro rasgo característico fue la presencia en el proyecto de una gran cantidad de constructores, lo que condujo a una división vertical del área comercial. El desarrollador implementa nuevos algoritmos para los nuevos requisitos comerciales en el código de los constructores, lo que lleva a la aparición de nuevas entidades con diferentes estructuras para el mismo objeto comercial. Es cierto que este enfoque puede considerarse más orientado a objetos que un simple enfoque de código subyacente con código de espagueti. Por lo tanto, si ve una gran cantidad de constructores en sus proyectos, la transición a un enfoque de contacto simplificará el soporte y acelerará el desarrollo de su proyecto.
Una vez, en la compañía, nos enfrentamos al hecho de que el cliente con el que estábamos implementando comenzó a expresar que el sistema que desarrollé a menudo producía errores. No podía discutir esto, aunque aparecían errores periódicamente, pero se corrigieron y algunos de los clientes tenían el sistema instalado y lo usaban. Debo agradecerle que el cliente fue dañino y exigente, y probó muy cuidadosamente nuestro sistema durante el período de implementación.
Tampoco me gustó el hecho de que no tenía suficiente tiempo para el desarrollo y el apoyo, a pesar de muchos esfuerzos, y en algún momento simplemente no tenía idea de qué más podría mejorar el sistema y hacerlo más estable.
La decisión llegó repentina e inesperadamente.
Comprendí que los mismos objetos comerciales se implementan de manera diferente en diferentes módulos del sistema: documentos de diferentes tipos, recibos, trabajadores, clientes de servicios, clientes de bases de datos, clientes de archivos con la capacidad de almacenar documentos en varios formatos (personalización para diferentes clientes;) )
Parte de la lógica se implementó en entidades, lo que impidió el uso de las mismas entidades en diferentes algoritmos.
Entonces decidí: era necesario crear algo así como un solo constructor con detalles a partir de los cuales se puedan ensamblar todos los algoritmos implementados en el sistema. Lo cual es lógico, porque reduce el número de clases similares y simplifica el soporte.
Decidí dividir estrictamente el "universo" de mi aplicación en
- contratos de datos: estructuras de datos que contienen y se usan solo para el almacenamiento de datos
Docs
Sobres
Recibos
EP
...
- clientes-servicios : escribo específicamente que los clientes son servicios, porque al implementar cada sistema que interactuaba en el área comercial, lo representaba como un sobre en este sistema, en el que se implementaban los métodos para trabajar con contratos de fecha. Y además del hecho de que estas clases son envoltorios sobre los servicios, también contenían la lógica, las conversiones y las transformaciones vinculantes necesarias para simplificar la lógica empresarial.
Además, los madereros se aferraron a estos clientes. Eso le permitió encontrar rápidamente el punto de error en el registro. (en el futuro, muchas llamadas desaparecieron cuando, según los registros, los propios usuarios comenzaron a comprender dónde se equivocaron: un sistema de archivos, una red, un sistema de contabilidad o un servicio web del operador)
Por ejemplo
CloudClient: un cliente de un servicio en la nube al que se envían y procesan documentos
- Descargar
- enviar
- Obtener
- Descargar
- De acuerdo
...
FileSystemClient - cliente del sistema de archivos
ERPClient - sistema de contabilidad del cliente
Los clientes implementaron todos los métodos utilizados previamente en los algoritmos en todos los módulos, lo que permitió implementar rápida y fácilmente algoritmos recientemente implementados desde las mismas partes.
Y la asignación de métodos de funcionalidad similares en los respectivos clientes condujo a una mayor especialización y reutilización del código.
La arquitectura era ahora un diagrama como en la imagen.

Asigné todos los objetos básicos de mi diseñador al ensamblaje con el final del SDK (Software Developers Kit) y se hizo más fácil de trabajar y lo más importante, más agradable. El trabajo ya ha dejado de ser la creación de muletas y soluciones temporales, y ahora la actitud hacia el proyecto desde el interior se ha vuelto más seria por el hecho de que ahora vi un gran margen de escalabilidad y competitividad de la arquitectura. Esto se debe a que este hecho aumentó significativamente la motivación y abrió nuevos horizontes profesionales.
Basado en el SDK creado, me entregué para implementar una capa de lógica empresarial que automatiza la implementación de tareas comerciales directas. Dado que todos los matices técnicos se llevaron a las capas inferiores ubicadas en los clientes, la implementación de los mismos algoritmos se simplificó y comenzó a parecer mucho más agradable.
El enfoque es simple y permite simplificar el desarrollo posterior y lo que es muy importante es aumentar la flexibilidad de la arquitectura. Sí, esto requerirá una amplia refactorización. En mi caso, me llevó 2 semanas de desarrollo en modo fanático. Pero después de eso, casi no codifiqué, porque todo funcionó de manera estable.
Y gracias a la separación de responsabilidades (SPR) y los registros, pude suprimir rápidamente los errores de servicios de terceros, lo que conlleva errores de mi parte. Anteriormente, esto requería análisis que consumían un tiempo considerable.
Este enfoque es bueno para usar en ciertas capas. En las capas superiores de la aplicación, un modelo anémico puede ser más conveniente, solo que es mejor implementar un modelo anémico basado en un enfoque contractual.