it-swarm-es.com

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

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 compleja de procesamiento químico; El equipo que lo escribió tiene un conocimiento de dominio increíblemente profundo pero poca o ninguna capacitación formal en los fundamentos de 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 propio código. Le ahorraré la "política" de la situación (¡hay siempre política!), Pero es suficiente decir que no hay un consenso de opinión sobre qué es necesario 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 The Pragmatic Programmer , o Fowler's Refactorización ("Código de olores", 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?.

Entonces esa es mi pregunta: ¿Qué incluiría usted en su lista de las estrategias más efectivas para ayudar a enderezar el espagueti (y prevenirlo en el futuro)?

468
kmote

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 que, como tales, deben adoptarse, adaptarse o descartarse en función de las circunstancias.

Cuidado: Volcar todo esto en un equipo a la vez probablemente fallará. Debes tratar de elegir elementos que te den 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 Anexo al final.


Resumen ejecutivo para el paciente impaciente

  • Defina una estructura de proyecto rígida , con:
    • plantillas de proyecto ,
    • convenciones de codificación ,
    • sistemas de compilació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.
  • Apúntelos a IDE buenos por su tecnología, y asegúrese de que sepan cómo usarlos.
  • Implemente verificadores de calidad de código y informes automáticos en el sistema de compilación.
  • Acople el sistema de compilación a integración continua y sistemas de inspección continua .
  • Con la ayuda de lo anterior, identifique código "hotspots" de calidad y refactor .

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 tu 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 quiere esto 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. Desea poder hacer lo canónico y no tener que preocuparse por 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 un README rápido para señalar 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 pautas y convenciones 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 no debe romperse 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 yo 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 herramienta gofmt, que elimina por completo cualquier debate y esfuerzo ( y ego !! ) inherente al estilo: run gofmt antes de comprometerse.

Asegúrese de que la descomposición del código no pueda pasar. Convenciones de código , integración continua y inspección continua , programación de pares y revisiones de código son tu 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 que expresen 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 de desarrollar una cultura de equipo . Pero es muy importante que todos sepan qué es aceptable y qué no, 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 lo omita para llegar a casa a tiempo o continuar con la siguiente tarea, o 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 divertidas para cometas gigantes o para hacks no obvios.

