He estado trabajando para una empresa de consultoría durante algún tiempo, con clientes de varios tamaños, y he visto aplicaciones web que varían en complejidad desde muy simple:
- MVC
- Capa de servicio
- EF
- DB
Para realmente complejo:
- MVC
- UoW
- DI / IoC
- Repositorio
- Servicio
- Pruebas de IU
- Pruebas unitarias
- Pruebas de integración
Pero en ambos extremos del espectro, los requisitos de calidad son casi los mismos. En proyectos simples, los nuevos desarrolladores / consultores pueden subir, hacer cambios y contribuir de inmediato, sin tener que atravesar 6 capas de abstracción para comprender lo que está sucediendo, o arriesgarse a malinterpretar alguna abstracción compleja y costar más adelante.
En todos los casos, nunca hubo necesidad de hacer que el código sea intercambiable o reutilizable, y las pruebas nunca se mantuvieron realmente después de la primera iteración porque los requisitos cambiaron, era demasiado lento, los plazos, la presión comercial, etc.
Entonces si - al final -
- las pruebas y las interfaces no se usan
- El desarrollo rápido (léase: ahorro de costos) es una prioridad
- los requisitos del proyecto cambiarán mucho durante el desarrollo
... ¿sería un error recomendar una arquitectura súper simple, incluso para resolver un problema complejo, para un cliente empresarial? ¿Es la complejidad lo que define las soluciones empresariales, o es la confiabilidad, # usuarios concurrentes, facilidad de mantenimiento o todo lo anterior?
Sé que esta es una pregunta muy vaga, y cualquier respuesta no se aplicaría a todos los casos, pero estoy interesado en escuchar a los desarrolladores / consultores que han estado en el negocio por un tiempo y que han trabajado con estos diversos grados de complejidad. , para saber si las abstracciones geniales pero costosas valen el costo total, al menos mientras el proyecto está en desarrollo.
Respuestas:
Depende del cliente. Muchos estarán bien con un enfoque más directo. Algunos pensarán que eres incompetente porque ese enfoque simple no resolverá sus problemas: todo "eso debe ser súper barato por una razón ...", algo que hace que algunas cosas sean mucho más caras de lo que cuesta hacerlas.
Yo diría que no hay manera en el infierno de que pueda hacer de manera rentable software no trivial sin ninguno de estos. Como empresa, si intentaras venderme algo sin ellos, me temo que me cargarás con una pila de caca de perro humeante completamente inflexible e imposible de mantener. ( Editar: para ser claros, estoy hablando de interfaces aquí, no
interfaces
. Los programas de procedimiento y funcionales no son todo un montón de basura, a pesar de que carecen de interfaces de estilo Java).Como diseñadores de programas, necesitamos hacer conjeturas educadas sobre dónde cambiarán las cosas y dibujar líneas allí para que las cosas que cambien puedan hacerlo de manera rápida, fácil y correcta. Las buenas abstracciones le ahorrarán dinero con el tiempo porque el cambio inevitable se vuelve barato.
Pero no se equivoque, el término "astronauta de la arquitectura" existe por una razón. No siempre estás construyendo el transbordador espacial. Agregar malas abstracciones que existen en medio de cosas que necesitan cambiar, o existen para apoyar un cambio que no existe ... pueden costarle.
Pero en mi experiencia, he oído gente se queja de más de código abstraída, pero sólo he visto proyectos fracasan debido al código bajo-abstracta.
fuente
Al arquitecto, o no al arquitecto
Para reformular Einstein, "las cosas deberían ser lo más simples posible, pero no más simples". Es importante comprender el verdadero uso de algunas arquitecturas, y no son necesariamente para el rendimiento individual y, a menudo, tampoco para la satisfacción laboral.
A veces las arquitecturas son tan complicadas porque un proyecto empresarial es tan grande, con tanta gente en el trabajo, que la arquitectura es en gran medida para permitir que tanta gente trabaje hacia algo sin que todos se tropiecen con los demás. Son, a veces, poco más que complejidad añadida que reduce la productividad individual y hace que el trabajo sea más difícil, pero permite que un gran número de personas trabajen. Esto funciona cuando el esfuerzo adicional supera la disminución individual de la voluntad de vivir, err, quiero decir "productividad".
¿Es esta la situación de tu cliente? Bueno, si su presupuesto no es de millones para este proyecto, tal vez no. Si está por debajo de 100k, entonces seguramente no. Construyes un búnker de hormigón para un reactor nuclear, no una estufa de leña :)
No es necesariamente incorrecto sugerir "lo más simple que podría funcionar" para su cliente, si eso es lo que requiere la situación. Podría ser la mejor manera posible de manejarlo. La forma más fácil de verlo es compararlo con proyectos de código abierto / disponibles en el mercado que están diseñados para realizar una tarea similar (de todos modos, esta es su investigación de mercado de diligencia debida) y ver qué les llevó a hacer lo que hicieron.
Por supuesto, cuando trabajas con millones de dólares, debes tener en cuenta algunos incentivos perversos en juego. En resumen, "cubriendo el culo": si recomienda un sistema de arquitectura súper complejo que requiere un doctorado para comprenderlo correctamente, ¿cuándo fue el infierno quién fue la culpa? No es suyo, por supuesto, sugirió solo lo mejor en tecnologías sofisticadas que todos dicen que es lo mejor, pero son "complicados" y "difíciles", por lo que la culpa es de las personas que intentaron implementarlo. Deben no haber sido lo suficientemente inteligentes o lo suficientemente hábiles ... en otras palabras, se dan muchos consejos para asegurarse de que no se vea mal cuando los proyectos fracasan, lo que inevitablemente deben hacer ya que no todos los proyectos tienen éxito. Es un mal juju, pero es un hecho de nuestra realidad.
Incumplimiento de seguimiento
Sugeriría que la falta de actualizar continuamente las pruebas y el seguimiento de las decisiones de arquitectura (lanzar planes cuando cambian en lugar de actualizarlos, etc.) es la razón por la que tantos sistemas terminan siendo rechazados y reescritos desde cero o reemplazados por un nuevo ' solución 'unos años más adelante.
Cuando las cosas que imponen claridad y consistencia se descartan por conveniencia, a veces es fácil pensar que fuiste muy astuto y realmente estás "haciendo las cosas" cuando en realidad hiciste cambios futuros más difíciles y más complicados; Es muy común robar de la productividad futura para obtener ganancias inmediatas. Es malo específicamente cuando nadie se da cuenta de que eso es lo que está sucediendo.
Las pruebas, por ejemplo, son especialmente adecuadas para cuando las cosas cambian. Cambia las pruebas para reflejar cuál es la nueva dirección, y luego arregla todas las cosas que ahora están "rotas" porque las personas cambiaron de opinión o se dieron cuenta de que se perdieron algo la última vez. Esto es como dejar de dormir porque tienes mucho que hacer esta semana: va a hacer las cosas más difíciles.
En conclusión, "depende" (útil, ¿no es así?)
La complejidad arquitectónica es un costo indirecto, como alquilar un espacio más grande para un negocio de ladrillo y mortero; solo tiene sentido cuando existe una complejidad real que necesita ser gestionada. Si se trata de un equipo de 3 personas trabajando en una solución relativamente convencional, MVC simple y herramientas mínimas probablemente sean completamente suficientes.
Si se trata de una solución de software empresarial compleja, de múltiples subsistemas, con millones de presupuesto y al menos media docena de equipos de 3 a 5? Vas a rogar por el dulce, dulce amor que solo la ingeniería de ida y vuelta en el análisis de programas orientado a objetos y todos sus cuadros, diagramas y modelos pueden brindar. Cualquier cosa que lo ayude a evitar que las docenas o cientos de pares de ojos no lo miren sin pestañear, preguntándose qué se supone que deben hacer hoy y cómo se supone que deben hacer algo.
fuente
Bienvenido a consultar.
Un gran lugar para ganar un montón de dinero entregando rápidamente características a los clientes.
Si busca trabajar creando un software hermoso, adaptable y fácil de mantener que funcione bien tanto ahora como en el futuro, le recomiendo que trabaje en una industria específica, como la salud o el gobierno, donde pueda crear un mejor nicho para un trabajo de calidad.
fuente
Lo que se obtiene de un diseño sólido es un ciclo de cambio más confiable a largo plazo. El costo es inicialmente más alto porque necesita programadores debidamente capacitados y un diseño adecuado, sin embargo, la intención es evitar que el costo de los cambios posteriores se dispare fuera de control.
Sin una arquitectura sólida, los cambios solo son más baratos al principio. A medida que el proyecto evoluciona, los cambios se vuelven cada vez más costosos. Esto, combinado con un deseo de mano de obra más barata y una iteración más rápida, podría matar el proyecto ya que los cambios eventualmente costarán más de lo que la compañía está dispuesta a pagar y tomará más tiempo del que la compañía puede esperar. Los cambios posteriores que podrían haber requerido un equipo promedio y un tiempo promedio requerirán un equipo sobrehumano y un tiempo prolongado para examinar los años de código y refactorizar lo suficiente como para realizar cambios de manera segura.
Si el cliente entiende y quiere hacer este sacrificio, realice los cambios que necesite el método más rápido. Pero no es prudente (y posiblemente deshonesto) hacer esas compensaciones para ellos, ya que este proceso afectará sus decisiones comerciales.
Parte del trabajo es comprender todas esas abstracciones que enumeró, no solo preguntar "¿Son necesarias?" pero para comprender cuándo y por qué son necesarios, y descubrir cómo aplicar esos patrones como parte del trabajo con el software.
Otra parte del trabajo es comprender que los clientes a menudo juzgan el trabajo por lo que pueden ver (la interfaz de usuario, la funcionalidad), y deben ser educados sobre lo que no pueden ver (el estado de la base de código).
fuente
Complicado es relativo. Cuando comencé a aprender a programar el concepto de punteros, las listas especialmente vinculadas eran complicadas ("¿Cómo se puede tener algo que se tenga como un campo?"), Pero una vez que entendí el concepto, eso fue simple.
Cuando comencé a aprender programación funcional, el concepto de lambda parecía complejo. Pero luego lo relacioné con la idea de un puntero de función de C ++ y fue simple. Y así sucesivamente con curry, y terminaciones, y así sucesivamente.
Cuando comencé a aprender TDD, pensé que era complejo o que agregaba gastos generales al proceso de desarrollo. Ahora no creo que mi código esté completo a menos que tenga pruebas que al menos cubran el camino feliz. La inyección de dependencia y el uso de interfaces en lugar de clases concretas parecen complejos al principio. Pero le permiten construir su código con la suposición de que resolverá los detalles de las dependencias y se centrará primero en las construcciones de nivel superior.
Echa un vistazo a Clean Code y The Clean Coder por "Uncle Bob" Martin. El primero habla sobre cómo codificar mejor. El segundo habla sobre cómo ser un mejor codificador. Hay una diferencia entre los dos.
Para dar una analogía, estoy aprendiendo guitarra. Estoy en el escenario donde puedo tocar melodías y acordes simples. La transición entre acordes y posiciones es difícil. Al practicar más, podré realizar esas transiciones más fácilmente y se convertirá en una segunda naturaleza para mí.
Utilizo el patrón de repositorio / unidad de trabajo para poder usar un repositorio en memoria mientras construyo la funcionalidad básica y la convierto en un repositorio "sql lite" u "odata" a medida que me acerco a la entrega. Tenga en cuenta que esto me permite completar más funciones incluso antes de que la infraestructura final esté en su lugar (o incluso decidida). Las abstracciones me permiten crear simulacros y trozos más fácilmente para que pueda verificar que el código que depende de las abstracciones funciona como se esperaba. Nuevamente, puedo completar funciones de arriba hacia abajo.
Diría que está mal crear la infraestructura primero. El simple hecho es que es anti-ágil. Si paso un sprint en "infraestructura", estoy construyendo cosas que ni siquiera estoy seguro de que necesite al final y los usuarios no tendrán nada que ver para dar su opinión.
Eso es lo que proporcionan las abstracciones. Cuanto más practiques usarlos, más se convertirán en una segunda naturaleza, y mirarás hacia atrás en esta discusión y te maravillarás hasta qué punto te has desarrollado. Al igual que con suerte, en unos años me preguntaré cómo las transiciones de acordes siempre fueron un desafío para mí.
fuente
No estoy totalmente de acuerdo con su afirmación de que la abstracción aumenta automáticamente la complejidad. La abstracción es la razón principal por la que hoy en día uno no tiene que resolver el código de la máquina.
El problema a veces con las abstracciones es que tienden a centrarse en el funcionamiento interno en lugar de ocultar la complejidad a sus usuarios finales. Las abstracciones deben aislar la lógica y promover la reutilización. Además, creo que las pruebas son una excelente manera de desafiar el diseño arquitectónico. Principalmente porque te obliga a mirar tu código desde el punto de vista del usuario.
Los problemas que mencionó sobre la falta de tiempo son la causa principal del mal diseño. El buen diseño generalmente no llega instantáneamente, sino a través de iteraciones y refinamiento. La forma en que generalmente extraemos los requisitos de nuestros clientes es a través de historias de usuarios. De esta forma, el cliente puede pensar qué y cómo quiere usar el sistema. Además, si el arquitecto conoce las intenciones del sistema, se pueden elegir decisiones de diseño o técnicas de abstracción apropiadas para agregar flexibilidad al sistema. No porque sean geniales o agradables.
fuente
Abordando sus preguntas ...
Absolutamente no.
Desde la perspectiva del cliente
Como se indicó anteriormente, depende en gran medida del cliente. También depende de su capacidad para medir con precisión qué soluciones son adecuadas para su cliente. Si bien siempre habrá un costo percibido para el valor deseado, como consultor, es su trabajo establecer las expectativas apropiadas del cliente. En algunos casos, tendrá que cumplir con esa percepción. En otros, será mejor para usted corregirlos. Después de todo, debe ser el experto para su cliente. Y si no lo eres, debes tener el conocimiento para poder convertirte en ese experto. Por eso te pagan.
Desde la perspectiva del desarrollador
La parte más difícil de elegir qué arquitectura usar es, a menudo, estimar correctamente la cantidad de trabajo requerida para utilizar la tecnología para satisfacer las necesidades específicas. Esto puede conducir rápidamente a proyectos que no cumplen con las expectativas del cliente. Comprenda que algunos proyectos en realidad se hacen más rápido utilizando estas piezas de código "complejas" que usted menciona. También se entiende que algunos no lo son. Debe proporcionar esa medida, en función de lo que usted o su equipo sepan.
Si bien los detalles pueden variar, en general, una solución empresarial es una solución de software que se aplica a una amplia audiencia mixta. El número de usuarios concurrentes puede o no ser un factor, aunque a menudo lo es. El número total de usuarios, con frecuencia en una variedad de roles comerciales, es uno de los factores determinantes más importantes en cuanto a si la solución es "empresarial".
Muchas soluciones empresariales son muy complejas, pero algunas son bastante simples. Si bien la empresa le da un aire de confiabilidad (y ciertamente debe ajustarse a un determinado estándar), las diferentes soluciones tienen diferentes niveles de confiabilidad.
La facilidad de mantenimiento es algo por lo que creo que todo desarrollador (independiente o miembro del equipo) se esfuerza, no necesariamente se logra tan fácilmente. Lo importante es que haya un procedimiento de mantenimiento que tenga pautas firmes, en lugar de que sea "fácil". Recuerde, las diferentes bases de código tendrán niveles de facilidad sustancialmente diferentes dependiendo de las filosofías, las metodologías, la actividad del entorno (comercial) y la complejidad del código.
Reaccionando a sus otras declaraciones ...
A menudo nunca hay una necesidad específica de hacerlo. Sin embargo, este debería ser su objetivo, en todo momento. Considere esto ... Es posible que tenga un cliente que requiera la capacidad de acceder o mostrar su calendario desde la página web. Si hace que su propio código sea reutilizable, cuando otro cliente solicite lo mismo, ya tendrá parte del trabajo realizado. Si no lo hace, debe hacerlo de nuevo. Cada problema del cliente es a menudo uno que otro cliente en el futuro puede necesitar. En otras palabras, cada cliente con el que trabaje debe tener el potencial de reducir el costo del trabajo para sus futuros clientes (no necesariamente el costo del producto).
Yo diría aquí que la metodología de prueba no fue lo suficientemente abstracta. Recientemente utilicé un código que hizo sus propias pruebas unitarias directamente dentro de sí mismo. Se hicieron una costumbre
assert
y unaexpect
función que se adaptaban a las necesidades del proyecto. Cada vez que se necesita una prueba unitaria, se puede aplicar sin siquiera ajustar el código. De hecho, el código se distribuye activamente con las afirmaciones y espera aún allí. Hizo esas verificaciones como parte del código de trabajo.A menudo he descubierto que la presión comercial adicional y los plazos que impiden el proceso de codificación han sido culpa del desarrollador, no del cliente. Si bien este no es siempre el caso, muchas veces la presión empresarial es causada por la percepción de incumplimiento de las expectativas del cliente. Cuando las fechas límite impiden el código, a menudo se debe a que el desarrollador no pudo medir con precisión la cantidad de trabajo requerida para el código funcional utilizable. En otras palabras, programarlos (los clientes lo esperan) , medirlos (los futuros clientes lo esperan) , realizarlos (los usuarios lo requieren) y recibir un pago por ellos (su contrato debe exigirlo) .
fuente
Mucho de lo que plantea esta pregunta es increíblemente subjetivo, creo que es importante sacar algunos datos sobre los costos compuestos de la complejidad arquitectónica. Hay un estudio de caso realmente interesante del MIT Sloan que mide
Básicamente, diría que hay algún medio feliz en el que cada base de código debe esforzarse para lograr la simplicidad (A) para que la productividad del desarrollador sea alta y (B) la previsión para que la funcionalidad no se vea comprometida cuando se agregan nuevas características.
El estudio de caso fue sobre esta compañía con una base de código monolítico que tenía un núcleo de alta complejidad (piense en utilidades y cosas de alta abstracción) y periferia de menor complejidad (piense en características más nuevas con pocas dependencias). Entre la periferia y el núcleo, la productividad del desarrollador disminuyó en un 50% (locura) y los defectos aumentaron 2.6x.
fuente
Puedo relacionarme con sus dudas con respecto a las complejas técnicas de desarrollo de software, y supongo que hay muchas personas que pueden, exactamente por las razones que mencionó: agregan una sobrecarga a la creación inicial de un nuevo sistema y no siempre muestran instantáneamente su beneficios.
Claramente, eso no significa que no existan, para cada concepto hay una razón, la mayoría de las veces una buena. En total, deberían reducir el trabajo necesario para finalizar un proyecto y luego mejorarlo.
En teoría, por supuesto, y apostaría a que aprendió todos esos beneficios teóricos y ahora más que nunca los ve fracasar. Y eso puede tener una buena razón, también, usar un concepto correcto no es tan fácil como entender por qué se usa, y si bien puede tener la experiencia necesaria para decidir cuándo abstraer y cuándo no, sus clientes aún pueden no hacerlo.
Usar un concepto en cada punto posible de su proyecto puede costarle mucho tiempo (vea la respuesta de Telatsyns para una oración simple y clara sobre eso) e incluso usar un concepto en el lugar correcto puede costarle, si no tiene suficiente experiencia para usarlo. . Como dijiste, esos no son conceptos simples, pero a veces realmente complejos que deben adaptarse a tu situación, una comprensión teórica no puede ser suficiente para usarlo de manera rápida y correcta.
Y por esas razones, no es sorprendente que sus clientes sin darse cuenta realmente se alejen de los conceptos y abandonen sus pruebas y abstracciones y comiencen a trabajar de nuevo de manera simple.
Con respecto a la gran barrera que puede ser la ingeniería de software, le sugiero este artículo: Las Siete Etapas de Experiencia en Ingeniería de Software Me topé con él en algún lugar de esta página y expresa algunos pensamientos y experiencias realmente interesantes.
fuente
Yo diría que si está desarrollando aplicaciones para la empresa, usted o alguien a cargo de sus proyectos (Proj mgr) debería tener una mejor idea de la cantidad de trabajo que debería dedicarse a los proyectos. Si está viendo una pérdida de tiempo, entonces debe discutir su punto de vista con Proj mgr. La forma en que me siento y opero siempre se basa en un juicio por tipo de base, pero siempre busco a ese cliente que te lanzará una bola curva. Me equivocaría al hacer un buen trabajo punteando tus I's y cruzando tus t's. También me aseguraría de contar con la gestión adecuada del ciclo de vida de la aplicación para que la mayor parte de la sobrecarga se automatice y ahorre tiempo, etc. ¡Espero que sea útil!
fuente