2009-06-10 7 views
28

Joel says to never do it, y estoy de acuerdo con esto en la mayoría de los casos. Creo que hay casos en que está justificado.¿Alguna vez ha hecho una reescritura total de una gran aplicación de C++ en C#?

Tenemos una gran aplicación C++ (alrededor de 250,000 líneas de código en total) que usa una interfaz MFC y un servicio de Windows como componentes principales. Estamos pensando en mover el proyecto a C#.

Las razones por las que estamos pensando en volver a escribir son:

  1. más rápido tiempo de desarrollo
  2. El uso de WCF y otros elementos de construcción en .NET
  3. operación más consistente en varios sistemas
  4. más fácil Soporte de 64 bits
  5. Muchas buenas bibliotecas .NET y componentes por ahí

¿Alguien ha hecho una reescritura como esta? ¿Fue exitoso?


EDIT:

El proyecto es de casi 10 años de edad ahora, y estamos llegando al punto en que la adición de nuevas características que deseamos estar escribiendo una importante funcionalidad que ya NET tiene incorporada .

+3

Tengo mucha curiosidad por las respuestas a esta, ya que estoy en una situación similar. –

+2

como yo, aunque en mi caso, se está moviendo de las bibliotecas propietarias de tiempo de ejecución innecesarias que codificamos en la vía C (no ++) – Firoso

+4

Depende del "Por qué" lo está haciendo. ¿Por qué romper algo que funciona? Sugeriría que no lo hagas a menos que tengas una buena razón. No tengo experiencia en la conversión de una aplicación grande como esta, pero me da miedo ;-) – Shoban

Respuesta

49

¿Ha pensado que en lugar de volver a escribir desde cero debería empezar a separar la GUI y la capa de fondo si no lo está, entonces puede comenzar a escribir fragmentos en C#.

las 250,000 líneas no se escribieron de la noche a la mañana, contienen cientos de miles de años humanos de esfuerzo, por lo que nadie lo suficientemente sano sugeriría volver a escribir todo desde cero de una vez.

El mejor enfoque si ustedes quieren hacerlo es pieza por pieza. de lo contrario, solicite varios años de esfuerzo de desarrollo de su administración mientras no se implementen nuevas características en su producto existente (básicamente estancado frente a la competencia)

+4

Los gerentes piensan que la conversión es línea por línea ... – vidalsasoon

+10

Sí, hágalo pieza por pieza y comience por modularizar su aplicación actual, para poder reutilizar algunos componentes C++ (por ejemplo, como DLL) desde su C# reescribe – none

+8

Acepto. Si bien no es de C++ a C#, estamos en el año 5 de un proyecto de 1 año para reescribir nuestra aplicación heredada. Podría haberse hecho en pedazos sin que el cliente lo sepa. Por supuesto, eso no es tan llamativo como un nuevo sistema. –

19

Ha sido probado antes, no solo C++ => C#, sino VB6 => VB .NET, C++ => Java y cualquier otro antiguo => nuevo que se te ocurra. nunca funcionó realmente Creo que debido a que las personas no consideran que la transformación de lo que realmente es (una reescritura total) tienden a tomarlo a la ligera.

La historia de migración de C++ => .NET debe ser a través de CLI, decidiendo cuidadosamente qué gestiona y qué queda sin gestionar y s-l-o-w-l-y "arreglando" pieza por pieza.

12

Expression Blend fue originalmente una aplicación MFC. La versión actual usa WPF para la interfaz de usuario, pero el motor todavía es completamente nativo. Vi una gran charla del arquitecto principal Henry Sowizral hace aproximadamente un año donde describió el proceso de la migración. Haga que la interfaz de usuario del motor sea independiente y podrá soportar la última tecnología de interfaz de usuario. El equipo Expression en un momento tuvo lo que él llamó la versión con cabeza de hidra. Dos interfaces de usuario de interfaz de usuario que se ejecutan simultáneamente con un motor subyacente: de esta forma podían ver dónde el comportamiento se había desviado involuntariamente de la versión anterior. Dado que la IU se suscribió a eventos y notificaciones, los cambios realizados en una ventana de herramientas de WPF se reflejaron en la ventana de herramientas de MFC anterior.

EDITAR: Parece que algunas tomas de corriente son available here o como html here.

4

C++ no se traducirá automáticamente a C# (no es así que desea mantenerlo, de todos modos), y está hablando de utilizar diferentes marcos.

