Heredé 200 mil líneas de código de espagueti. ¿Y ahora qué?


470

Espero que esto no sea una pregunta demasiado general; Realmente podría usar algunos consejos experimentados.

Estoy recién empleado como el único "Ingeniero de SW" en una tienda bastante pequeña de científicos que han pasado los últimos 10-20 años armando una vasta base de código. (Fue escrito en un lenguaje prácticamente obsoleto: G2 - piense en Pascal con gráficos). El programa en sí es un modelo físico de una planta de procesamiento químico complejo; El equipo que lo escribió tiene un conocimiento de dominio increíblemente profundo pero poca o ninguna capacitación formal en los fundamentos de la programación. Recientemente han aprendido algunas lecciones difíciles sobre las consecuencias de la gestión de configuración inexistente. Sus esfuerzos de mantenimiento también se ven obstaculizados en gran medida por la gran acumulación de "lodo" indocumentado en el código mismo. Te ahorraré la "política" de la situación ( siempre hay política!), pero es suficiente decir que no hay un consenso de opinión sobre lo que se necesita para el camino por delante.

Me han pedido que comience a presentar al equipo algunos de los principios del desarrollo de software moderno. Quieren que les presente algunas de las prácticas y estrategias estándar de la industria con respecto a las convenciones de codificación, la gestión del ciclo de vida, los patrones de diseño de alto nivel y el control de origen. Francamente, es una tarea bastante desalentadora y no estoy seguro de por dónde empezar.

Inicialmente, me inclino a darles tutorías en algunos de los conceptos centrales de El programador pragmático o Refactorización de Fowler ("olores de código", etc.). También espero presentar una serie de metodologías ágiles. Pero en última instancia, para ser efectivo, creo que voy a necesitar afinar los fundamentos básicos de 5-7; en otras palabras, ¿cuáles son los principios o prácticas más importantes que pueden comenzar a implementar de manera realista que les darán la mayor cantidad de dinero?

Así que esa es mi pregunta: ¿Qué haría usted incluir en su lista de las estrategias más efectivas para ayudar a enderezar los espaguetis (y evitar que en el futuro)?


124
El libro de Michael Feather Trabajando efectivamente con código heredado
MarkJ

13
Dado que G2 es como un código no, sino un código automatizado escrito por alguna GUI gadawful, creo que debe especificar si realmente está refactorizando en G2 o rehaciendo todo el asunto en algo sensato.
Erik Reppen

101
Hagas lo que hagas, no reescribas esto desde cero. Sería un grave error. 20 años de conocimiento químico: son cosas que nunca podrás recrear. Y con razón perderías el respeto de los científicos.
Francesco

13
Agregue el consejo razonado de Joel Spolsky sobre no reescribir al comentario de @ Francesco: joelonsoftware.com/articles/fog0000000069.html .
Govert

16
Bonita cita que leí recientemente que está relacionada: "El software es el único campo de ingeniería que reúne prototipos y luego intenta venderlos como productos entregados"
Chris S

Respuestas:


466

Prefacio

Esta es una tarea desalentadora, y hay mucho camino por recorrer. Así que sugiero humildemente que esto sea una guía bastante completa para su equipo, con consejos sobre herramientas apropiadas y material educativo.

Recuerde: Estas son pautas , y como tales están destinadas a ser adoptadas, adaptadas o descartadas según las circunstancias.

Cuidado: volcar todo esto en un equipo a la vez probablemente fallará. Debes tratar de elegir los elementos que te darán el mejor golpe para sudar e introducirlos lentamente, uno a la vez.

Nota: no todo esto se aplica directamente a los sistemas de programación visual como G2. Para obtener detalles más específicos sobre cómo lidiar con estos, consulte la sección Adición al final.


Resumen ejecutivo para el impaciente

  • Defina una estructura de proyecto rígida , con:
    • plantillas de proyecto ,
    • convenciones de codificación ,
    • sistemas de construcción familiares ,
    • y conjuntos de pautas de uso para su infraestructura y herramientas.
  • Instale un buen SCM y asegúrese de que sepan cómo usarlo.
  • Indíqueles buenos IDEs para su tecnología y asegúrese de que sepan cómo usarlos.
  • Implemente verificadores de calidad de código e informes automáticos en el sistema de compilación.
  • Combine el sistema de construcción con la integración continua y los sistemas de inspección continua .
  • Con la ayuda de lo anterior, identifique "hotspots" de calidad de código y refactorice .

Ahora para la versión larga ... ¡Cuidado, prepárense!


La rigidez es (a menudo) buena

Esta es una opinión controvertida, ya que la rigidez a menudo se ve como una fuerza que trabaja en su contra. Es cierto para algunas fases de algunos proyectos. Pero una vez que lo ve como un soporte estructural, un marco que elimina las conjeturas, reduce en gran medida la cantidad de tiempo y esfuerzo desperdiciados. Haz que funcione para ti, no contra ti.

Rigidez = Proceso / Procedimiento .

El desarrollo de software necesita buenos procesos y procedimientos por exactamente las mismas razones por las que las plantas o fábricas químicas tienen manuales, procedimientos, simulacros y pautas de emergencia: prevenir malos resultados, aumentar la previsibilidad, maximizar la productividad ...

¡Sin embargo, la rigidez viene con moderación!

Rigidez de la estructura del proyecto.

Si cada proyecto viene con su propia estructura, usted (y los recién llegados) se pierden y deben comenzar desde cero cada vez que los abre. No quiere esto en una tienda de software profesional, y tampoco lo quiere en un laboratorio.

Rigidez de los sistemas de construcción

Si cada proyecto se ve diferente, hay una buena posibilidad de que también se construyan de manera diferente . Una compilación no debería requerir demasiada investigación o demasiadas conjeturas. ¿Quieres ser capaz de hacer lo canónico y no tiene que preocuparse de detalles: configure; make install, ant, mvn install, etc ...

Reutilizar el mismo sistema de compilación y hacer que evolucione con el tiempo también garantiza un nivel constante de calidad.

Necesita READMEapuntar rápidamente los detalles del proyecto y guiar con gracia al usuario / desarrollador / investigador, si corresponde.

Esto también facilita enormemente otras partes de su infraestructura de construcción, a saber:

Por lo tanto, mantenga actualizada su compilación (como sus proyectos), pero hágalo más estricto con el tiempo y más eficiente al informar violaciones y malas prácticas.

No reinvente la rueda y reutilice lo que ya ha hecho.

Lectura recomendada:

Rigidez en la elección de lenguajes de programación

No puede esperar, especialmente en un entorno de investigación, que todos los equipos (y menos aún todos los desarrolladores) utilicen el mismo lenguaje y tecnología. Sin embargo, puede identificar un conjunto de herramientas "oficialmente compatibles" y fomentar su uso. El resto, sin una buena justificación, no debería permitirse (más allá de la creación de prototipos).

Mantenga su pila de tecnología simple, y el mantenimiento y la amplitud de las habilidades requeridas al mínimo: un núcleo fuerte.

Rigidez de los convenios y directrices de codificación

Las convenciones y pautas de codificación son las que le permiten desarrollar una identidad como equipo y una jerga compartida . No desea errar en terra incógnita cada vez que abre un archivo fuente.

Las reglas sin sentido que hacen la vida más difícil o prohíben acciones explícitas en la medida en que se rechazan los cometidos basados ​​en violaciones simples y simples son una carga. Sin embargo:

  • un conjunto de reglas básicas bien pensado elimina gran parte de los quejidos y pensamientos: nadie debe romper bajo ninguna circunstancia;

  • y un conjunto de reglas recomendadas proporcionan orientación adicional.

Enfoque personal: Soy agresivo cuando se trata de codificar convenciones, algunos incluso dicen nazi , porque creo en tener una lingua franca , un estilo reconocible para mi equipo. Cuando se registra el código basura, se destaca como un herpes labial en la cara de una estrella de Hollywood: desencadena una revisión y una acción automáticamente. De hecho, a veces he ido tan lejos como para recomendar el uso de ganchos de precompromiso para rechazar los compromisos no conformes. Como se mencionó, no debería ser demasiado loco y obstaculizar la productividad: debería conducirlo. Preséntelos lentamente, especialmente al principio. Pero es preferible pasar tanto tiempo arreglando un código defectuoso que no se puede trabajar en problemas reales.

Algunos idiomas incluso hacen cumplir esto por diseño:

  • Java estaba destinado a reducir la cantidad de basura aburrida que puedes escribir con ella (aunque sin duda muchos logran hacerlo).
  • La estructura de bloque de Python por sangría es otra idea en este sentido.

  • Ve, con su gofmtherramienta, que elimina por completo cualquier debate y esfuerzo (¡ y ego! ) Inherentes al estilo: corre gofmtantes de comprometerte.

Asegúrese de que la descomposición del código no pueda pasar. Las convenciones de código , la integración continua y la inspección continua , la programación de pares y las revisiones de código son su arsenal contra este demonio.

