2009-05-31 13 views
6

Estoy trabajando en un proyecto que (pronto) se ramificará en múltiples versiones diferentes (Trial, Professional, Enterprise, etc.).Estrategias para desarrollar múltiples productos desde One Codebase

He estado utilizando Subversion desde que se lanzó por primera vez (y CVS antes), así que me siento cómodo con la noción abstracta de ramas y etiquetas. Pero en toda mi experiencia de desarrollo, solo he trabajado en el código troncal. En algunos casos excepcionales, algún otro desarrollador (que era el dueño del repositorio) me pidió que confirmara los cambios en una determinada rama y simplemente hice lo que él me pidió que hiciera. Considero que "fusionar" un extraño arte negro, y solo lo he intentado bajo una cuidadosa supervisión.

Pero en este caso, soy responsable del repositorio, y este tipo de cosas es totalmente nuevo para mí.

La gran mayoría del código se compartirá entre todos los productos, por lo que supongo que el código siempre residirá en el enlace troncal. También asumo que tendré una rama para cada versión, con etiquetas para compilaciones de lanzamiento de cada producto.

Pero más allá de eso, no sé mucho, y estoy seguro de que hay mil y una maneras diferentes de arruinarlo. Si es posible, me gustaría evitar arruinarlo.

Por ejemplo, supongamos que quiero desarrollar una nueva característica, para las versiones pro y enterprise, pero quiero excluir esa característica de la versión demo. ¿Cómo podría lograr eso?

En mi desarrollo diario, también asumo que necesito cambiar mi instantánea de desarrollo de una rama a otra (o volver al tronco) mientras trabajo. ¿Cuál es la mejor manera de hacerlo, de una manera que minimice la confusión?

¿Qué otras estrategias, pautas y sugerencias sugieren?


ACTUALIZACIÓN:

Bueno, está bien entonces.

Parece que la bifurcación no es la estrategia correcta en absoluto. Así que cambié el título de la pregunta para eliminar el foco de "ramificación" y estoy ampliando la pregunta.

supongo que algunos de mis otras opciones son:

1) Siempre podía distribuir la versión completa del software, con todas las características, y el uso de la licencia para habilitar selectivamente y desactivar características en base a la autorización de la licencia . Si tomo esta ruta, puedo imaginar un nido de ratas de bloques if/else llamando a un único objeto de "administrador de licencias" de algún tipo. ¿Cuál es la mejor manera de evitar el espagueti-código en un caso como este?

2) Podría usar la inyección de dependencia. Pero en general, lo odio (ya que mueve la lógica del código fuente a archivos de configuración, lo que hace que el proyecto sea más difícil de asimilar). Y aun así, sigo distribuyendo la aplicación completa y seleccionando funciones en tiempo de ejecución. Si es posible, prefiero no distribuir los archivos binarios de la versión empresarial a los usuarios de demostración.

3) Si mi plataforma admite la compilación condicional, podría usar bloques #IFDEF y marcadores de compilación para incluir funciones de forma selectiva. Eso funcionaría bien para funciones grandes y gruesas, como paneles de GUI completos. ¿Pero qué hay para los conciertos más pequeños y transversales ... como la tala o el seguimiento estadístico, por ejemplo?

4) Estoy usando ANT para compilar.¿Hay algo así como la inyección de dependencia de tiempo de compilación para ANT?

Respuesta

2

Una pregunta más interesante. Me gusta la idea de distribuir todo y luego usar una clave de licencia para habilitar y deshabilitar ciertas funciones. Tiene una preocupación válida acerca de que es mucho trabajo revisar el código y continuar verificando si el usuario tiene licencia para una determinada función. Suena como si estuvieras trabajando en Java, así que lo que yo sugeriría es que estudies el uso de un tejedor de aspecto para insertar el código para verificar la licencia en tiempo de compilación. Todavía hay un objeto al que van todas las llamadas para verificar la licencia, pero no es tan malo si estás usando un aspecto, diría que es una buena práctica.

En su mayor parte, solo necesita leer si algo tiene licencia y tendrá una pequeña cantidad de componentes para que la tabla pueda mantenerse en la memoria en todo momento y, dado que solo se lee, no debería tenerla también. muchos problemas con el enhebrado.

Como alternativa, puede distribuir varios tarros, uno para cada componente con licencia y que solo permitan cargar las clases que tienen licencia. Tendría que vincularse con el cargador de clases para lograr esto.

2

¿Quieres hacerlo a través de la subversión? Usaría Subversion para mantener diferentes versiones de (una rama por versión, por ejemplo, v1.0, v2.0, etc.), pero me gustaría construir diferentes ediciones (trial/pro, etc.) desde el misma base de código.

De esta forma simplemente habilita o deshabilita varias funciones a través de una compilación y no tiene que preocuparse por sincronizar las diferentes ramas. Si usa Subversion para administrar versiones diferentes y versiones diferentes, puedo ver una explosión de ramas/etiquetas en el futuro cercano.

Para la conmutación, puede simplemente mantener una base de código de check-out, y usar svn switch para pagar las diferentes versiones. Es mucho menos lento que realizar nuevas cajas para cada interruptor.

+0

No recomendaría usar 'cambiar' porque puede fallar a la mitad (por ejemplo, cuando los archivos no versionados están obstruyendo los versionados) dejándolo con copias de trabajo parcialmente conmutadas. Tener un pago por cada sucursal reducirá la confusión. –

1

Usted está son para saltar sobre la ramificación y fusión de la compra tan rápido. Es un PITA.

La única razón por la que me gustaría ramificar un repositorio de subversión es si deseo compartir mi código con otro desarrollador. Por ejemplo, si trabaja en una función a la vez y todavía no la ha realizado, debe usar una rama para comunicarse. De lo contrario, me quedaría en el maletero tanto como sea posible.

En segundo lugar, la recomendación de Brian para diferenciar los lanzamientos en la compilación y no en la base de código.

Cuestiones relacionadas