2009-05-29 14 views
11

Supongamos que tengo un proyecto "MyFramework" que tiene algún código, que se utiliza en bastantes soluciones. Cada solución tiene su propia gestión de control de fuente (SVN).¿Cuál es la mejor práctica para compartir un proyecto de Visual Studio (ensamblaje) entre las soluciones

MyFramework es un producto interno y no tiene un calendario de lanzamiento formal, y lo mismo ocurre con las soluciones.

Preferiría no tener que compilar y copiar los archivos DLL a los 12 proyectos, es decir, los nuevos desarrolladores deberían poder hacer un svn-checkout y ponerse a trabajar.

¿Cuál es la mejor manera de compartir MyFramework en todas estas soluciones?

Respuesta

7

Como menciona SVN, puede usar externals para "importar" el proyecto de marco en la copia de trabajo de cada solución que lo use.Esto llevaría a un diseño de la siguiente manera:

C:\Projects 
    MyFramework 
    MyFramework.csproj 
    <MyFramework files> 

    SolutionA 
    SolutionA.sln 
    ProjectA1 
     <ProjectA1 files> 
    MyFramework <-- this is a svn:externals definition to "import" MyFramework 
     MyFramework.csproj 
     <MyFramework files> 

Con esta solución, usted tiene el código fuente de MyFramework disponibles en cada solución que lo utiliza. La ventaja es que puede cambiar el código fuente de MyFramework desde cada una de estas soluciones (sin tener que cambiar a un proyecto diferente).

PERO: al mismo tiempo, esto también es una gran desventaja, ya que hace que sea muy fácil de romper MyFramwork para algunas soluciones cuando modifiying por otro.

Por esta razón, me han caído recientemente que el enfoque y ahora estoy tratando a nuestros proyectos marco como una solución/producto totalmente independiente (con su propia liberación horario). Todas las demás soluciones incluyen una versión específica de los binarios de los proyectos marco.

Esto asegura que un cambio realizado en las bibliotecas marco no se rompe cualquier solución que se reutiliza una biblioteca. Para cada solución, ahora puedo decidir cuándo quiero actualizar a una versión más nueva de las bibliotecas de framework.

+0

Me gusta este enfoque, tendré que leer más acerca de los externos. Supongo que puede cambiar todo y comprometerse con el repositorio correcto cuando haya terminado. El marco es muy joven (recientemente nos dimos cuenta de que estábamos escribiendo el mismo código por todas partes) por lo que poder hacer cambios rápidos es uno de los primeros en la lista de prioridades. También es importante asegurarse de que esos cambios no rompan todo lo demás. –

4

Eso suena como un desastre ... ¿cómo hacer frente con los desarrolladores de deshacer/romper el trabajo de los demás ...

Si yo fuera usted, me gustaría poner MyFrameWork en una solución completamente independiente. Cuando un desarrollador desea desarrollar uno de los 12 proyectos, abre la solución del proyecto en un IDE. & abre MyFrameWork en un IDE independiente.

Si llama fuerte a su ensamblado MyFramework & GAC y hace referencia a él en sus otros proyectos, entonces el "Copiar archivos DLL" no será un problema.

Acaba de compilar MyFrameWork (y un evento PostBuild puede ejecutar GacUtil para ponerlo en el caché de asssembly) y luego crear su otro proyecto.

+0

que sin duda es una consideración, pero tenemos CI en todos los proyectos por lo que al menos lo encontraríamos pronto. En cuanto al GAC, me gustaría evitar el GAC si es posible. –

1

Estoy de acuerdo con otro póster, eso suena como un problema. Pero si no puede querer hacerlo de la "manera correcta" puedo pensar en otras dos formas de hacerlo. Usamos algo similar al número 1 a continuación. (Para C++ aplicación nativa)

  1. un archivo de script o por lotes u otro proceso que se ejecuta que hace un get y una acumulación de la dependencia. (solo una vez) Esto se crea/ejecuta solo si no hay cambios en el repositorio. Deberá saber qué etiqueta/rama/versión desea obtener. Puede usar un archivo bat como un paso previo a la compilación en sus archivos de proyecto.

  2. Guarde los binarios en el repositorio (no es una buena idea). Incluso en este caso, los proyectos dependientes tienen que hacer un get y deben saber qué versión obtener.

Finalmente, lo que tratamos de hacer para nuestro (s) proyecto (s) fue imitar la forma en que usamos y nos referimos a bibliotecas de terceros.

Lo que puede hacer es crear un paquete de lanzamiento para la dependencia que configura una variable de entorno de ruta para sí misma. Permitiría que existieran varias versiones de él en la máquina y luego las versiones específicas de enlace/referencia de proyectos dependientes.

Algo así como

$(PROJ_A_ROOT) = c:\mystuff\libraryA 

$(PROJ_A_VER_X) = %PROJ_A_ROOT%\VER_X 

y después hacer referencia a la versión que desea en las soluciones dependientes, ya sea por su nombre específico, o usando la versión env var.