Además, como verá a continuación, el código es documentación , y esa es otra área donde las convenciones fomentan la legibilidad y la claridad.

Rigidez de la documentación.

La documentación va de la mano con el código. El código en sí mismo es documentación. Pero debe haber instrucciones claras sobre cómo construir, usar y mantener cosas.

Usar un solo punto de control para la documentación (como WikiWiki o DMS) es algo bueno. Cree espacios para proyectos, espacios para más bromas al azar y experimentación. Haga que todos los espacios reutilicen reglas y convenciones comunes. Intenta hacerlo parte del espíritu de equipo.

La mayoría de los consejos que se aplican al código y las herramientas también se aplican a la documentación.

Rigidez en los comentarios del código

Los comentarios de código, como se mencionó anteriormente, también son documentación. A los desarrolladores les gusta expresar sus sentimientos sobre su código (principalmente orgullo y frustración, si me preguntas). Por lo tanto, no es inusual para ellos expresar esto en términos no inciertos en los comentarios (o incluso en el código), cuando un texto más formal podría haber transmitido el mismo significado con menos improperios o drama. Está bien dejar pasar algunas por razones divertidas e históricas: también es parte del desarrollo de una cultura de equipo . Pero es muy importante que todos sepan qué es aceptable y qué no lo es, y ese ruido de comentario es solo eso: ruido .

Rigidez en los registros de confirmación

Los registros de confirmación no son un "paso" molesto e inútil del ciclo de vida de su SCM: NO se lo salte para llegar a casa a tiempo o continuar con la siguiente tarea, o para ponerse al día con los amigos que se fueron a almorzar. Son importantes y, como (la mayoría) del buen vino, cuanto más tiempo pasa, más valiosos se vuelven. Así que hazlos bien. Me quedo estupefacto cuando veo a compañeros de trabajo que escriben frases para combates gigantes o para hacks no obvios.

Las confirmaciones se realizan por una razón, y esa razón NO siempre está expresada claramente por su código y la línea de registro de confirmación que ingresó. Hay más que eso.

Cada línea de código tiene una historia y una historia . Los diferenciales pueden contar su historia, pero debes escribir su historia.

¿Por qué actualicé esta línea? -> Porque la interfaz cambió.

¿Por qué cambió la interfaz? -> Porque la biblioteca L1 que lo definió se actualizó.

¿Por qué se actualizó la biblioteca? -> Debido a que la biblioteca L2, que necesitamos para la función F, dependía de la biblioteca L1.

¿Y cuál es la característica X? -> Ver la tarea 3456 en el rastreador de problemas.

No es mi elección de SCM, y puede que tampoco sea la mejor para su laboratorio; pero Githace esto bien y trata de forzarlo a escribir buenos registros más que la mayoría de los otros sistemas SCM, usando short logsy long logs. Enlace el ID de la tarea (sí, necesita uno) y deje un resumen genérico para el shortlog, y expanda en el registro largo: escriba la historia del conjunto de cambios .

Es un registro: está aquí para realizar un seguimiento y registrar las actualizaciones.

Regla general: si estaba buscando algo sobre este cambio más tarde, ¿es probable que su registro responda su pregunta?

Proyectos, documentación y código están vivos

Manténgalos sincronizados, de lo contrario ya no forman esa entidad simbiótica. Funciona de maravilla cuando tienes:

  • clear confirma los registros en su SCM, con enlaces a ID de tareas en su rastreador de problemas,
  • donde los tickets de este rastreador se vinculan a los conjuntos de cambios en su SCM (y posiblemente a las compilaciones en su sistema de CI),
  • y un sistema de documentación que vincula a todos estos.

El código y la documentación deben ser coherentes .

Rigidez en las pruebas

Reglas de juego:

  • Cualquier código nuevo vendrá con (al menos) pruebas unitarias.
  • Cualquier código heredado refactorizado vendrá con pruebas unitarias.

Por supuesto, estos necesitan:

  • para probar realmente algo valioso (o son una pérdida de tiempo y energía),
  • estar bien escrito y comentado (como cualquier otro código que ingreses).

También son documentación y ayudan a delinear el contrato de su código. Especialmente si usas TDD . Incluso si no lo hace, los necesita para su tranquilidad. Son su red de seguridad cuando incorpora un nuevo código (mantenimiento o función) y su torre de vigilancia para protegerse contra la descomposición del código y las fallas ambientales.

Por supuesto, debe ir más allá y tener pruebas de integración y pruebas de regresión para cada error reproducible que arregle.

Rigidez en el uso de las herramientas

Está bien que el desarrollador / científico ocasional quiera probar un nuevo comprobador estático en la fuente, generar un gráfico o modelo con otro o implementar un nuevo módulo con un DSL. Pero es mejor si hay un conjunto canónico de herramientas que se espera que todos los miembros del equipo conozcan y usen.

Más allá de eso, deje que los miembros usen lo que quieran, siempre que sean TODOS:

  • productiva ,
  • NO requiere asistencia regularmente
  • NO ajustarse regularmente a su infraestructura general ,
  • NO interrumpir su infraestructura (modificando áreas comunes como código, sistema de compilación, documentación ...),
  • NO afecta el trabajo de otros ,
  • Capaz de realizar oportunamente cualquier tarea solicitada .

Si ese no es el caso, haga cumplir que recurran a los valores predeterminados.


Rigidez vs Versatilidad, Adaptabilidad, Prototipos y Emergencias

La flexibilidad puede ser buena. Dejar que alguien use ocasionalmente un truco, un enfoque rápido y sucio, o una herramienta favorita para mascotas para hacer el trabajo está bien. NUNCA permita que se convierta en un hábito, y NUNCA permita que este código se convierta en la base de código real para soportar.


El espíritu de equipo importa

Desarrolle un sentido de orgullo en su base de código

  • Desarrollar un sentido de orgullo en el código

Evita los juegos de culpa

  • UTILICE juegos de Integración continua / Inspección continua: fomenta la competencia productiva y de buenos modales .
  • HAGA un seguimiento de los defectos: es solo una buena limpieza.
  • HAGA la identificación de las causas raíz : son solo procesos a prueba de futuro.
  • PERO NO asigne la culpa : es contraproducente.

Se trata del código, no de los desarrolladores

Haga que los desarrolladores sean conscientes de la calidad de su código, PERO haga que vean el código como una entidad separada y no como una extensión de sí mismos, lo que no puede criticarse.

Es una paradoja: debe alentar la programación sin ego para un lugar de trabajo saludable pero confiar en el ego con fines motivadores.


De científico a programador

Las personas que no valoran y se enorgullecen del código no producen un buen código. Para que esta propiedad emerja, necesitan descubrir lo valioso y divertido que puede ser. La profesionalidad y el deseo de hacer el bien no son suficientes: necesita pasión. Por lo tanto, debe convertir a sus científicos en programadores (en el sentido amplio).

Alguien argumentó en comentarios que después de 10 a 20 años en un proyecto y su código, cualquiera sentiría un apego. Tal vez me equivoque, pero supongo que están orgullosos de los resultados del código y del trabajo y su legado, no del código en sí o del acto de escribirlo.

Por experiencia, la mayoría de los investigadores consideran que la codificación es una necesidad o, en el mejor de los casos, una distracción divertida. Solo quieren que funcione. Los que ya están bastante versados ​​y que tienen interés en la programación son mucho más fáciles de persuadir de adoptar las mejores prácticas y cambiar las tecnologías. Necesitas llevarlos hasta la mitad.


El mantenimiento del código es parte del trabajo de investigación

Nadie lee trabajos de investigación de mierda. Es por eso que son revisados ​​por pares, revisados, refinados, reescritos y aprobados una y otra vez hasta que se consideran listos para su publicación. ¡Lo mismo se aplica a una tesis y una base de código!

Deje en claro que la refactorización y actualización constantes de una base de código evita la descomposición del código y reduce la deuda técnica, y facilita la futura reutilización y adaptación del trabajo para otros proyectos.


¡¿¿Por qué todo esto??!

¿Por qué nos molestamos con todo lo anterior? Por la calidad del código . ¿O es un código de calidad ...?

Estas pautas tienen como objetivo conducir a su equipo hacia este objetivo. Algunos aspectos lo hacen simplemente mostrándoles el camino y dejándolos hacerlo (lo cual es mucho mejor) y otros los toman de la mano (pero así es como se educa a las personas y se desarrollan hábitos).

¿Cómo sabes cuando la meta está al alcance?

La calidad es medible

No siempre cuantitativamente, pero es medible . Como se mencionó, debe desarrollar un sentido de orgullo en su equipo, y mostrar progreso y buenos resultados es clave. Mida la calidad del código regularmente y muestre el progreso entre intervalos y cómo es importante. Haga retrospectivas para reflexionar sobre lo que se ha hecho y cómo mejoró o empeoró las cosas.

Existen excelentes herramientas para la inspección continua . La sonda es popular en el mundo Java, pero puede adaptarse a cualquier tecnología; y hay muchos otros Mantenga su código bajo el microscopio y busque estos molestos bichos y microbios molestos.