Eso significa que está haciendo una reescritura total de 250K líneas de código. Esto es efectivamente lo mismo que un nuevo proyecto de línea de 250K, excepto que tienes los requisitos bien especificados para comenzar. Bueno, no "muy bien"; sin duda hay algún código difícil de entender, algunos probablemente debido a cuestiones importantes que dificultan la elegancia y la estructura general se verá algo oscurecida.

Ese es un proyecto muy grande. Al final, lo que tendrá es un código que hace lo mismo, probablemente con más errores, probablemente bastante mal estructurados (aunque puede refactorizarse con el tiempo), con más potencial para el desarrollo futuro. No tendrá ninguna de las nuevas características que la gente ha estado pidiendo durante el proyecto (a menos que le guste vivir peligrosamente).

No estoy diciendo que no lo haga. Estoy diciendo que debe saber lo que está proponiendo, cuál será el costo y cuáles serían los beneficios. En la mayoría de los casos, esto se suma a "¡No hagas eso!"

2

Reescritura total por el bien de reescribir? Yo no lo recomendaría.

+0

No lo haríamos solo por el bien de una reescritura. Las razones se enumeran en la pregunta. –

+0

Mis disculpas por la respuesta corta. En mi experiencia, la mayoría de las reescrituras principales han sido patrocinadas por la empresa a la que estoy prestando servicios, y la mayoría de eso sucedió porque calculamos la refacturación de una gran parte de la base de código. –

3

Hice algo similar. Parte de mi trabajo consiste en desarrollar & compatible con algún software llamado ContractEdge. Originalmente fue desarrollado en Visual C++ 6 por un equipo en India. Luego asumí el rol de desarrollo después de que básicamente se realizó en 2004. Más adelante, cuando Windows Vista estuvo disponible como versión Beta, descubrí que ContractEdge se bloqueaba en Vista. Lo mismo sucedió en el lanzamiento del candidato.

Así que tuve que tomar una decisión. O busca el problema en decenas de miles de líneas de código desconocido en su mayoría, o aprovecha la oportunidad para volver a escribirlo en .NET. Bueno, lo reescribí en VB.NET 2.0 en aproximadamente 2 meses. Lo enfoqué como una reescritura total, esencialmente descartando todo y simplemente me centré en duplicar la funcionalidad con un lenguaje diferente. Resultó que solo tuve que escribir aproximadamente la décima parte del número de líneas del código original. Luego llevamos a cabo un programa beta de un mes de duración para eliminar cualquier error restante. Inmediatamente después lo lanzamos y ha sido un gran éxito desde entonces, con menos problemas que la versión de C++ que reemplazó.

En nuestro caso particular, creo que la reescritura funcionó bien. La decisión se hizo más fácil en base al hecho de que nadie en nuestro equipo estaba tan familiarizado con C++ como lo estaban con .NET. Entonces, desde esa perspectiva, la facilidad de mantenimiento ahora es mucho más fácil. Hoy en día creo que C++ tiene un nivel de lenguaje demasiado bajo para la mayoría del software de negocios. Realmente se puede hacer mucho más en .NET con menos código. Escribí sobre este tema en mi blog.

+0

Buen punto. ¿Realmente necesitas las más de 250 líneas? – gbn

+1

Exactamente. Casi puedo garantizar que una reescritura total en C# reduciría drásticamente el tamaño del proyecto. Eso por sí solo no suele ser motivo suficiente para reescribir una aplicación. Pero si la aplicación está empezando a experimentar dolores de crecimiento de otras maneras, puede ser hora de considerarlo. –

+1

@ gbn, TheSteve - El proyecto tiene ahora casi 10 años. Definitivamente hay dolores de crecimiento, y estamos llegando al punto en que comenzaríamos a escribir funcionalidades significativas que el framework .NET ya tiene incorporado. –

19

Mi empresa realmente hizo eso. Teníamos una base de código C++ de aproximadamente ese tamaño, y todos (programadores, administradores, clientes) coincidieron más o menos en que no era la mejor pieza de software. Queríamos algunas características que hubieran sido extremadamente difíciles de implementar en la antigua base de códigos, así que decidimos (después de muchas discusiones y proyectos de prueba) reescribirla en .NET. Reutilizamos el código que era lo suficientemente modular usando C++/CLI (aproximadamente el 20% de él, principalmente material de trituración de números críticos para el rendimiento que debería haber sido escrito en C++ de todos modos), pero el resto fue reescrito desde cero. Le tomó cerca de 2 años-hombre, pero ese número realmente depende mucho del tipo de aplicación, del tamaño de su equipo y de sus programadores, por supuesto. Consideraría todo un éxito: pudimos volver a diseñar todo el sistema para habilitar nuevas características que hubieran sido casi imposibles con la antigua base de códigos.También pudimos evitar los problemas que a menudo teníamos en el viejo software rediseñando a su alrededor. Además, el nuevo sistema es mucho más flexible y modular en los lugares donde aprendimos que se necesitaba flexibilidad. (En realidad, a veces me sorprende la facilidad con la que se pueden incorporar nuevas características en el nuevo sistema, aunque nunca pensamos en ellas cuando lo diseñamos).