Los compromisos se realizan por una razón, y esa razón NO siempre se expresa 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 un historial . 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 Git hace esto bien y trata de forzarte a escribir buenos registros más que la mayoría de los otros sistemas SCM, usando short logs y long logs. Enlace el ID de la tarea (sí, necesita uno) y deje un resumen genérico para 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 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 generales:

  • 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 usa 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 por 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 usando otro, o implementar un nuevo módulo usando 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:

  • productivo ,
  • NO requiere asistencia regularmente
  • NO se ajusta regularmente a su infraestructura general ,
  • NO interrumpiendo 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. Permitir 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 [~ # ~] deja 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

  • Desarrolle un sentido de orgullo en el código

Evita los juegos de culpa

  • SÍ use juegos de Integración continua/Inspección continua: fomenta buenos modales y competencia productiva .
  • HAGA un seguimiento de los defectos: es solo una buena limpieza.
  • HACER identificar las causas raíz : son solo procesos a prueba de futuro.
  • PERO NO asignar 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 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? Para código de calidad . ¿O es 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 inspección continua . Sonar es uno de los más populares en el mundo Java, pero puede adaptarse a cualquier tecnología; y hay muchas otras. Mantenga su código bajo el microscopio y búsquelo bichos molestos molestos y microbios.


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: necesita comenzar en algún lugar .

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

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

¿Cómo lo hicimos? Acabamos de hacer todo lo anterior. O lo intenté 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 que apresuradamente cortando el "gordo": código basura, dependencias inútiles ... No detuvimos todo el desarrollo para hacer esto: tenemos períodos ocasionales de relativa paz y tranquilidad donde son libres de volverse locos en la base de código y desgarrarla, pero la mayoría de las veces lo hacemos todo de forma predeterminada a un modo de "revisión y refactorización" cada oportunidad que tenemos: durante las construcciones, durante el almuerzo, durante los sprints de corrección de errores, el viernes tardes ...

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 la superficie en busca de errores en su codifica mucho.

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 refactorice las cosas), pero en general el beneficio para nuestra moral Y para el 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 necesita 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 imponer algunas cosas en nosotros, y mal para otros. O tal vez ellos solían tener razón . Las cosas cambian. Demuestre que son mejores formas de aumentar su productividad. Pruebas y 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 críticos Frutos bajos .

    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. Repara 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 significativas 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 , según una solicitud de atención al cliente:

    • Por lo general, es una buena práctica [~ # ~] no [~ # ~] solucionar otros problemas, ya que podría introducir otros nuevos de mala gana.
    • Vaya estilo SEAL: entre, elimine el error, salga y envíe su parche. Es un golpe quirúrgico y táctico.
  • Pero para todos los demás casos , si abre un archivo, haga su deber:

    • definitivamente: revise (tome notas, informe de problemas de archivos),
    • tal vez: clean it (limpiezas de estilo y violaciones menores),
    • idealmente: refactorizar (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 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, yo mismo trabajé en uno de estos. 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 visual IDE que usaba las campanas y silbidos usuales: interfaces de arrastrar y soltar, espacios de trabajo de proyectos versionados (usando archivos de texto y XML para el almacenamiento de metadatos), muchas controladores conectables a fuentes de datos heterogéneas y un lienzo visual para diseñar tuberías para procesar datos de fuentes de datos N 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 personalizado, 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 sistema agradable, 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.

Sobre versiones y almacenamiento

Al final, casi siempre puede versión cosas, incluso con el entorno más restringido 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 anteproyecto 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:

  • Documento todo lo que haces.
  • Comparta su experiencia.
  • Código abierto 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 brinde ayuda a otras personas y fomente la discusión sobre su pila de tecnología.

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

Tal vez es hermoso por dentro , pero nadie tiene una pista hasta ahora, así que ayuda derriba este muro feo y ¡deja que otros echen un vistazo!

464
haylem

El primer 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 origen 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

101
Yusubov

Cuando tengo que trabajar con código de espagueti, lo primero en lo 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 se enfrentará 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 suficientemente fuerte, ya que puede hacer que el compilador haga mucho trabajo pesado por usted. Realiza un cambio en algún lugar que romperá (intencionalmente) 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 al refactorizar.

43
Mason Wheeler

No sé si esta es una opción para usted, pero comenzaría a tratar de convencerlos de que contrate 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.

22
Gilney

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 versión . Git o Mercurial por ejemplo.
  • Obtenga algún tipo de sistema de integración continua (por ejemplo, Jenkins ) en funcionamiento.
  • Obtenga un sistema de seguimiento de errores en funcionamiento. Mantis es bastante agradable en mi opinión.
  • Examine 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 (por lo general, hay una razón por la cual el código parece cierto por qué, puede ser bueno o malo, o ambos; P). Michael Feathers trabajando eficazmente con código heredado es un excelente recurso para esto.
20

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. ¿Una buena herramienta para generar un 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 acerca de los problemas que resultan de demasiadas interdependencias y tal vez arroje na 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. El objetivo, sin embargo, 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 estén todos a bordo, más rápidos serán los beneficios.

10
Caleb

Después de mirar un poco en 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í:

enter image description here

o esto:

enter image description here

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 muy sabio consejo para tratar con él.

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 como operación de exploración ) que no parece ser así en primera vista.

Aunque obviamente su primera prioridad será obtener algún tipo de control de versión en línea, como se señaló ElYusubov , y parece que el control de versión ha sido compatible desde la versión 8. . 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 algo más 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 está implementado 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 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 cierta 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 es también 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 acercarse a la refactorización de la manera 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 en el que 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.

9
rjzii

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 el 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, p. Ej. APIs, 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. Segunda sesión informativa
  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
Chui Tey

Preguntas como estas son la razón por la cual existe el proyecto 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 (corto) libro de Robert Glass Hechos y Falacias de la Ingeniería del Software: su enfoque basado en evidencia es un buen Una forma 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 una simple opinión.
En cuanto a las prácticas específicas, las dos que las personas 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 Trabajando 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 McConnell es Code Complete es demasiado para empezar (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" ( ¡Computación en ciencia e ingeniería, mayo-junio de 2005), que describe Un enfoque de "defensa en profundidad" que combina una docena de prácticas diferentes de una manera lógica y coherente.

9
Greg Wilson

Creo que antes que nada tienes que 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 quizás 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 del 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 inmediatamente ) ...

¿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 la implementación de 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í, dentro del cual usted o ellos deberían 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

7
Lorand Kedves

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 en G2, pero ya que estás buscando 5 -7 fundamentos básicos, estos parecen un conjunto bien establecido para comenzar. Si quieres redondearlo a 7, puedes comenzar con DRY y tirar Fail-Fast.

4
StriplingWarrior

"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 sobre) una planta química compleja , o partes de una ... entonces yo ' 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, fuera de 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 utilizados 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ó con 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).

De modo que puedo decir con cierta experiencia que ciertas elecciones clave que se tomaron 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 por año, 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. P.ej. 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, ASAP, no años después cuando 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.

3
Luke Usherwood

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, el primer consejo que daría es resistir la necesidad 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 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 la ingeniería inversa lo suficiente como para saber que puede probar su versión de reemplazo adecuadamente, debe tener mucho cuidado.

3
Bill

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

  1. Se paciente. Un agujero que le llevó 20 años a Dig 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 APIs rotas, o la falta de API consistente o cualquier abstracción o interfaz contra la cual 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. Aliente 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 oponen 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 una herramienta de análisis que lo ayudará 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 del gigante puntos muertos que las bases de código heredadas te imponen, también le dan a tu cerebro la capacidad de volar sin restricciones por tu lenguaje G2. Escribe tus herramientas y ayudantes en el idioma que puedas hacer 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 idioma. Enseña al resto del equipo a construir pequeñas aplicaciones y herramientas de ayuda, y "componentes" y tú " Eventualmente veré que su base de código heredada no es tan desalentadora después de todo.

3
Warren P
  1. Control de revisión: muestra a los expertos del dominio 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 convertidor de G2 a texto que pueda habilitar diffs.)

  2. Integración continua y prueba: 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 probablemente el código de espagueti involucra muchas variables globales) que cubren casi todas las funciones y casos de uso.

  3. Refactorizar código común en rutinas y componentes reutilizables. Las personas sin software sin control de revisión probablemente copien y peguen 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 de los antiguos temporizadores 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 deben hacer, confiarán más en ello. Puntos de bonificación : haga que el consultor le aconseje el doble de cambios que realmente desea, luego puede ser el "buen tipo" y ponerse del lado de los expertos en dominios , comprometiéndose a cambiar solo la mitad de lo que sugirió el consultor.

3
Conrad Poelman

Haga 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.

Introducir 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 empiecen 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 tienen 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) triunfa sobre 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 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.

2
dietbuddha

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 ellos mismos 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. Idealmente, cuando las cosas van bien en un mega-refactor, las conversaciones serán más sobre qué tipo de cosas emocionantes puede hacer con la interfaz en lugar de lo que hizo el tentáculo Z9 de drBobsFuncStructObjThingMk2_0109 cuando enojó a la var X19a91 global.

  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.

2
Erik Reppen

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 utilizado 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!

0
Bill

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.

P.ej. dos desarrolladores tuvieron 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 -> introduzca 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
M Afifi