Pero, ¿qué pasa si mi código ya es una mierda?

Todo lo anterior es divertido y lindo como un viaje a Never Land, pero no es tan fácil de hacer cuando ya tienes (un montón de código de basura) y un equipo reacio a cambiar.

Aquí está el secreto: debes comenzar en alguna parte .

Anécdota personal: en un proyecto, trabajamos con una base de código que pesaba originalmente más de 650,000 Java LOC, más de 200,000 líneas de JSP, más de 40,000 JavaScript JavaScript y más de 400 MB de dependencias binarias.

Después de aproximadamente 18 meses, es 500,000 Java LOC (MÁS LIMPIO) , 150,000 líneas de JSPs y 38,000 JavaScript LOC, con dependencias de apenas 100MBs (¡y estos ya no están en nuestro SCM!).

¿Cómo lo hicimos? Acabamos de hacer todo lo anterior. O se esforzó mucho.

Es un esfuerzo de equipo, pero lentamente inyectamos en nuestras regulaciones y herramientas de proceso para monitorear la frecuencia cardíaca de nuestro producto, mientras recortamos rápidamente el "gordo": código basura, dependencias inútiles ... No detuvimos todo el desarrollo para haga esto: tenemos períodos ocasionales de relativa paz y tranquilidad en los que somos libres de volvernos locos en la base de código y desgarrarla, pero la mayoría de las veces lo hacemos todo por defecto al modo "revisar y refactorizar" cada vez que tenemos : durante las construcciones, durante el almuerzo, durante los sprints de corrección de errores, durante los viernes por la tarde ...

Hubo algunos grandes "trabajos" ... Cambiar nuestro sistema de compilación de una compilación Ant gigante de 8500+ XML LOC a una compilación Maven multimódulo fue una de ellas. Luego tuvimos:

  • módulos claros (o al menos ya era mucho mejor, y todavía tenemos grandes planes para el futuro),
  • gestión automática de dependencias (para facilitar el mantenimiento y las actualizaciones, y para eliminar deps inútiles),
  • construcciones más rápidas, fáciles y reproducibles,
  • informes diarios de calidad.

Otra fue la inyección de "cinturones de herramientas de utilidad", a pesar de que estábamos tratando de reducir las dependencias: Google Guava y Apache Commons reducen su código y reducen mucho la superficie de errores en su código.

También convencimos a nuestro departamento de TI de que tal vez usar nuestras nuevas herramientas (JIRA, Fisheye, Crucible, Confluence, Jenkins) era mejor que las existentes. Todavía necesitábamos lidiar con algunos que despreciamos (QC, Sharepoint y SupportWorks ...), pero fue una experiencia mejorada en general, con algo más de espacio.

Y todos los días, ahora hay una escasez de entre uno y docenas de compromisos que solo se ocupan de arreglar y refactorizar cosas. Ocasionalmente rompemos cosas (necesita pruebas unitarias, y es mejor que las escriba antes de refactorizar las cosas), pero en general el beneficio para nuestra moral Y para el producto ha sido enorme. Obtenemos una fracción de un porcentaje de calidad de código a la vez. ¡Y es divertido verlo aumentar!

Nota: Nuevamente, la rigidez debe ser sacudida para dejar espacio para cosas nuevas y mejores. En mi anécdota, nuestro departamento de TI está en parte en lo correcto al tratar de imponernos algunas cosas y en otras no. O tal vez solían tener razón . Las cosas cambian. Demuestre que son mejores formas de aumentar su productividad. Las pruebas y los prototipos están aquí para esto.


El ciclo de refactorización incremental súper secreto del código de espagueti para una calidad increíble

       +-----------------+      +-----------------+
       |  A N A L Y Z E  +----->| I D E N T I F Y |
       +-----------------+      +---------+-------+
                ^                           |
                |                           v
       +--------+--------+      +-----------------+
       |    C L E A N    +<-----|      F I X      |
       +-----------------+      +-----------------+

Una vez que tenga algunas herramientas de calidad en su cinturón de herramientas:

  1. Analice su código con verificadores de calidad de código.

    Linters, analizadores estáticos, o lo que sea que tengas.

  2. Identifique sus puntos críticos y frutas bajas .

    Las infracciones tienen niveles de gravedad, y las clases grandes con una gran cantidad de graves son una gran señal de alerta: como tales, aparecen como "puntos calientes" en los tipos de vistas de radiadores / mapas de calor.

  3. Arregle los puntos calientes primero.

    Maximiza su impacto en un corto período de tiempo ya que tienen el mayor valor comercial. Idealmente, las violaciones críticas deben tratarse tan pronto como aparezcan, ya que son posibles vulnerabilidades de seguridad o causas de bloqueo, y presentan un alto riesgo de inducir una responsabilidad (y en su caso, un mal desempeño para el laboratorio).

  4. Limpie las infracciones de bajo nivel con barridos automáticos de la base de código .

    Mejora la relación señal / ruido para que pueda ver violaciones importantes en su radar a medida que aparecen. A menudo hay un gran ejército de violaciones menores al principio si nunca se solucionaron y su base de código se dejó libre en la naturaleza. No presentan un "riesgo" real, pero perjudican la legibilidad y facilidad de mantenimiento del código. Arreglos ya sea cuando los encuentres mientras trabajas en una tarea, o mediante grandes búsquedas de limpieza con barridos de código automatizados si es posible. Tenga cuidado con los grandes barridos automáticos si no tiene un buen conjunto de pruebas y un sistema de integración. Asegúrese de acordar con los compañeros de trabajo el momento adecuado para ejecutarlos para minimizar la molestia.

  5. Repita hasta que esté satisfecho.

    Lo que, idealmente, nunca debería ser, si este sigue siendo un producto activo: seguirá evolucionando.

Consejos rápidos para una buena limpieza

  • Cuando está en modo de revisión , basado en una solicitud de atención al cliente:

    • Por lo general, es una buena práctica NO solucionar otros problemas, ya que podría presentar otros nuevos de mala gana.
    • Ve al estilo SEAL: entra, elimina el error, sal y envía tu parche. Es un golpe quirúrgico y táctico.
  • Pero para todos los demás casos , si abre un archivo, haga su deber:

    • definitivamente: revíselo (tome notas, informe de problemas de archivos),
    • tal vez: limpiarlo (limpiezas de estilo y violaciones menores),
    • idealmente: refactorizarlo (reorganizar grandes secciones y sus vecinos).

Simplemente no se desvíe de pasar una semana de archivo en archivo y terminar con un conjunto de cambios masivo de miles de correcciones que abarcan múltiples funciones y módulos, lo que dificulta el seguimiento futuro. Un problema en el código = un ticket en su rastreador. A veces, un conjunto de cambios puede afectar múltiples tickets; pero si sucede con demasiada frecuencia, probablemente estés haciendo algo mal.


Anexo: Gestión de entornos de programación visual

Los jardines amurallados de los sistemas de programación a medida

Múltiples sistemas de programación, como el OP G2, son diferentes bestias ...

  • Sin fuente "Código"

    A menudo, no le dan acceso a una representación textual de su "código" fuente: puede estar almacenado en un formato binario patentado, o tal vez almacena cosas en formato de texto pero las oculta. Los sistemas de programación gráfica a medida en realidad no son infrecuentes en los laboratorios de investigación, ya que simplifican la automatización de los flujos de trabajo de procesamiento de datos repetitivos.

  • Sin herramientas

    Aparte de los suyos, eso es. A menudo está limitado por su entorno de programación, su propio depurador, su propio intérprete, sus propias herramientas y formatos de documentación. Son jardines amurallados , excepto si finalmente captan el interés de alguien lo suficientemente motivado como para aplicar ingeniería inversa a sus formatos y construir herramientas externas, si la licencia lo permite.

  • Falta de documentación

    Muy a menudo, estos son sistemas de programación de nicho, que se utilizan en entornos bastante cerrados. Las personas que los usan con frecuencia firman NDA y nunca hablan de lo que hacen. Programar comunidades para ellos es raro. Entonces los recursos son escasos. Estás atrapado con tu referencia oficial, y eso es todo.

La parte irónica (y a menudo frustrante) es que todas las cosas que hacen estos sistemas obviamente podrían lograrse mediante el uso de lenguajes de programación generales y de propósito general, y muy probablemente de manera más eficiente. Pero requiere un conocimiento más profundo de la programación, mientras que no puede esperar que su biólogo, químico o físico (por nombrar algunos) sepa lo suficiente sobre programación, y aún menos para tener el tiempo (y el deseo) de implementar (y mantener) sistemas complejos, que pueden o no ser de larga duración. Por la misma razón que usamos DSL, tenemos estos sistemas de programación a medida.