No es bonito, pero funciona.

2

La "mejor manera" dependerá de su entorno. Trabajé en un entorno de integración continua basado en TFS, donde la compilación nocturna implementó los binarios en un recurso compartido. Todos los proyectos dependientes referidos a la acción. Cuando esto se volvió lento, construí algunas herramientas para permitir que los desarrolladores tengan una copia local de los binarios compartidos, sin cambiar los archivos del proyecto.

2

¿Funciona regularmente el trabajo en cualquiera de las 12 soluciones con cambios en el código "framework"?

Si por lo que su marco es probablemente nuevo y acaba de ser creado, por lo que acababa de incluir el proyecto de la estructura en todas las soluciones. Después de todo, si el trabajo exige que tenga que cambiar el código de la estructura, debería ser fácil hacerlo.

Dado que los cambios en el marco de trabajo de una solución afectarán a todas las otras soluciones, se producirán descansos, y deberá lidiar con ellos.

Una vez que rara vez tiene que cambiar el marco mientras trabaja en las soluciones (este debería ser su objetivo) entonces incluiría una referencia a un dll framework y actualizaría el dll en cada solución solo según sea necesario.

2

svn:externals se encargará de esto muy bien si usted sigue algunas reglas.

En primer lugar, es más seguro si utiliza URI relativas (comenzando con un carácter ^) para las definiciones de svn: externals y si es posible, coloque los proyectos en el mismo repositorio. De esta forma, las definiciones seguirán siendo válidas incluso si el servidor de subversión se mueve a una nueva URL.

En segundo lugar, asegúrese de seguir la siguiente pista del libro de SVN. Utilice PEG-rango de velocidad en su SVN: definiciones externas para evitar la rotura aleatoria y etiquetas inestables:

Usted debería considerar seriamente el uso de números de revisión explícitos en todas sus definiciones externas . Si lo hace, significa que puede decidir cuándo desplegar una instantánea diferente de información externa y exactamente qué instantánea extraer.Además evitar la sorpresa de conseguir cambios en los repositorios de terceros que puede que no tenga ningún control más, utilizar números de revisión explícitos también significa que cuando retroceda su copia de trabajo a una revisión anterior, sus definiciones externas también revertir al aspecto que tenían en ese revisión anterior ...

+0

Otras respuestas mencionan que el uso de svn: externals podría romper fácilmente otras soluciones. Quiero señalar (una vez más) que el uso de números de revisión explícitos puede eliminar este problema. El uso de una revisión específica debería llevar al mismo resultado que copiar un binario específico en la solución, además de que se obtiene una depuración más fácil y no se copian los binarios.Me podría imaginar el uso de la versión actual de MyFramework en el maletero de todas las soluciones y cuando creo un RC para una solución, fijaré el externo a una revolución específica de MyFramework. – Tom

1

Una solución escalable es hacer svn-external en el directorio solución para que sus proyectos importados aparecen en paralelo a su otro proyecto s. Las razones para esto se dan a continuación.

Uso de un subdirectorio separado para proyectos "importados", p. externals, a través de svn-external parece una buena idea hasta que tenga dependencias no triviales entre proyectos. Por ejemplo, supongamos que un proyecto depende de proyecto en proyecto B y B proyecto en proyecto C. Si usted entonces tiene una solución de S con el proyecto A, que va a terminar con la siguiente estructura de directorios:

# BAD SOLUTION # 
S 
+---S.sln 
+---A 
| \---A.csproj 
\---externals 
    +---B  <--- A's dependency 
    | \---B.csproj 
    \---externals 
     \---C  <--- B's dependency 
      \---C.csproj 

Usando esta técnica, , incluso puede terminar teniendo múltiples copias de un solo proyecto en su árbol. Esto claramente no es lo que quieres.

Además, si sus proyectos usan dependencias NuGet, normalmente se cargan dentro del directorio de nivel superior packages. Esto significa que referencias NuGet de proyectos dentro del subdirectorio externals se romperán.

Además, si se utiliza Git además de SVN, un método recomendado para el seguimiento de cambios es tener un repositorio Git separado para cada proyecto, y luego un repositorio Git separado para la solución que utiliza git submodule de los proyectos dentro. Si un submódulo Git no es un subdirectorio inmediato del módulo principal, entonces el comando del submódulo Git creará un clon que es un subdirectorio inmediato.

Otra ventaja de tener todos los proyectos en la misma capa es que puedes crear una "super-solución" que contenga proyectos de todas tus soluciones (rastreado a través de Git o svn-external), que a su vez te permite a compruebe con una sola solución: reconstruya que cualquier cambio que haya realizado en un solo proyecto sea coherente con todos los demás proyectos.

# GOOD SOLUTION # 
S 
+---S.sln 
+---A 
| \---A.csproj 
+---B  <--- A's dependency 
| \---B.csproj 
\---C  <--- B's dependency 
    \---C.csproj 
Cuestiones relacionadas