architecture - resueltos - la descarga de solidos suspendidos desde una mina de fosfato
Síntomas concretos de ingeniería excesiva (17)
Recientemente me encontré en la posición de explicar una aplicación (interna) que escribí a dos candidatos que a mi empresa le gusta contratar para ayudar en el mantenimiento y agregar características menores.
Es la primera aplicación de "producción" que he escrito, tiene 45k LOC y pasé casi dos años de desarrollo "solo" en ella. Soy bastante joven (18) y escribí la aplicación desde cero mientras me contrataban como sustituto de un antiguo desarrollador que dejó la empresa. Sin experiencia en el diseño de aplicaciones de este tamaño, intenté usar patrones comunes de arquitectura y diseño.
Hoy sé que he realizado una seria ingeniería excesiva, por ejemplo, utilizando una arquitectura de seguimiento de cambios desconectada en lugar del patrón Unidad de Trabajo, que el ORM elegido ya ha implementado. Probablemente nunca tendré que ir "real" en tres niveles.
Ambos candidatos tienen más de 10 años de experiencia en el desarrollo de aplicaciones internas con la plataforma correspondiente. Siendo la mitad de su edad y poca experiencia, respeto su opinión. Cuando les estaba explicando la arquitectura de la aplicación, los comentarios estaban en la línea de:
- Dios mío, nadie me pagaría para hacer cosas así, tengo que hacer las cosas
- Quédate con lo que hace el framework, no uses bibliotecas / tecnologías de lujo
- No envuelva el código del marco. En un equipo, todos escribirán su propio código de envoltura de todos modos.
- Estás utilizando .NET 3.5? Bueno, estamos usando 2.0.
- ¿Qué me compran esas cosas de LINQ? Toda esta consulta de composición y proyección parece demasiado complicada.
Ahora me pregunto:
¿Soy un astronauta de la arquitectura ? ¿Cómo sé que voy demasiado lejos con la arquitectura? ¿Cuáles son los síntomas comunes de la ingeniería excesiva?
¿Cuáles son los síntomas comunes de la ingeniería excesiva?
Código que resuelve problemas que no tienes.
¿Implementaste tu proyecto dentro de un marco de tiempo razonable? ¿Está funcionando ahora? Si es así, probablemente pueda relajarse un poco, ya que uno de los peores problemas con la ingeniería excesiva nunca es hacer nada útil.
Los chicos con los que habló también pueden tener algunas buenas sugerencias, pero eso no significa que deba tomar todo lo que dicen como evangelio. Por ejemplo, usar una versión reciente de .NET en un proyecto nuevo no me parece que deba preocuparme. ¿Están realmente quejándose de eso?
Como alguien que ha estado desarrollando software profesionalmente durante 24 años, todo lo que puedo decir es que este problema (hacer la llamada al nivel de abstracción requerido para un problema en particular) es la parte más difícil de mi trabajo diario de diseño y programación.
En los "viejos" días, abundaba la falta de ingeniería, lo que llevó a todas las metodologías y prácticas estructuradas. Ahora, parece que hemos ido por el otro lado. No hay una respuesta fácil y, a veces, solo sabrá si está bajo o sobre diseñado en retrospectiva ;)
He tenido varias experiencias en retrospectiva en las que me dije a mí mismo: "Ojalá no hubiera complicado tanto esto", sino también "Si tan solo escuchara la vocecita en la parte posterior de mi cabeza y la hiciera un poco más". genérico aquí ".
Todavía tengo que destilar reglas absolutas para hacer la llamada ...
Sospecho que soy propenso a la ingeniería excesiva, así que he hecho de esta foto el fondo de pantalla de mi PC
Cuando la computadora de un compañero de trabajo pasa volando más allá de su cabeza porque han pasado las últimas 6 horas tratando de hacer aparecer un cuadro de diálogo con su ridículo marco, ese es un síntoma bastante concreto.
En cuanto a la pregunta sobre si usted es un astronauta de la arquitectura: si es consciente del peligro que lo pone por delante de muchas personas. Tampoco querrás seguir el camino de tus oradores de vacas, parece que algunos de ellos se han convertido en crujientes crujidos.
La ingeniería excesiva es el resultado de un problema con la priorización que resultó en que alguna parte del sistema recibió demasiada atención. Por lo tanto, el síntoma más evidente de la ingeniería excesiva sería que puede ver todo alrededor de otras partes del sistema que están sufriendo por falta de atención.
(También existe una tendencia a que la ingeniería excesiva exponga al sistema a mayores riesgos de mal diseño, debido a la mayor complicación y la cantidad de especulaciones propensas a errores involucradas en la decisión de qué aspectos se deben aplicar a la ingeniería excesiva, pero como se señala en un comentario, que no sigue automáticamente.)
En mi humilde opinión, la mayoría de los comentarios que recibiste sobre tu aplicación no son realmente sobre ingeniería excesiva, porque ingeniería excesiva no tiene que ver con tecnología. Se trata de la arquitectura. Las nuevas tecnologías se pueden aprender y comprender en un tiempo razonable. Comprender una aplicación sobre diseñada es generalmente mucho más difícil y, a veces, incluso imposible. Esto hace que los puntos 2, 4 y 5 sean inválidos. El primer punto no es realmente válido porque, obviamente, le pagaron por escribir la solicitud tal como está y si funciona, no tiene ningún problema aquí.
Esta es mi "prueba rápida" para averiguar si una aplicación tiende a diseñarse en exceso:
- Envoltorios para "todo": los envoltorios son útiles, pero es fácil sobrepasarlos Compruebe si solo envuelve las cosas que realmente necesitan ser envueltas. (Básicamente envolví mi propio envoltorio una vez. Sé de lo que estoy hablando ;-).)
- Reinventando la rueda: un clásico. Esto es muy común y ya lo mencionaste. ¿Implementaste alguna funcionalidad porque necesitabas lo que querías ? ¿Qué hace su marco de trabajo que otras bibliotecas disponibles no?
- "Se siente" sobre-diseñado: este es el punto más importante pero también el más difícil de ver. Eche un vistazo a su código y observe qué partes se sienten demasiado complicadas. Pregúntese entonces si hay una manera más fácil de implementarlo y por qué no eligió de esta manera. Si no tienes una buena respuesta, esta parte probablemente esté sobre diseñada.
Estos son solo consejos rápidos que utilizo para mis aplicaciones. No se garantiza que sean el "todo y el final" de la "detección de ingeniería excesiva".
En un enfoque más genérico y de alto nivel,
I feel that when there''s a gap between the complexity of the problem and
the complexity of the solution, then you have a clear case of overengineering.
¿Cuáles son las formas de lograrlo? Resuelva los problemas que no tiene, al ver el problema más complejo de lo que realmente es, tratando de pronosticar demasiado en el futuro, creando cosas demasiado genéricas, entre otras.
Evitar cualquier uso de YAGNI , DRY y KISS vienen a la mente al considerar las cosas que están sobre diseñadas. Si hay muchas partes que parecen estar parcialmente completadas y muchas partes del código que parecen tener un "¿Qué pasa si sucede? ¿Qué pasa si sucede?" Sentirlo, ese sería otro punto. Ignorar los buenos principios del diseño OO o los principios SÓLIDOS sería otra nota. Si crees que has escrito el código perfecto, eso sería otra señal de problemas, ya que es extremadamente raro que alguien escriba algo que no pueda mejorarse de una manera u otra.
OMI, tenga en cuenta que algunas personas pueden ser demasiado críticas con su trabajo, ya que parte de cualquier base de código puede implicar que a las personas les gusten las cosas de una manera determinada, por ejemplo, nombrar convenciones sobre métodos, pruebas y variables. Esa es la forma como es. Ahora, lo que debe tener en cuenta es cómo manejar a las personas en situaciones como el conflict o la persuasion/influence , donde hay herramientas que pueden ayudar.
Intente evaluar si ha hecho cosas para minimizar el trabajo durante la vida útil esperada del código. Esto incluye el mantenimiento, así como el desarrollo.
En el ciclo de vida del código, recuerde que la vida del código no es la misma que la de la aplicación. Tal vez sea mejor escribir primero un prototipo rápido, luego reingresar / refactorizar después de una mejor comprensión del dominio. En esta situación, el ciclo de vida es muy corto, así que manténgalo simple.
Además, diferentes aplicaciones requieren diferentes recursos de ingeniería. ¿Esta aplicación costará vidas si falla? Es decir, ¿es un controlador para un corazón mecánico, o para los cohetes de navegación del transbordador espacial? ¿O es una lista de contactos para adolescentes aburridos?
No eres un astronauta de la arquitectura. LINQ es bastante simple y básico y útil, por ejemplo. Lo mismo ocurre con .NET 3.5.
Al mismo tiempo, usted es el novato en el equipo y va a tener algún tipo de ribbing, incluso si les gusta lo que hizo.
Toma todo con un grano de sal. Solo acepta sus críticas, asiente y toma una cerveza con ellos después.
Si te piden que lo cambies, entonces tu comentario es "cielos ... Sé que lo hice mal, pero funciona y va a ser demasiado problema cambiarlo".
Para la mayoría de las aplicaciones comerciales internas, la mayoría de su código debe estar relacionado con la implementación de problemas comerciales, y no con preocupaciones técnicas no relacionadas con el negocio (como su "arquitectura de seguimiento de cambios desconectada"). Los marcos actualmente disponibles son bastante maduros y admiten los casos de uso más comunes. Si está inventando una nueva tecnología o (en el contexto del desarrollo de aplicaciones empresariales) simplemente está envolviendo algún otro marco o biblioteca existente por el simple hecho de envolver, probablemente lo esté haciendo mal. Idealmente, cada pieza de arquitectura que construya debe ser rastreable a algún requerimiento comercial. Mantenlo simple.
Quiero ofrecer una perspectiva diferente, pero creo que este término debería tacharse y reemplazarse con una descripción más apropiada. Coloca un estigma en la "ingeniería" que debería ser sobre la simplicidad, la facilidad de mantenimiento y la practicidad sobre todo, cuando gran parte de lo que se describe como "ingeniería excesiva" tiene las cualidades opuestas precisas (como si se tratara de una ingeniería excesiva o se tomara muy en serio). , se supone que produce las soluciones más complicadas). Es común, por ejemplo, ver una correlación entre el exceso de ingeniería y el procedimiento de prueba deficiente (al menos yo he visto que estos dos van de la mano), y qué tipo de exceso en ingeniería realiza la cantidad mínima de pruebas formales ?
Lo digo desde un punto de vista en el que a menudo escuché a los gerentes de software y dinosaurios ocasionales que no eran tan expertos en el tema de los EE. UU. Para decir este término a cualquiera que intente, por ejemplo, reducir los costos de mantenimiento en un sistema o proponer procedimientos de prueba más sólidos estándares de seguridad. Es demasiado fácil para el lego pensar que cualquier tipo de enfoque serio en la ingeniería de sonido, las pruebas y la no producción de código a la velocidad que quieren es una "ingeniería excesiva".
Hay muchos que reconocen genuinamente los verdaderos olores de la "ingeniería excesiva", pero el término es, al menos, posiblemente engañoso.
En cuanto a los síntomas, además de los excelentes ya proporcionados, para mí es un punto ciego para poder evaluar y reevaluar adecuadamente el trabajo que se encuentra frente a usted. Los programadores pueden construir mundos en su imaginación, obsesionarse y absorberse con conceptos imponentes. Si bien es una respuesta aburrida y genérica, eso puede llevar al peligro de no ver los problemas y prioridades reales justo debajo de nuestras narices. Conceptualizar demasiado profundo es a menudo desarrollar un punto ciego en cuanto a lo que está justo delante de nosotros, complicar los problemas, perder el contacto con la realidad y las necesidades reales del usuario final. Para mí los mayores síntomas a los que hay que prestar atención giran en torno a la psicología.
Todo tipo de profesiones que giran en torno a la producción son vulnerables a esta tendencia básica en la que uno pierde de vista los problemas reales e inmediatos por resolver como resultado de obsesionarse demasiado con los conceptos (por ejemplo, un director de cine). Con la programación en general, una forma de combatirla es favorecer la claridad, la simplicidad, la practicidad, la codificación antes de conceptualizar algo en el noveno grado (dándonos más tiempo para reevaluar antes de que nos enamoremos demasiado de cualquier idea). Uno no puede ir demasiado lejos abrazando estos ideales, pero la clave para mí es evitar desarrollar ese punto ciego que nos impide evaluar adecuadamente nuestro propio trabajo. Una base de código con exceso de ingeniería no se produce de la noche a la mañana: se necesita una gran cantidad de trabajo dedicado en la dirección equivocada para lograrlo, y para mí, el mayor problema evitable no está relacionado con la previsión, pero a menudo desarrolla la visión retrospectiva demasiado tarde.
Una señal de advertencia muy fuerte de la sobreingeniería es cuando todo pasa por tanta indirección que es difícil encontrar la pieza de código que realmente implementa alguna funcionalidad concreta, a nivel de dominio. Si encuentra que la mayoría de sus funciones realizan un trabajo concreto muy pequeño y simplemente llama a otras funciones virtuales, puede tener un problema.
la mitad son hombres viejos (estoy en su liga) que se adhieren a la máquina de vapor probada y verdadera que han conocido. La otra mitad es cierta, pero en realidad no te dice nada nuevo.
Aparte de eso, la respuesta de Jeff Sternal es estelar.
Aburrimiento
El aburrimiento es un buen precursor de código sobre-diseñado. Admito que, cuando obtuve mi primer trabajo, me sentí tan infrautilizado. Estaba aburrida. Y cuando me aburrí, escribí código. No cualquier código - CATEDRALES DE CÓDIGO.
No, en serio, tenía una imagen mental de mi código y abstracciones como grandes torres con agujas de color dorado, contrafuertes voladores de ónix vítreo, una maravillosa bóveda con soporte de cúpulas arqueadas rematadas con una hermosa tracería geométrica, etc. etc.
Fue realmente fascinante ver los patrones trabajando juntos para mí mismo, pero en retrospectiva, estoy completamente avergonzado por el desorden impío que dejé atrás.
Si está escribiendo sus propios marcos y código DSL para pasar las horas menos estimulantes en el trabajo, simplemente deténgase. Es mejor pasar el tiempo leyendo Wards Wiki , o escribiendo un libro de código abierto , o puede que desee pedir más trabajo a la gerencia.
Complementos que proporcionan funcionalidad intrínseca a tu aplicación
Afrontémoslo, las arquitecturas conectables son increíblemente atractivas y divertidas de escribir. Sin embargo, esta es otra de esas áreas en las que debe preguntarse: "¿Realmente necesito hacerlo de esta manera?".
Si no necesita agregar ad-hoc a su aplicación, no espere que nadie escriba extensiones de terceros, y el alcance de su aplicación está bien definido, no necesita una arquitectura conectable.
No debe escribir complementos para admitir la funcionalidad intrínseca en su aplicación. Digamos que estabas escribiendo un programa de pintura; probablemente soportaría complementos para guardar archivos en múltiples formatos, pero no necesitaría un administrador de deshacer conectable o un diálogo de búsqueda de archivos.
Escribiendo tu propio framework
Las probabilidades son, alguien ya lo ha hecho. Más que eso, ya lo han hecho 1000 veces mejor que tú. Más que eso, lo que hayan hecho es probablemente ya un estándar de la industria, por lo que aprender de la tecnología lo hará más competitivo en otros trabajos.
En la última empresa donde trabajé, un programador había trabajado solo en sus proyectos durante la mayor parte de su mandato. Escribió una de las aplicaciones más populares de la compañía y fue considerado como el mejor del equipo, pero en mi opinión, tenía la mala costumbre de escribir todo lo que necesitaba desde cero.
Había escrito su propio marco de inyección de dependencias, su propio ORM, un marco de prueba de unidad (que, inexplicablemente, se veía y actuaba de manera muy similar a NUnit, ¿por qué no usó NUnit?), Un marco para crear objetos de fábrica (un " fábrica de fábrica " lo llamaría).
Eso sí, el código era realmente notable, pero ¿cuál era el punto?
Escribiendo una mejor biblioteca principal
En mi empresa actual, siempre parecía que los programadores escribían cantidades inútiles de código para replicar características ya presentes en el marco .NET.
Entre otras cosas, escribieron:
- Un marco de directorio activo para la autenticación de formularios en formularios web ASP.NET - inexplicable porque ASP.NET tiene esta función incorporada.
- Temas y skins intercambiables en caliente para sitios web: también inexplicables, ya que el código era menos funcional que los temas ASP.NET incorporados y requería un 1000% más de hinchazón.
- Ellos inexplicablemente escribieron sus propios conjuntos de datos y adaptadores de datos. Estos objetos proporcionaron menos funcionalidad que los conjuntos de datos escritos que VS autogenerará para usted, mientras que simultáneamente requerirá más código repetitivo que los objetos de dominio NHibernate.
O bien no conocen muy bien el marco, o creen que es notoriamente inadecuado.
Solo hay unos pocos ejemplos precisos en los que puedo pensar dónde la biblioteca reimplementada es mejor que la original (consulte Jane Street Core Library , C5 Generic Collections para .NET , una clase de moneda real ), pero es probable que no escriba. Una mejor biblioteca estándar.