Anécdota personal 2:En realidad, trabajé en uno de estos yo mismo. No hice el enlace con la solicitud del OP, pero mi proyecto era un conjunto de grandes piezas interconectadas de software de procesamiento y almacenamiento de datos (principalmente para investigación bioinformática, atención médica y cosmética, pero también para negocios inteligencia o cualquier dominio que implique el seguimiento de grandes volúmenes de datos de investigación de cualquier tipo y la preparación de flujos de trabajo de procesamiento de datos y ETL). Una de estas aplicaciones era, simplemente, un IDE visual que usaba las campanas y silbidos habituales: interfaces de arrastrar y soltar, espacios de trabajo de proyectos versionados (usando archivos de texto y XML para el almacenamiento de metadatos), muchos controladores conectables a fuentes de datos heterogéneas y un visual lienzo para diseñar tuberías para procesar datos de N fuentes de datos y al final generar M salidas transformadas, y posibles visualizaciones brillantes e informes complejos (e interactivos) en línea. Su típico sistema de programación visual a medida, que sufre un poco de síndrome NIH con el pretexto de diseñar un sistema adaptado a las necesidades de los usuarios.

Y, como era de esperar, es un buen sistema, bastante flexible para sus necesidades, aunque a veces un poco exagerado, por lo que se pregunta "¿por qué no usar herramientas de línea de comandos en su lugar?", Y desafortunadamente siempre lidera en medianas equipos que trabajan en proyectos grandes para muchas personas diferentes que lo utilizan con diferentes "mejores" prácticas.

¡Genial, estamos condenados! - ¿Qué hacemos al respecto?

Bueno, al final, todo lo anterior aún se mantiene. Si no puede extraer la mayor parte de la programación de este sistema para usar más herramientas y lenguajes convencionales, "solo" necesita adaptarla a las restricciones de su sistema.

Acerca de las versiones y el almacenamiento

Al final, casi siempre puedes versionar cosas, incluso con el entorno más limitado y amurallado. La mayoría de las veces, estos sistemas todavía vienen con su propio control de versiones (que desafortunadamente es bastante básico, y solo ofrece volver a las versiones anteriores sin mucha visibilidad, solo guardando instantáneas anteriores). No se trata exactamente de usar conjuntos de cambios diferenciales como lo haría su SCM de elección, y probablemente no sea adecuado para que varios usuarios envíen cambios simultáneamente.

¡Pero aún así, si brindan dicha funcionalidad, tal vez su solución sea seguir nuestras amadas pautas estándar de la industria anteriores y transponerlas a este sistema de programación!

Si el sistema de almacenamiento es una base de datos, probablemente exponga las funcionalidades de exportación o se pueda realizar una copia de seguridad en el nivel del sistema de archivos. Si está utilizando un formato binario personalizado, tal vez simplemente pueda intentar versionarlo con un VCS que tenga un buen soporte para datos binarios. No tendrá un control detallado, pero al menos tendrá la espalda cubierta de catástrofes y tendrá un cierto grado de cumplimiento de recuperación ante desastres.

Sobre las pruebas

Implemente sus pruebas dentro de la plataforma y use herramientas externas y trabajos en segundo plano para configurar copias de seguridad periódicas. Probablemente, inicie estas pruebas de la misma manera que iniciaría los programas desarrollados con este sistema de programación.

Claro, es un trabajo de pirateo y definitivamente no está a la altura de lo que es común para la programación "normal", pero la idea es adaptarse al sistema mientras se intenta mantener una apariencia de proceso de desarrollo de software profesional.

El camino es largo y empinado ...

Como siempre con entornos de nicho y sistemas de programación a medida, y como lo expusimos anteriormente, se trata de formatos extraños, solo un conjunto limitado (o totalmente inexistente) de herramientas posiblemente torpes y un vacío en lugar de una comunidad.

La recomendación: Intente implementar las pautas anteriores fuera de su sistema de programación a medida, tanto como sea posible. Esto garantiza que puede confiar en herramientas "comunes", que cuentan con el soporte adecuado y el impulso de la comunidad.

La solución: cuando esto no sea una opción, intente adaptar este marco global a su "caja". La idea es superponer este modelo de mejores prácticas estándar de la industria sobre su sistema de programación y aprovecharlo al máximo. El consejo aún se aplica: definir la estructura y las mejores prácticas, alentar la conformidad.

Desafortunadamente, esto implica que es posible que deba sumergirse y hacer una gran cantidad de trabajo de piernas. Entonces...

Últimas palabras famosas y solicitudes humildes:

  • Documenta todo lo que haces.
  • Comparte tu experiencia.
  • Open Source cualquier herramienta que escriba.

Al hacer todo esto, usted:

  • no solo aumenta sus posibilidades de obtener apoyo de personas en situaciones similares,
  • pero también brinda ayuda a otras personas y fomenta la discusión sobre su pila de tecnología.

Quién sabe, usted podría estar en el comienzo de una nueva comunidad vibrante de lenguaje oscuro X . Si no hay ninguno, ¡comience uno!

  • Haga preguntas sobre Stack Overflow ,
  • Tal vez incluso escriba una propuesta para un nuevo sitio StackExchange en el Área 51 .

Tal vez sea hermoso por dentro , pero nadie tiene ni idea hasta ahora, ¡así que ayuda a derribar este feo muro y deja que otros echen un vistazo!


22
NOTA: Los comentarios sobre esto se han limpiado cuando se iban de las manos. Haylem ha incorporado los más relevantes y útiles en la respuesta. Además, la respuesta está muy cerca del límite de 30,000 caracteres para las publicaciones. Edite con extremo cuidado.
ChrisF

3
Solo falta una pieza en la integración continua, que es una distinción importante: NO culpe a las personas por los malos registros, SÍ culpe por no limpiar a tiempo. Está bien cometer un error. Los errores lo ayudan a aprender, pero dejar que sus compañeros de trabajo sufran con sus errores desperdicia tiempo, energía y, en el peor de los casos, les enseña resentimiento.
Jason

96
¿Cuándo puedo comprar esta respuesta en tapa dura?
LarsH

55
Inicialmente me desactivó esta respuesta. No estoy muy seguro de por qué, pero la redacción me frotó de la manera incorrecta y me sentí un poco demasiado alto. Sin embargo, al leer la guía sección por sección (en lugar de en una sola sesión), me pareció extremadamente útil. Si encuentra esta respuesta desalentadora y ha llegado a este comentario sin leerla, entonces regrese y simplemente lea una sección.
sdasdadas

55
demasiado rígido, largo aliento y afirmando lo obvio. Si esta es su agenda / estrategia, nadie lo escuchará más después de un mes más o menos.
Joppe

101

El primer paso sería la introducción de un sistema de control de versiones (SVN, Git, Mercurial, TFS, etc.). Esto es imprescindible para un proyecto que tendrá refactorización.

Editar: con respecto a VSC: cada paquete de control de código fuente puede administrar archivos binarios, aunque con algunas limitaciones. La mayoría de las herramientas en el mercado tienen la capacidad de usar un visor y editor de diferencias personalizado, use esta capacidad. Los archivos fuente binarios no son una excusa para no usar el control de versiones.

Hay una publicación similar sobre cómo lidiar con el código heredado , podría ser una buena referencia a seguir: consejos para trabajar con código heredado


19
Desafortunadamente, uno de los inconvenientes del lenguaje G2 es que los archivos fuente no son legibles por humanos (es fundamentalmente un lenguaje gráfico, similar a LabView ) y, por lo tanto, implementar el Control de versiones no es trivial en el mejor de los casos. Este es, de hecho, uno de nuestros mayores obstáculos, actualmente (IMO).
kmote

44
@kmote: ¿El fabricante de G2 tiene alguna de sus propias herramientas especiales para ayudar con el control de versiones? ¿Alguien más ha hecho una herramienta así?
FrustratedWithFormsDesigner

39
Cada paquete de control de código fuente puede administrar archivos binarios, aunque con algunas limitaciones. Cada herramienta que conozco tiene la capacidad de usar un visor y editor de diferencias personalizado, use esta capacidad. Los archivos fuente binarios no son una excusa para no usar el control de versiones.
mattnz

11
Puede aplicar ingeniería inversa al formato de archivo G2 y crear una utilidad para volcarlo en formato de texto compatible con diff. Eso puede parecer desalentador, pero para una base de código tan grande, valdría la pena el esfuerzo (en mi opinión ingenua).
Joey Adams

66
@Erik: Usar el Control de versiones SOLAMENTE como una herramienta de "reversión" es como comprar un Porsche para hacer la compra de comestibles. Lo hace tan bien como cualquier otra cosa, pero puede hacer mucho más por usted .......
mattnz

43

Cuando tengo que trabajar con código de espagueti, lo primero que trabajo es modularización . Encuentre lugares donde pueda dibujar líneas y extraer (más o menos) piezas independientes de la base de código. Probablemente no serán muy pequeños, debido a un alto grado de interconexión y acoplamiento, pero surgirán algunas líneas de módulos si las busca.