En pocas palabras: para un proyecto de tamaño mediano (100k- 500kloc) una reescritura es una opción, pero definitivamente debe ser consciente del precio y arriesgarse a tomarlo. Solo lo haría si la antigua base de código es realmente de baja calidad y se resiste a la refactorización.

Además, hay dos errores que no debes hacer:

  1. contratar a un nuevo programador .NET y dejar que él/ella haga la reescritura - alguien nuevo puede ayudar, pero la mayor parte del trabajo y sobre todo el diseño tiene que ser hecho por desarrolladores que tengan suficiente experiencia con el código anterior, por lo que tienen una sólida comprensión de los requisitos. De lo contrario, simplemente repetirá sus viejos errores (más algunos nuevos) en un idioma diferente.
  2. Deje que un programador de C++ reescriba como su primer proyecto de C#. Esa es una receta para el desastre, por razones obvias. Cuando aborda un proyecto de ese tamaño, debe tener una comprensión sólida del marco que está utilizando.

(creo que estos dos errores podrían razones por las que muchas reescrituras fallan.)

+4

Creo que estás 100% en lo cierto con respecto al primero de los dos errores que mencionas, golpea. Reescribir un proyecto es una gran oportunidad para arreglar muchas cosas, pero solo si sabe exactamente qué salió mal con la primera iteración. El tipo que desarrolló el primero (si todavía está cerca) tendrá información que un novato del s/w no tendrá todavía. – bobobobo

2

Además de otras respuestas, yo no tomaría "tiempo de desarrollo más rápido" por sentado. Claro, para la mayoría de las aplicaciones centradas en datos "empresariales" probablemente sea el caso, pero hay muchas áreas en las que .NET no generará aumentos de productividad significativos, además de que debe tener en cuenta la curva de aprendizaje.

+0

Tiene razón, .NET no es la mejor solución para ningún tipo de problema, pero en un proyecto de ese tamaño, suele haber muchas "cosas de arquitectura OOP" o "código de pegamento" o como se llame. Ahí es donde el sistema de módulos .NET, el sistema de tipo unificado, los metadatos GC, los eventos (...) realmente brillan en contraste con C++. Y aún puede escribir módulos en C++/CLI de todos modos. – Niki

+0

@Niki - Sí, nuestra aplicación definitivamente se beneficiará de las nuevas características de .NET framework. –

1

¿Ha considerado un puerto para C++. NET? Puede ser menos doloroso.

2

Hemos realizado una gran migración de C++ >> C# a medida que nos movemos a .NET. Es un proyecto bastante difícil. La administración difícilmente se morderá los fondos, así que debes buscar un compromiso. El mejor enfoque es dejar las capas más internas (o más bajas) en C++ y cubrir la parte superior con C#, con mejores API diseñadas con conceptos más nuevos como legibilidad y usabilidad de API en mente, protegidas con pruebas unitarias y herramientas avanzadas como FxCop. Estas obviamente son grandes victorias.

También le ayuda a nivelar sus componentes un poco mejor, ya que obliga a realizar ciertos cortes. El producto final no es agradable, ya que podría terminar copiando mucho código en C++ porque años y años de codificación contienen muchas correcciones de errores y muchas optimizaciones indocumentadas y difíciles de entender. Agregue a eso todos los trucos de puntero que podría hacer en C (nuestro código ha evolucionado de C a C++ a lo largo del tiempo). A medida que se estabiliza, se encuentra leyendo cada vez más el código C++ y moviéndolo hacia el C#, en lugar de los objetivos de "diseño más limpio" que tenía en mente al principio.

Luego descubres que el rendimiento de interoperabilidad es una mierda. Eso puede requerir una segunda reescritura, tal vez ahora use código inseguro C#. Grrr!

Si todos los miembros del equipo provienen de C++, el nuevo código también se ve como un diseño de C++. Intenta buscar una combinación de desarrolladores de C# y C++ en el equipo, para que puedas obtener una API más similar a .NET al final.

