Entonces, vendimos al cliente un producto de software B2B.
En la presentaci贸n, le gust贸 todo, pero durante la implementaci贸n result贸 que algo todav铆a no encajaba. Por supuesto, puede decir que necesita seguir las "mejores pr谩cticas" y transformarse en un producto, y no al rev茅s. Esto puede funcionar si tiene una marca fuerte (por ejemplo, tres letras grandes y puede enviar las tres letras peque帽as). De lo contrario, le explicar谩n r谩pidamente que el cliente logr贸 todo gracias a sus procesos comerciales 煤nicos, y mejor cambiemos su producto o no funcionar谩. Hay una opci贸n para rechazar y referirse al hecho de que las licencias ya se han comprado, y no hay ning煤n lugar para ir desde el submarino. Pero en mercados relativamente estrechos, tal estrategia no funcionar谩 por mucho tiempo.
Tenemos que modificarlo.
Los enfoques
Existen varios enfoques b谩sicos para la adaptaci贸n del producto.
Monolito
Cualquier cambio se realiza directamente en el c贸digo fuente del producto, pero se incluye en ciertas opciones. En tales productos, como regla, hay formas monstruosas con configuraciones, a las cuales, para no confundirse, se les asignan sus n煤meros o c贸digos. La desventaja de este enfoque es que el c贸digo fuente se convierte en un gran espagueti, en el que hay tantos casos de uso diferentes que se vuelve muy largo y costoso de mantener. Cada opci贸n posterior requiere m谩s y m谩s recursos. El rendimiento de dicho producto tambi茅n deja mucho que desear. Y si el lenguaje en el que est谩 escrito el producto no es compatible con pr谩cticas modernas como la herencia y el polimorfismo, entonces todo se vuelve muy triste.
Copia
El cliente recibe el c贸digo fuente completo del producto con una licencia para modificarlo. A menudo, dichos proveedores le dicen al cliente que no adaptar谩n el producto ellos mismos, ya que ser谩 demasiado costoso (es mucho m谩s rentable para un vendedor vender licencias que contactar a los servicios). Pero tienen subcontratistas familiares que contratan empleados relativamente baratos y de alta calidad en alg煤n pa铆s de terceros pa铆ses que est谩n listos para ayudarlos. Tambi茅n hay situaciones en las que las mejoras ser谩n realizadas directamente por los especialistas del cliente (si tienen unidades de personal). En tales casos, el c贸digo fuente se toma como punto de partida, y el c贸digo modificado no tendr谩 ninguna conexi贸n con lo que era originalmente y vivir谩 su propia vida. En este caso, puede eliminar con seguridad al menos la mitad del producto original y reemplazarlo con su propia l贸gica.
Fusi贸n
Esta es una mezcla de los dos primeros enfoques. Pero en 茅l, el desarrollador que corrige el c贸digo siempre debe recordar: "viene la fusi贸n". Cuando se lanza una nueva versi贸n del producto fuente, en la mayor铆a de los casos deber谩 fusionar manualmente los cambios en el c贸digo fuente y modificado. El problema es que en cualquier conflicto ser谩 necesario recordar por qu茅 se hicieron ciertos cambios, y esto podr铆a ser hace mucho tiempo. Y si la refactorizaci贸n de c贸digo se realiz贸 en el producto original (por ejemplo, los bloques de c贸digo simplemente se reorganizaron), la fusi贸n requerir谩 mucho tiempo.
Modularidad
L贸gicamente, el enfoque m谩s correcto. El c贸digo fuente del producto en este caso no sufre cambios, y se agregan m贸dulos adicionales que ampl铆an la funcionalidad. Sin embargo, para implementar dicho esquema, el producto debe tener una arquitectura que le permita expandirse de esta manera.
Descripci贸n
M谩s adelante, con ejemplos, mostrar茅 c贸mo expandimos los productos desarrollados sobre la base de la plataforma
lsFusion abierta y gratuita.
Un elemento clave del sistema es el m贸dulo. Un m贸dulo es un archivo de texto con la extensi贸n
lsf , que contiene el
c贸digo lsFusion . En cada m贸dulo, se declaran tanto la l贸gica de dominio (funciones, clases, acciones) como la l贸gica de presentaci贸n (formularios, navegador). Los m贸dulos, por regla general, se encuentran en directorios, divididos por un principio l贸gico. Un producto es una colecci贸n de m贸dulos que implementan su funcionalidad y se almacenan en un repositorio separado.
Los m贸dulos son interdependientes. Un m贸dulo depende de otro si usa su l贸gica (por ejemplo, se refiere a propiedades o formas).
Cuando aparece un nuevo cliente, se inicia un repositorio separado (Git o Subversion), en el que se crear谩n los m贸dulos con las modificaciones necesarias. Este repositorio define el llamado m贸dulo superior. Cuando se inicia el servidor, solo se conectar谩n esos m贸dulos, de los cuales depende directa o transitivamente a trav茅s de otros m贸dulos. Esto le permite al cliente usar no toda la funcionalidad del producto, sino solo la parte que necesita.
Jenkins crea una tarea que combina los m贸dulos de producto y cliente en un 煤nico archivo jar, que luego se instala en un servidor de producci贸n o prueba.
Considere varios casos principales de mejoras que surgen en la pr谩ctica:
Supongamos que tenemos un m贸dulo de
pedido en el producto, que describe la l贸gica de pedido est谩ndar:
El cliente
X desea agregar un porcentaje de descuento y un precio de descuento para la l铆nea de pedido.
Primero, se crea un nuevo m贸dulo
OrderX en el repositorio del cliente. En su encabezado, se coloca una dependencia en el m贸dulo de
pedido original:
En este m贸dulo, declaramos nuevas propiedades bajo las cuales se crear谩n campos adicionales en las tablas, y las agregamos al formulario:
Hacemos que el precio con descuento no est茅 disponible para la grabaci贸n. Se calcular谩 como un evento separado cuando cambie el precio inicial o el porcentaje de descuento:
Ahora debe cambiar el c谩lculo del importe en la l铆nea de pedido (debe tener en cuenta nuestro precio de descuento reci茅n creado). Para hacer esto, generalmente creamos ciertos "puntos de entrada" donde otros m贸dulos pueden insertar su comportamiento. En lugar de la declaraci贸n inicial de la propiedad de suma en el m贸dulo Orden, utilizamos lo siguiente:
En este caso, el valor de la propiedad de
suma se recopilar谩 en un CASO, donde CUANDO se puede dispersar en diferentes m贸dulos. Se garantiza que si el m贸dulo A depende del m贸dulo B, todo CUANDO del m贸dulo B funcionar谩 m谩s tarde que CUANDO del m贸dulo A. Para calcular correctamente la
cantidad descontada, se agrega la siguiente declaraci贸n al m贸dulo
OrderX :
Como resultado, si se establece un descuento, la cantidad estar谩 sujeta a 茅l, de lo contrario, la expresi贸n original.
Supongamos que un cliente desea agregar una restricci贸n de que el monto del pedido no debe exceder un cierto monto especificado. En el mismo m贸dulo
OrderX , declaramos una propiedad en la que se almacenar谩 el valor de restricci贸n, y lo agregamos al formulario de
opciones est谩ndar (puede crear un formulario separado con la configuraci贸n si lo desea):
Luego, en el mismo m贸dulo, declaramos el monto del pedido, lo mostramos en el formulario y agregamos un l铆mite a su exceso:
Y finalmente, el cliente solicit贸 cambiar ligeramente el dise帽o del formulario de edici贸n del pedido: hacer el encabezado del pedido a la izquierda de las l铆neas con un separador, as铆 como mostrar siempre los precios con una precisi贸n de dos caracteres. Para hacer esto, se agrega el siguiente c贸digo a su m贸dulo, que cambia el dise帽o est谩ndar generado del formulario de pedido:
Como resultado, obtenemos dos m贸dulos de
pedido (en el producto), en los que se implementa la l贸gica b谩sica del pedido, y
OrderX (en el cliente), en el que se implementa la l贸gica de descuento necesaria:
Cabe se帽alar que el m贸dulo
OrderX puede llamarse
OrderDiscount y transferirse directamente al producto. Luego, si es necesario, ser谩 posible que cada cliente conecte f谩cilmente la funcionalidad con descuentos.
Esto est谩 lejos de todas las posibilidades que ofrece la plataforma para expandir la funcionalidad en m贸dulos individuales. Por ejemplo, usando la herencia, puede implementar modularmente la l贸gica de
registro .
Si hay alg煤n cambio en el c贸digo fuente del producto que contradiga el c贸digo en el m贸dulo dependiente, se generar谩 un error cuando se inicie el servidor. Por ejemplo, si el formulario de
pedido se
elimina en el m贸dulo
Pedido , al inicio habr谩 un error de que el formulario de
pedido no se encontr贸 en el m贸dulo
OrderX . Adem谩s, el error se resaltar谩 en el
IDE . Adem谩s, el IDE tiene una funci贸n para buscar todos los errores en el proyecto, lo que le permite identificar todos los problemas que se han producido debido a la actualizaci贸n de la versi贸n del producto.
En la pr谩ctica, tenemos todos los repositorios (del producto y todos los clientes) conectados al mismo proyecto, por lo que refactorizamos con calma el producto, mientras cambiamos la l贸gica en los m贸dulos del cliente donde se usa.
Conclusi贸n
Dicha arquitectura micromodular proporciona los siguientes beneficios:
- Cada cliente est谩 conectado solo con la funcionalidad que necesita . La estructura de su base de datos contiene solo aquellos campos que usa. La interfaz de la soluci贸n final no contiene elementos innecesarios. El servidor y el cliente no realizan eventos y comprobaciones innecesarios.
- Flexibilidad en los cambios a la funcionalidad b谩sica . Directamente en el proyecto del cliente, puede realizar cambios en cualquier forma del producto, agregar eventos, nuevos objetos y propiedades, acciones, cambiar el dise帽o y mucho m谩s.
- La entrega de nuevas mejoras requeridas por el cliente se acelera significativamente . Con cada solicitud de cambio, no necesita pensar c贸mo afectar谩 a otros clientes. Debido a esto, se pueden hacer muchas mejoras y ponerlas en funcionamiento lo antes posible (a menudo en unas pocas horas).
- Un esquema m谩s conveniente para expandir la funcionalidad del producto . Primero, se puede incluir cualquier funcionalidad para un cliente espec铆fico que est茅 listo para probarlo, y luego, en caso de una implementaci贸n exitosa, los m贸dulos se transfieren completamente al repositorio del producto.
- C贸digo base de independencia . Dado que se proporcionan muchas mejoras bajo los contratos de servicio al cliente, formalmente, todo el c贸digo desarrollado bajo estos contratos pertenece al cliente. Con este esquema, se garantiza una separaci贸n completa del c贸digo del producto que pertenece al proveedor del c贸digo propiedad del cliente. Previa solicitud, transferimos el repositorio al servidor del cliente, donde puede modificar la funcionalidad que necesita con sus propios desarrolladores. Adem谩s, si el proveedor otorga licencias para m贸dulos de productos individuales, el cliente no tiene el c贸digo fuente de los m贸dulos para los cuales no hay licencia. Por lo tanto, no tiene la capacidad t茅cnica para conectarlos de forma independiente en violaci贸n de las condiciones de licencia.
El esquema de modularidad descrito anteriormente con la ayuda de extensiones en la programaci贸n a menudo se llama
mezclar . Por ejemplo, Microsoft Dynamics introdujo recientemente el concepto de extensi贸n, que tambi茅n le permite expandir los m贸dulos base. Sin embargo, all铆 se requiere mucha programaci贸n de nivel inferior, lo que a su vez requiere calificaciones m谩s altas de los desarrolladores. Adem谩s, a diferencia de lsFusion, la expansi贸n de eventos y restricciones requiere los "puntos de entrada" iniciales al producto para aprovechar esto.
En este momento, de acuerdo con el esquema descrito anteriormente, apoyamos e implementamos un
sistema ERP para la venta minorista con m谩s de 30 clientes relativamente grandes, que consta de m谩s de 1000 m贸dulos. Entre los clientes hay redes de bienes de consumo, as铆 como farmacias, tiendas de ropa, cadenas de tiendas de lencer铆a, mayoristas y otros. En el producto, respectivamente, hay categor铆as separadas de m贸dulos que est谩n conectados dependiendo de la industria y los procesos comerciales utilizados.