Una vez que tenga módulos, ya no tendrá que enfrentarse a la desalentadora tarea de limpiar todo un programa desordenado. Ahora, en cambio, tiene varios módulos desordenados independientes más pequeños para limpiar. Ahora elija un módulo y repita en una escala más pequeña. Encuentre lugares donde pueda extraer funciones grandes en funciones más pequeñas o incluso en clases (si G2 las admite).

Todo esto es mucho más fácil si el lenguaje tiene un sistema de tipos lo suficientemente fuerte, ya que puede hacer que el compilador haga mucho trabajo pesado por usted. Realiza un cambio en algún lugar que (intencionalmente) rompa la compatibilidad, luego intente compilar. Los errores de compilación lo llevarán directamente a los lugares que deben cambiarse, y cuando deje de recibirlos, encontrará todo. ¡Luego ejecuta el programa y prueba todo! Las pruebas continuas son de vital importancia cuando se refactoriza.


17
Trabajar eficazmente con código heredado es probablemente una lectura obligada para esto.
Oded

3
Mejor aún ... En lugar de simplemente ejecutar el programa, la unidad prueba sus nuevos módulos :)
Demian Brecht

1
Este es el mejor enfoque (junto con el paso obvio de llevar todo el lote al control de versiones). Todo el truco en las grandes respuestas es demasiado general y demasiado grande para aplicar de una vez. pequeños pasos hasta que tengas un concepto general. Heredé un proyecto de 50k una vez (en realidad cuatro versiones de esencialmente el mismo 50k). Después de un mes tuve una versión y me deshice de unas 10k líneas a través de la refactorización / reestructuración básica. 1-pegarlo en el repositorio, 2-asegurarse de que puede construirlo, 3-refactorizar / reestructurar, repetir 3 hasta que esté listo.

22

No sé si esta es una opción para usted, pero comenzaría a tratar de convencerlos de que contraten más desarrolladores profesionales . De esta forma podrían concentrarse en problemas de dominio (estoy seguro de que tienen suficiente allí).

Creo que son personas muy inteligentes, pero convertirse en un buen desarrollador exige mucho tiempo. ¿Están listos para pasar tanto tiempo en una actividad que no es su negocio principal? En mi humilde opinión, esta no es la manera de lograr los mejores resultados.


16
El OP es el primer desarrollador profesional. La mejor manera para que el OP los convenza de contratar más, es que el OP proporcione un valor adicional obvio en los primeros 6-12 meses. Si eso se puede lograr, OP tendrá credibilidad y podrá contratar más.
MarkJ

20

Guau. ¡Parece que tienes un gran desafío por delante! Haría algo en las siguientes líneas:

  • En primer lugar: priorizar . ¿Qué quieres lograr primero? ¿Qué es lo más importante para el estado actual del proyecto? ¿De qué sacará más provecho frente a cuánto tiempo llevará llegar allí?
  • Asegúrese de tener un sistema de control de versiones. Git o Mercurial por ejemplo.
  • Poner en funcionamiento algún tipo de sistema de integración continua (por ejemplo, Jenkins ).
  • Obtenga un sistema de seguimiento de errores en funcionamiento. Mantis es bastante agradable en mi opinión.
  • Analice el análisis de código estático (si hay algo disponible para el idioma con el que está trabajando actualmente).
  • Intente lograr tanta consistencia en cualquier cosa, desde nombrar variables hasta convenciones y pautas generales de código en la base de código.
  • Obtenga el sistema bajo prueba . Esto es extremadamente importante para un gran sistema heredado como este en mi opinión. Use casos de prueba para documentar el comportamiento existente , sin importar si el comportamiento se siente extraño o no (generalmente hay una razón por la cual el código parece cierto por qué, podría ser bueno o malo, o ambos; P). Michael Feathers, trabajar eficazmente con código heredado es un excelente recurso para esto.

10

Dicen que el primer paso para resolver un problema es admitir que tienes uno. Con eso en mente, puede comenzar generando un gráfico de dependencia que ilustra la gran maraña que es su base de código actual. Buena herramienta para generar diagrama de dependencia? tiene algunos años pero contiene algunos indicadores de herramientas que pueden ayudar a crear tales gráficos. Me gustaría ir con un gran gráfico grande y feo que muestra todo lo posible para llevar el punto a casa. Hable sobre los problemas que resultan de demasiadas interdependencias y tal vez escriba una línea de Buckaroo Banzai :

Puede verificar su anatomía todo lo que desee, y aunque puede haber una variación normal, cuando se trata de eso, en el interior de la cabeza, todo se ve igual. No, no, no, no hagas eso. Nunca se sabe a qué se puede unir.

A partir de ahí, presente un plan para comenzar a arreglar el desorden. Divida el código en módulos que sean lo más autónomos posible. Esté abierto a sugerencias sobre cómo hacerlo: las personas con las que está hablando conocen el historial y la funcionalidad del código mejor que usted. Sin embargo, el objetivo es tomar un gran problema y convertirlo en un número de problemas más pequeños que luego pueda priorizar y comenzar a limpiar.

Algunas cosas en las que enfocarse:

  • Cree interfaces limpias entre módulos y comience a usarlas. El código antiguo puede, por necesidad, continuar sin usar esas nuevas interfaces agradables por un tiempo; ese es el problema que está comenzando a resolver. Pero haga que todos acepten usar solo las nuevas interfaces en el futuro. Si hay algo que necesitan que no está en las interfaces, arregle las interfaces, no las rodee.

  • Busque casos en los que se haya repetido la misma funcionalidad. Trabajar hacia la unificación.

  • Recuerde a todos de vez en cuando que estos cambios están destinados a hacer la vida más fácil, no más difícil. La transición puede ser dolorosa, pero es para un buen propósito, y cuanto más todos estén a bordo, más rápido serán los beneficios.


1
@kmote No te hubieran contratado si no hubieran reconocido que necesitan ayuda y quieren hacer las cosas mejor. La parte difícil puede ser ayudarlos a recordar que su trabajo no es solucionar los problemas, sino ayudarlos a solucionarlos. Buckaroo Banzai es bastante popular entre los tipos científicos de cierta edad, tal vez pueda ayudarlo a mantener las cosas ligeras.
Caleb

9

Después de analizar un poco Gensym G2 , parece que la forma de abordar este problema dependerá en gran medida de la cantidad de código base que se vea así:

ingrese la descripción de la imagen aquí

o esto:

ingrese la descripción de la imagen aquí

versus esto, cortesía de 99 botellas de cerveza :

beer-bottles()

i:integer =99;
j:integer;
constant:integer =-1;

begin
for i=99 down to 1
    do
    j = (i+constant);
        if (i=1) then begin
            post"[i] bottle of beer on the wall";
            post" [i] bottle of beer";
            post" Take one down and pass it around ";
            post" No bottle of beer on the wall"; 
        end 
        else begin
            post"[i] bottles of beer on the wall";
            post" [i] bottles of beer";
            post" Take one down and pass it around ";
            if (i=2) then 
                post" [j] bottle of beer on the wall"
           else
                post" [j] bottles of beer on the wall"; 
           end
    end
end

En el caso de este último, está trabajando con el código fuente, que es efectivamente una cantidad conocida y algunas de las otras respuestas ofrecen algunos consejos muy sabios para tratarlo.

Si la mayor parte de la base de código es la última, o incluso si es una porción considerable, se encontrará con el interesante problema de tener un código que probablemente no pueda ser refactorizado debido a que es extremadamente especializado, o peor aún, algo que parece puede ser extraíble, pero a menos que esté debidamente documentado, no sabe si está eliminando el código crítico (piense en algo similar a una operación de estafa ) que no parece ser así a primera vista.

Aunque obviamente su primera prioridad será obtener algún tipo de control de versiones en línea, como señaló ElYusubov , y parece que el control de versiones ha sido compatible desde la versión 8.3 . Dado que G2 es una combinación de un par de metodologías de lenguaje diferentes, es probable que le resulte más efectivo usar el control de versión que se le proporciona en lugar de intentar encontrar otra cosa y hacer que funcione.

A continuación, aunque es probable que algunos aboguen por comenzar a refactorizar, soy un gran defensor de asegurarme de que comprenda completamente el sistema con el que está trabajando antes de comenzar a tocar cualquiera de los códigos, especialmente cuando se trata de códigos y diagramas visuales desarrollados por desarrolladores sin capacitación formal (o formación) en metodologías de ingeniería de software. El razonamiento para esto es múltiple, pero la razón más obvia es que está trabajando con una aplicación que potencialmente tiene más de 100 años de trabajo y realmente necesita asegurarse de saber qué está haciendo y cuánto documentación hay en ella. Como no dijo en qué industria se implementa el sistema, según lo que he estado leyendo sobre G2, parece seguro asumir que es probable que sea una aplicación de misión crítica que incluso puede tener el potencial de tener implicaciones para la seguridad de la vida. Por lo tanto, comprender exactamente lo que está haciendo será muy importante. Si hay un código que no está documentado, trabaje con los demás miembros del equipo para asegurarse de que se implemente la documentación para asegurarse de que las personas puedan determinar qué hace el código.