Después de un tiempo, el proyecto puede perder interés y mgmt puede no financiar la relectura completa, por lo que terminará obteniendo un código C++ sin caparazón C#, y aún puede tener problemas unicode/64 bits sin resolver. Realmente requiere una planificación muy, muy cuidadosa.

1

Actualmente estoy reescribiendo una aplicación web bastante grande.

Una cosa para recordar es que al convertir de un idioma a otro especialmente algo como C++ a .Net es que puede terminar con menos, y probablemente más limpio, código debido a avances de lenguaje o código de marco.

Esa es una ventaja para la mantenibilidad futura, incluso aparte de la oportunidad de volver a diseñar los aspectos menos robustos de la aplicación anterior.

0

Curiosamente, la mayoría de las respuestas de las personas que han hecho esto parecen positivas. Lo más importante de IMO es tener buenas pruebas unitarias para que pueda estar seguro de que su reescritura hace lo que quiere que haga (que puede no ser exactamente igual a lo que hacía el código anterior).

+0

así que uno quiere decir que fallaron! –

5

He pasado por un proyecto que hizo exactamente lo que está describiendo con aproximadamente la misma base de código de tamaño. Inicialmente, estaba completamente a bordo con la reescritura. Terminó tomando más de 3 años y casi se convirtió en una marcha de la muerte. En general, ahora estoy de acuerdo mucho más con los incrementalistas.

Sin embargo, basándonos en nuestra experiencia, diré que tal reescritura (especialmente si puede reutilizar algún código de lógica de negocio C++ en .NET), no es tan técnicamente peligrosa como pueda parecer. Sin embargo,, ¡puede ser muy peligroso socialmente!

En primer lugar, debe asegurarse de que todo el mundo entienda que lo que está haciendo inicialmente es una "reescritura" (o "nueva versión"), no una actualización o "reinvención". El Psycho de 1998 fue una nueva versión de 1960 original. El 2003 Battlestar Galactica fue una reinvención del original de 1978. ¿Ver la diferencia?

En nuestro caso, el plan inicial era recrear el producto existente en .NET. Eso no habría sido técnicamente desalentador, ya que entendimos bien el original. Sin embargo, en la práctica, el impulso de agregar, corregir y mejorar solo unas pocas cosas resultó irresistible y, en última instancia, agregó 2-3 años a la línea de tiempo.

En segundo lugar, debe asegurarse de que todos, desde los ejecutivos hasta el personal de ventas y los usuarios finales, estén de acuerdo con que su producto actual permanezca inalterado durante el desarrollo de la nueva versión. Si su mercado se está moviendo de tal manera que no podrá mantener su negocio durante ese período, entonces no lo haga.

Así que los principales obstáculos para nosotros resultaron ser sociales, en lugar de técnicos. Los usuarios y los intereses comerciales se frustraron mucho con la falta de progreso visible. Todos se sintieron obligados a impulsar sus propias mejoras y características propias, por lo que nuestro producto final tenía solo un parecido superficial con el original. Definitivamente fue una reinvención en lugar de un remake.

Al final, parece que nos ha ido bien, pero fue una verdadera rutina, y no es algo que elegiríamos hacer de nuevo. Nos quemamos con mucha buena voluntad y paciencia (tanto interna como externa), que en gran medida se podrían haber evitado con un enfoque gradual.

1

Algunos comentarios adicionales.

Dependiendo de la vida útil de su aplicación, puede verse obligado a reescribirla en un lenguaje moderno ya que sospecho que los desarrolladores de C++ serán cada vez más difíciles de encontrar.

Simplemente moviendo la aplicación a un nuevo idioma no obtendrá grandes recompensas. ¡También querrás rediseñar la aplicación! No subestimes el esfuerzo requerido para hacer esto. Supongo que el esfuerzo para rediseñar + reescribir podría ser tanto como 50% del esfuerzo para la implementación original. (Por supuesto, 50% es una suposición totalmente no científica).

Es una manera fácil de engañarse a sí mismo al pensar "Bueno, C# y WPF son mucho más productivos que reescribir este desastre sería un pedazo de pastel".

2

Estuve involucrado en un proyecto de tamaño muy similar. Fue necesario volver a escribir la interfaz gráfica de usuario debido a nuevo hardware y nuevos requisitos. Decidimos portar esto a .NET usando C++/CLI. Pudimos reutilizar más de la mitad del código y hacerlo funcionar bastante bien.

Pudimos aprovechar .NET donde tenía más sentido. Esto hizo que las partes principales del código fueran mucho más limpias. Encontramos muy útil el libro "Pro Visual C++/CLI y la plataforma .NET 2.0" de Stephen R. G. Fraser.

Cuestiones relacionadas