A continuación, comience a ajustar las pruebas unitarias alrededor de la base de código y los diagramas visuales que pueda. Debo admitir un poco de ignorancia con respecto a cómo hacer esto con G2, pero podría valer la pena crear su propio marco de prueba para lograrlo. Este también es un momento ideal para comenzar a presentar a los otros miembros del equipo para que usen algunas de las prácticas de ingeniería más rigurosas relacionadas con la calidad del código (es decir, todo el código debe tener pruebas unitarias y documentación).

Una vez que haya implementado pruebas unitarias en una buena cantidad de código, puede comenzar a abordar la refactorización de una manera como la sugerida por haylem ; sin embargo, recuerde tener en cuenta que se trata de algo que está destinado a desarrollar sistemas expertos y refactorizarlo podría ser una batalla cuesta arriba. Este es en realidad un entorno donde hay algo que decir para no escribir código extremadamente genérico a veces.

Finalmente, asegúrese de prestar mucha atención a lo que dicen los otros miembros del equipo, solo porque el código y la calidad del diagrama no es la mejor no necesariamente se refleja mal en ellos. En última instancia, por el momento es probable que sepan más sobre lo que hace la aplicación que usted, por lo que es más importante que se siente y se asegure de comprender lo que hace antes de hacer cambios radicales.


1
@haylem: no tengo idea, y puede ser completamente posible que haya 200,000 LOC más n diagramas de flujo y gráficos en la aplicación. Por lo tanto, 200,000 LOC podrían estar subestimando significativamente la complejidad de la aplicación.
rjzii

9

Por lo general, las quejas que escucha por adelantado no tienen nada que ver con los problemas importantes. Después de todo, es completamente normal escuchar estas quejas en cualquier proyecto de software.

Código difícil de entender? Cheque. Código masivo de base? Cheque.

El verdadero problema es que las personas se van, y cuando la nueva persona se une a la organización, existe una desorientación típica. Además, hay un problema de expectativas poco realistas y problemas de calidad del código.

Esto es lo que abordaría, en orden:

  1. Copias de seguridad, tanto el servidor como la versión local
  2. Configurar rastreador de errores
  3. Configurar el sistema de versiones
  4. Configurar FAQ / Wiki
  5. Primer informe de todos los científicos / programadores.
    • Recuérdeles la regla 80/20. El 20% de los errores son responsables del 80% de los problemas.
    • Concéntrese en los problemas más importantes y mantenga las solicitudes de mejora, etc.
    • El propósito aquí no es asustar a las personas con una gran lista, sino una lista de pequeñas victorias alcanzables. Después de todo, también tienes que demostrar tu valía.
  6. Configurar sistema de construcción
    • Comience a trabajar para obtener compilaciones confiables (esto puede llevar un tiempo)
    • identificar y nombrar cada proyecto
    • identificar dependencias cíclicas
    • si hay binarios de algunos proyectos de código abierto, intente obtener fuentes
  7. Identifique cómo se puede modularizar el código G2, por ejemplo, API, servicios
  8. Identifique cómo se puede probar y documentar el código G2.
  9. Configurar el sistema de revisión de código
  10. Segundo informe
  11. Identifique un equipo crack de mejores programadores y trabaje con ellos para envolver sus módulos.
  12. Las revisiones de código están allí en esta etapa para mejorar la comunicación y la documentación. Mantenlo fácil en esta etapa. Solucione cualquier problema de proceso.
  13. Implemente el sistema para otros programadores. Deje que los miembros del equipo de crack se conviertan en mentores del resto. Recuerde que la escala es el problema aquí. Está efectivamente en una función de gestión.

9

Preguntas como estas son la razón por la cual existe el proyecto de Carpintería de software .

Durante los últimos 14 años, hemos enseñado a científicos e ingenieros habilidades básicas de desarrollo de software: control de versiones, pruebas, cómo modularizar código, etc. Todos nuestros materiales están disponibles gratuitamente bajo una licencia Creative Commons, y realizamos un par de docenas de talleres gratuitos de dos días cada año para ayudar a las personas a comenzar.

Basado en eso, creo que el mejor punto de partida es probablemente el excelente libro (breve) Facts and Falacies of Software Engineering de Robert Glass : su enfoque basado en la evidencia es una buena manera de convencer a los científicos de que lo que les estamos diciendo sobre las buenas prácticas de programación es más que solo opinión.
En cuanto a las prácticas específicas, las dos personas que están más dispuestas a adoptar son el control de versiones y las pruebas unitarias; una vez que estén en su lugar, pueden abordar el tipo de refactorización sistemática que Michael Feathers describe en Trabajar eficazmente con código heredado .
Ya no recomiendo el Programador pragmático (mucha exhortación, difícil de poner en práctica para los principiantes), y creo que el Código de McConnell completo es demasiado para comenzar (aunque es una gran cosa darles seis meses o un año, una vez que dominen lo básico).

También recomendaría el excelente artículo de Paul Dubois "Mantener la corrección en los programas científicos" ( Computing in Science & Engineering , mayo-junio de 2005), que describe un enfoque de "defensa en profundidad" que combina una docena de prácticas diferentes en una lógica, coherente camino.


sugerencias interesantes Lo comprobaré. (Nota: enlace roto en el papel de Dubois)
kmote

7

Creo que antes que nada debes aclarar tu situación. ¿Qué quieren de ti?

  • Es muy poco probable que quieran que aprendas un idioma antiguo, porque ahora parece un callejón sin salida: hay una posibilidad cada vez menor de encontrar a alguien que sepa o quiera aprender G2, por lo que el conocimiento quedará enterrado en el montón de código que se derrumba cuando los científicos actuales se van o el código parcheado falla cada vez más a menudo.
  • ¿Están los científicos (o algunos de ellos) listos para aprender un nuevo lenguaje y muchos paradigmas de programación? ¿O quieren separar la programación y la actividad científica a largo plazo, y tal vez tener más programadores si es necesario? Esto parece una separación racional y más eficiente de la experiencia.

Creo que el requisito principal aquí es "guardar el conocimiento en el sistema", ¡así que tienes que ir y excavarlo!

La primera tarea es escribir una documentación.

Analice la estructura y los requisitos como si fuera una tarea nueva, pero con la ayuda de un sistema existente. Estarán encantados porque PREGUNTAS en lugar de ENSEÑAR primero, y rápidamente obtendrás suficiente conocimiento de fondo más organizado desde el punto de vista de un programador: "¿qué está pasando aquí?" Los documentos (estructura estática del sistema, flujo de trabajo, componentes, problemas) serán inmediatamente valiosos para ellos, y tal vez les muestren más información relevante que a usted (algunos de los chicos pueden tener "¡AHA!" Y comenzar a corregir algunos códigos de inmediato ) ...

Entonces deberías empezar a preguntar a dónde quieren ir

Si están listos para alejarse de G2, ¿qué sistema quieren ver (plataforma, idioma, interfaz, estructura general)? Si es posible, puede comenzar a escribir un contenedor externo alrededor del sistema, teniendo la estructura de destino, pero manteniendo los componentes originales, comenzando así lentamente un tipo de marco que permita que se implementen nuevos componentes en este entorno de destino. Debe encontrar los servicios principales (conexiones de datos persistentes y "kits de herramientas": cálculo central, dibujo, ... bibliotecas), y así les proporciona un entorno familiar en una nueva plataforma e idioma, que permite la transición por usted o por usted. ellos: tome los viejos códigos uno por uno, vuelva a implementarlos (¡y LIMPIE!) en el nuevo entorno. Cuando eso está listo, conocen el nuevo idioma; y la capa de servicio (principalmente creada por usted, lo siento) está lista para alojar los nuevos componentes.

Si no se mueven , debe aprender G2 y crear el marco modular allí, en el que usted o ellos deben mover los componentes (con limpieza). De todos modos, el lenguaje es solo una serialización de datos y un árbol de algoritmos ...

¡Mientras analiza y escribe los documentos, lea, use y anuncie patrones de diseño GoF! :-)

... mis 2 centavos


Estoy de acuerdo en que el paso 1 es resolver lo que quieren de ti, pero el siguiente paso debería ser hacerlo, y si el siguiente paso no es documentar el estado de las cosas, entonces no hagas eso demasiado. Si lo haces, no lo apreciarán.
Bill

@bill: La pregunta dice "no hay un consenso de opinión sobre lo que se necesita para el camino por delante". ¡No lo saben! Supongo que hay debates serios sin ideas reales sobre el sistema que deben guardarse "de alguna manera". La tarea de un programador en esta situación es obvia (al menos para mí): haga un análisis correcto desde el punto de vista técnico para ayudar a tomar una decisión racional.
Lorand Kedves

Por supuesto que no saben lo que quieren, esa es la parte de "resolverlo", que es diferente a simplemente elegir algo como documentación y patrones y decir hacer estas cosas. Esas cosas son buenas, pero tiene que ser un proceso que involucre al grupo, y si comienzas con cosas que no ven valor en primer lugar, tendrás dificultades para comprar. - ¡Salud!
Bill

@Bill: Creo que dices exactamente lo mismo que he escrito sobre el contenido y la creación de esa documentación ... ;-)
Lorand Kedves

4

Acabo de terminar haciendo una serie de presentaciones sobre los principios SOLID de Robert Martin para mis compañeros de trabajo. No sé qué tan bien se traducen estos principios a G2, pero dado que está buscando 5-7 fundamentos básicos, estos parecen ser un conjunto bien establecido para comenzar. Si quieres redondearlo a 7, puedes comenzar con DRY y lanzar Fail-Fast.


1
ooh, excelente sugerencia! Me recordó esta buena descripción junto con este resumen gratuito de libros electrónicos .
kmote

3

El único problema de producción parece un problema de gestión de cambios. Si ese es el caso y el software realiza su propósito de otra manera, el primer consejo que daría es resistir el impulso de hacer demasiado y demasiado rápido.

El control de la fuente, la refactorización y los desarrolladores más entrenados son buenas sugerencias, pero si esta es la primera vez que tiene que lidiar con este tipo de problema, avanzar lentamente y hacer cambios controlados no puede enfatizarse lo suficiente.

La necesidad de destruir el desorden será grande a veces, pero hasta que haya realizado una ingeniería inversa lo suficiente como para saber que puede probar su versión de reemplazo adecuadamente, debe tener mucho cuidado.


3

Los principios más importantes para trabajar en tal situación son:

  1. Se paciente. Un agujero que tardó 20 años en excavar no se completará en unas pocas semanas.

  2. Ser positivo. Resista la tentación de quejarse y quejarse.

  3. Se pragmático. Mire un cambio positivo que puede lograr en un día y hágalo hoy. ¿Tienes un sistema de control de versiones todavía? Impleméntelo y capacite a las personas. Luego mire y vea si puede automatizar las pruebas (pruebas unitarias o algo similar). Enjuague. Repetir.

  4. Ser un modelo. Muestre (no solo diga) a las personas cómo funciona ágil siendo ágil. Los primeros tres puntos anteriores son las claves para ser un buen tipo, que es el predecesor de ser un tipo ágil eficaz. En mi opinión, las personas que son admirables desarrolladores no solo son inteligentes, también son buenos, empleados y colegas modelo.

  5. Mapa de su territorio. Tengo una técnica para mapear bases de código heredadas gigantes. Clono el repositorio, hago una copia de trabajo y luego trato de cambiar algo y veo qué más se rompe. Al investigar el acoplamiento (a través del estado global, o API rotas, o la falta de API consistente o cualquier abstracción o interfaz para programar) y al leer el código que se rompe cuando cambio las cosas, descubro el problema, hago preguntas que conducen a ideas del resto del equipo (¡Oh, lo agregamos porque Boss X hace 5 años lo exigía, nunca funcionó!). Con el tiempo, obtendrás un mapa mental del territorio. Una vez que sepa qué tan grande es, sabrá lo suficiente para hacer su mapa y llegar a casa. Anime a otros a mapear el territorio de su base de código gigante y a desarrollar el conocimiento técnico del equipo. Algunas personas se resisten a la "documentación" porque no es ágil Lo que sea. También trabajo en entornos científicos, y la documentación es lo más importante para mí, malditos manifiestos ágiles.

  6. Crea pequeñas aplicaciones. Cuando trabajo con una base de código heredada, descubro que me muevo a una pulpa. Recupero mi espíritu construyendo pequeñas aplicaciones de ayuda. Tal vez esas aplicaciones lo ayuden a leer, comprender y modificar esa base de código G2 gigante. Tal vez pueda hacer una mini IDE o herramienta de análisis que lo ayude a trabajar en su entorno. Hay muchos casos en los que la metaprogramación y la construcción de herramientas no solo lo ayudarán a salir de los puntos muertos gigantes que las bases de código heredadas le imponen, sino que también le dan a su cerebro la capacidad de volar sin restricciones por su lenguaje G2. Escriba sus herramientas y ayudantes en cualquier idioma en el que pueda hacerlos más rápido y mejor. Para mí, esos idiomas incluyen Python y Delphi. Si eres un chico de Perl, o si realmente TE GUSTA programar en C ++ o C #, entonces escribe tus herramientas de ayuda en ese lenguaje.


3
  1. Control de revisión : muestre a los expertos en dominios el beneficio de poder revertir, ver quién cambió qué, etc. (Esto es más difícil con archivos totalmente binarios, pero si el contenido es realmente código, seguramente hay algún tipo de G2-to- convertidor de texto que puede habilitar diffs.)

  2. Integración y prueba continuas : haga que los expertos en el dominio participen en la creación de pruebas de extremo a extremo (más fácil, ya que ya deben tener entradas y salidas esperadas en alguna parte) y pruebas de unidades pequeñas (más difícil, porque el código de espagueti probablemente involucra muchas variables globales) que cubren casi todas las funciones y casos de uso.

  3. Refactorice el código común en rutinas y componentes reutilizables. Las personas que no tienen software sin control de revisión probablemente copian y pegan cientos de líneas a la vez para hacer rutinas. Encuéntrelos y refactorícelos, mostrando que todas las pruebas pasan y que el código se ha acortado. Esto también te ayudará a aprender su arquitectura. Si tiene suerte cuando tenga que comenzar a tomar decisiones arquitectónicas difíciles, es posible que tenga 100KLOC.

Políticamente , si encuentra resistencia por parte de los antiguos en este proceso, contrate a un consultor para que venga y dé una charla sobre una buena metodología de software. Asegúrese de encontrar una buena con las opiniones con las que esté de acuerdo, y haga que la gerencia compre la necesidad del consultor incluso si los expertos en el dominio no lo hacen. (Deben estar de acuerdo, después de todo, lo contrataron, por lo que evidentemente se dan cuenta de que necesitan experiencia en ingeniería de software). Este es un truco que desperdicia dinero, por supuesto, pero la razón es que si usted, el nuevo programador de jóvenes, dice si necesitan hacer algo, pueden ignorarlo. Pero si la gerencia le paga a un consultor $ 5000 para que venga y les diga lo que necesitan hacer, confiarán más en ello. Puntos extra: haga que el consultor le aconseje el doble de cambios que realmente desea, entonces puede ser el "buen tipo" y ponerse del lado de los expertos en el dominio, comprometiéndose a cambiar solo la mitad de lo que sugirió el consultor.


3

"El programa en sí es un modelo físico de una planta compleja de procesamiento químico ..."

"Dado que G2 es como un código no, sino un código automatizado escrito por alguna GUI gadawful ..." - Erik Reppen

Asumiendo que el objetivo principal de su software es simular (quizás optimizar, ejecutar estimaciones de parámetros) una planta química compleja , o partes de una ... luego me gustaría lanzar una sugerencia bastante diferente:

Debería considerar utilizar un lenguaje de modelado matemático de alto nivel para extraer la esencia, los modelos matemáticos centrales, del software codificado a mano.

Lo que hace un lenguaje de modelado es desacoplar la descripción del problema de los algoritmos utilizados para resolverlo. Estos algoritmos son generalmente aplicables a la mayoría de las simulaciones / optimizaciones de una clase dada (por ejemplo, procesos químicos) en cuyo caso realmente no deberían reinventarse y mantenerse internamente.

Tres paquetes comerciales que se utilizan ampliamente en su industria son: gPROMS, Aspen Custom Modeller y (si sus modelos no incluyen fenómenos distribuidos a lo largo de dominios espaciales) hay paquetes de software basados ​​en Modelica, como Dymola.

Todos estos paquetes admiten "extensiones" de una forma u otra, de modo que si tiene partes de sus modelos que requieren programación personalizada, pueden encapsularse en un objeto (por ejemplo, un .DLL) al que pueden hacer referencia las ecuaciones en el modelo. Mientras tanto, la mayor parte de su modelo sigue siendo breve, descrito en una forma fácilmente legible por los científicos directamente. Esta es una forma mucho mejor de capturar el conocimiento y la propiedad intelectual de su empresa.

La mayoría de estos programas también deberían permitirle 'iniciar pequeñas' y portar pequeñas partes (submodelos) de su código monolítico en su formato, mediante una llamada externa. Esta puede ser una buena manera de mantener un sistema de trabajo y validarlo pieza por pieza.

Descargo de responsabilidad completo: trabajé como ingeniero de software en la compañía detrás de gPROMS durante 8 años. En ese momento vi (y ocasionalmente incorporé) ejemplos de software personalizado (por ejemplo, proveniente de la academia) que había comenzado pequeño y ordenado, implementando alguna solución o algoritmo inteligente, pero luego explotó a lo largo de los años con extensiones y modificaciones, sin la guía útil de Un ingeniero de software para mantenerlo limpio. (Soy un gran fanático de los equipos multidisciplinarios).

Por lo tanto, puedo decir con cierta experiencia que ciertas elecciones clave que se hicieron mal al principio del desarrollo de un software (como un lenguaje o biblioteca de claves) tienden a quedarse y causar dolor durante mucho tiempo ... Ya han "moldeado" el software a su alrededor. Me parece que podría estar enfrentando muchos años de limpieza de código puro aquí. (Dudo en usar números, pero estoy pensando en más de 10 personas años, tal vez mucho más si no puede transferir el código de G2 a algo que admita buenas herramientas de refactorización automatizadas como Eclipse / Java quick-smart).

Si bien mi estado predeterminado es "refactorizar y mantener un sistema de trabajo", también creo que una vez que un problema se vuelve "demasiado grande", un cambio / reescritura más radical se vuelve más rápido en general. (Y posiblemente traiga beneficios adicionales, como saltar a una tecnología más moderna). Digo eso con algo de experiencia portando a una nueva plataforma de software, pero de lo que deduzco es aún más dramático con un puerto a un paquete de modelado matemático.

Para dar una perspectiva, puede que te sorprenda la reducción de tamaño. Por ejemplo, los 200,000 LoC en realidad podrían representarse en algo así como 5,000 líneas de ecuaciones (OK, supongo que aquí, pero podría tratar de obtener un testimonio real de amigos en el negocio); más algunos módulos de funciones relativamente pequeños escritos en algo como C (por ejemplo, cálculos de propiedades físicas, aunque de nuevo pueden existir paquetes disponibles dependiendo de su proceso químico). Esto se debe a que, literalmente, simplemente desecha el código de solución algorítmica y deja que una 'pila' general de solucionadores matemáticos haga el trabajo duro. Una vez que tenga simulaciones en ejecución, puede hacer mucho más con ellas, como optimizar el proceso, sin cambiar una línea de código.

Finalmente, diría: si la única documentación confiable de los diversos modelos matemáticos (y algoritmos) es el código en sí, querrá la ayuda de los científicos y autores originales para ayudar a extraer esos modelos, lo antes posible, no años después. algunos de ellos pueden haber seguido adelante. Deben encontrar que un lenguaje de modelado matemático es una forma muy natural de capturar esos modelos; incluso pueden (horrorizar) disfrutar (re) escribirlo.


Finalmente, dado que mi respuesta podría estar fuera de lugar, me gustaría agregar un libro más a la lista de buenos libros que ya se mencionan aquí: Clean Code de Robert Martin. Lleno de consejos simples (y justificados) que son fáciles de aprender y aplicar, pero que podrían marcar una gran diferencia para las personas que desarrollan código nuevo en su empresa.


2

Tiraría lo siguiente:

  1. Hay un programador aquí. A la mierda la política. Ellos conocen su oficio. Ya sabes el tuyo. Marque ese territorio incluso si tiene que orinar en él. Son cientificos. Pueden respetar ese tipo de cosas o deberían hacerlo, ya que están haciendo constantemente lo mismo. Por cualquier medio que pueda, marque los límites ahora. Esto es lo que arreglaré. Esto es de lo que no puedo ser responsable.

  2. Los científicos escriben / prueban los algoritmos. Los científicos que lo deseen pueden escribir sus propios algoritmos en 1-3 idiomas en los que todos pueden ponerse de acuerdo para que usted los convierta a código central. Eso pone a prueba sus cosas en ellos. Más allá de eso, tendrán que ayudarlo a aislar las cosas importantes de la ciencia frente a lo que Dios sabe lo que hicieron por la arquitectura. La base de código está manguera. Es necesario hacer muchos cortes y quemaduras. Dales opciones para que te entreguen versiones de trabajo de cosas que empleen lo que mejor saben para que puedas hacer lo que mejor sabes hacer. Pegue sus conocimientos en una caja de la que son responsables pero con la que puede trabajar.

  3. Si puede, utilice un lenguaje amigable basado en eventos con funciones de primera clase. Cuando todo lo demás falla, desencadenar un evento o lanzar una devolución de llamada a algún objeto con una interfaz y un mecanismo de estado que realmente tiene sentido puede ser un gran ahorro de tiempo cuando estás en código hasta las rodillas que no tiene ningún sentido sangriento y posiblemente nunca será. A los científicos parece gustarles Python. No es difícil pegar cosas C intensivas en matemáticas de nivel inferior con eso. Sólo digo'

  4. Busque a alguien que haya resuelto este o un problema similar. Pasa un tiempo serio investigando. Estos muchachos escucharon sobre G2 de alguien.

  5. Patrones de diseño. Adaptadores. Úsalos. Úsalos mucho en situaciones como esta.

  6. Aprende lo que puedas de la ciencia. Cuanto más sepa, mejor podrá determinar la intención en el código.


13
NUNCA vaya cara a cara con los científicos. NUNCA . Harán de tu vida un infierno. :)
haylem

2

Haz el análisis primero.

Haría un análisis antes de decidir qué enseñar. Averigua dónde están los mayores puntos de dolor. Úselos para priorizar qué prácticas repasar.

Presente solo unos pocos cambios a la vez (en una situación similar hice 2-3 prácticas cada 2 semanas) .

Limitaría las prácticas a ~ 3 dependiendo del nivel de cambio al estilo de programación de SDLC; hasta que comiencen a sentirse cómodos con ellos (presionaría para introducir 1 cambio nuevo cada ~ 1-2 semanas a medida que se sientan más cómodos con la idea de aprender nuevos enfoques). También es una buena idea identificar cuáles son los criterios para el éxito. Lo que la práctica debe lograr (incluso si es un objetivo suave como la moral del equipo). De esa manera puedes mostrar si es efectivo o no.

  • ¿Por qué limitar el número de cambios?

Incluso si asume que estas personas quieren ser mejores programadores y están abiertos al aprendizaje, existen límites sobre cuánto y qué tan rápido las personas pueden aprender nuevos conceptos y aplicarlos; especialmente si no tienen una base CS o han participado en un ciclo de vida de desarrollo de software anteriormente.

Agregue una reunión de cierre semanal para discutir cómo las prácticas los afectaron.

La reunión debe usarse para discutir lo que salió bien y lo que necesita trabajo. Permítales tener voz y ser colaborativos. Discuta y haga planes para abordar los problemas que están teniendo y para ver los próximos cambios que se avecinan. Mantenga la reunión enfocada en las prácticas y su aplicación. Evangeliza un poco sobre los beneficios que deberían comenzar a ver al aplicar las prácticas.

Ciertas prácticas tienen prioridad.

El uso adecuado de un sistema de control de versiones (IMO) supera a todo lo demás. Muy cerca están las lecciones de modularización, acoplamiento / cohesión y seguimiento de tickets de características / errores.

Eliminar las prácticas que no funcionan.

No tenga miedo de deshacerse de las prácticas que no funcionan. Si hay un alto costo y poco o ningún beneficio, elimine la práctica.

La mejora es un proceso.

Transmitir que la mejora sostenida y constante es un proceso. Identifique los puntos de mayor dolor, aplique una solución, espere / entrene y luego repita. Se sentirá agonizantemente lento inicialmente hasta que acumule algo de impulso. Mantenga a todos enfocados en las mejoras que se avecinan y en las mejoras que ya son exitosas.


0

Parece que el primer paso que tienes es venderle al equipo la necesidad de invertir en una nueva metodología de software. Según su declaración, no hay consenso en el equipo, y lo necesitará para poder avanzar con una lenta "actualización" del código.

Si pudiera, personalmente tomaría las duras lecciones aprendidas e introduciría cada uno de los conceptos clave que desea como solución al problema en la industria del software.

Por ejemplo, dos desarrolladores tenían copias diferentes y terminaron implementando una versión híbrida no probada -> Introducir control de versiones, ramificación y pruebas.

Alguien eliminó algunas líneas de código que no entendieron y causó una interrupción -> presentar DDD.

Si las lecciones difíciles no se comparten con usted con suficiente detalle, simplemente muestre sus propios ejemplos de cómo las cosas salieron mal cuando no se respetó esta disciplina.


0

El control del código fuente es el paso 1, como ya se ha dicho muchas veces. Si bien las personas con las que trabaja pueden no ser desarrolladores profesionales y no responderán a muchas mumbo jumbo ágiles o empresariales. Tampoco son monos de código de bajo nivel y tratar de tratarlos así obligándolos a hacer cosas "a tu manera" no funcionará.

Tienes que estudiar qué hay ahí fuera. Si no han usado el control del código fuente, simplemente identificar las versiones correctas del código (si es posible) y cuáles son todos los posibles entregables llevará mucho tiempo. Entonces tendrá la tarea de enseñar a sus colegas cómo usar el control del código fuente y convencerlos de que vale la pena su tiempo. Comience con los beneficios!

Mientras lo haces, busca otras frutas bajas y soluciona esos problemas.

Sobre todo, escuche lo que tienen que decir y trabaje para mejorar su situación. No te preocupes por tratar de poner tu sello en lo que hacen.

¡Buena suerte!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.