svn - tag - tortoise merge
¿La subversión es externa a antipattern? (7)
Decir que a es b no hace a a a a menos que digas por qué es así.
La falla principal que veo con las referencias externas en subversión es que no se garantiza que el repositorio esté presente cuando actualiza su copia de trabajo.
Las referencias externas de Subversion se pueden usar y abusar, y la característica en sí misma no es más que eso, una característica . No se puede decir que sea un patrón , ni un antipatrón .
He leído la respuesta de la persona que citas, y debo decir que no estoy de acuerdo. Si su proyecto requiere archivos de la versión XYZ de un repositorio, una referencia de subversión externa puede proporcionarle fácilmente eso.
Sí, puede usarlo incorrectamente al no especificar específicamente qué versión de esa referencia necesita. ¿Eso te dará problemas? ¡Probable!
¿Es un antipatrón? Bueno, eso depende. Si sigues el enlace proporcionado por el autor del texto que citas, es decir. antipattern , entonces no. Que algo se pueda usar para proporcionar una mala solución no hace que todo el método de hacerlo sea un antipatrón . Si esa fuera la regla, entonces diría que los lenguajes de programación en general son antipatrones, porque en todos los lenguajes de programación puede hacer malas soluciones .
Subversion le permite incrustar copias de trabajo de otros repositorios utilizando externals , lo que permite un fácil control de versiones de software de biblioteca de terceros en su proyecto.
Si bien estos parecen ideales para la reutilización de bibliotecas y el control de versiones del software del proveedor , no dejan de tener sus críticas :
No utilice Subversion externos (o similares en otras herramientas), son un antipatrón y, por lo tanto, innecesarios
¿Hay riesgos ocultos en el uso de elementos externos? Por favor explique por qué serían considerados antipatrón.
El principal riesgo con el uso de svn: externals es que el repositorio al que se hace referencia se cambiará de una manera que rompe el código o introduce una vulnerabilidad de seguridad. Si el repositorio externo también está bajo su control, entonces esto puede ser aceptable.
Personalmente, solo uso svn: externals para apuntar a las ramas "estables" de un repositorio que poseo.
Existen fallas definitivas en las externalidades de subversión, pero parece que las utilizamos de forma razonablemente exitosa para incluir bibliotecas (tanto propias como de proveedores) de las que depende el proyecto actual. Entonces no los veo como un "antipatrón". Los puntos de uso importantes para mí son:
- Señalan una revisión o etiqueta específica (nunca la cabeza) del otro proyecto.
- Se insertan en el proyecto actual lejos de su propio código fuente, etc. (por ejemplo, en un subdirectorio llamado "archivos de soporte").
- Se refieren únicamente a los otros archivos de "interfaz" de proyectos (por ejemplo, carpeta de inclusión) y bibliotecas binarias (es decir, no obtenemos la fuente completa del otro proyecto).
A mí también me interesarían los principales riesgos de este acuerdo y mejores enfoques.
No creo que esto sea un antipatrón en absoluto. Hice algunas búsquedas rápidas en Google y básicamente no obtuve nada ... nadie se queja de que usar svn: externals sea malo o dañino. Por supuesto, hay algunas advertencias que debes tener en cuenta ... y no es algo que debas espolvorear en todos tus repositorios ... pero en cuanto a la cita original, esa es solo su opinión personal (y subjetiva) . Él nunca discutió realmente sobre svn: externals, excepto para condenarlos como un antipatrón. Tales afirmaciones radicales sin ningún tipo de apoyo o al menos con un razonamiento sobre cómo la persona llegó a hacer la declaración siempre son sospechosas.
Dicho esto, hay algunos problemas con el uso de elementos externos. Al igual que Mike respondió, pueden ser muy útiles para señalar las ramas estables del software lanzado ... especialmente el software que ya controlas. Los usamos internamente en una serie de proyectos para bibliotecas de servicios públicos y demás. Tenemos un pequeño grupo que mejora y trabaja en la base de bibliotecas de servicios públicos, pero ese código base se comparte en una serie de proyectos. No queremos que varios equipos solo verifiquen el código del proyecto de utilidad y no queremos tratar con un millón de sucursales, por lo que para nosotros svn: external funciona muy bien. Para algunas personas, pueden no ser la respuesta. Sin embargo, estoy totalmente en desacuerdo con la afirmación "Por favor no use ..." y que estas herramientas representan un antipatrón.
Si simple externo es un antipatrón porque puede romper su repositorio, entonces uno con revisión explícita no debe.
Extracto del libro svn :
Una definición externa es un mapeo de un directorio local a la URL ** - y posiblemente una revisión particular - ** de un recurso versionado.
Creo que todo depende de tu propósito de usar la función, no es un antipatrón en sí mismo.
Soy el autor de la cita en la pregunta, que proviene de una respuesta anterior .
Jason tiene razón al desconfiar de declaraciones breves como la mía y pedir una explicación. Por supuesto, si explicara completamente todo en esa respuesta, necesitaría haber escrito un libro.
Mike también tiene razón al señalar que uno de los problemas con una característica de tipo svn:external
es que los cambios en la fuente de destino podrían romper su propia fuente, especialmente si esa fuente de destino está en un repositorio que no es de su propiedad.
Al explicar más mi comentario, permítanme primero decir que hay formas "seguras" de usar la característica svn:external
-like, al igual que con cualquier otra herramienta o característica. Sin embargo, me refiero a él como antipattern porque es mucho más probable que se abuse de esta característica. En mi experiencia, siempre se ha usado mal, y es muy poco probable que alguna vez lo use de esa manera segura ni recomiende ese uso. Tenga en cuenta que no me refiero al menosprecio al equipo de Subversion. Me encanta Subversion, aunque tengo la intención de pasar a Bazar.
El principal problema con esta característica es que fomenta y se utiliza normalmente para vincular directamente el origen de una compilación ("proyecto") a la fuente de otra, o para vincular el proyecto a un archivo binario (DLL, JAR, etc.) De lo que depende Ninguno de estos usos es sabio, y constituyen un antipatrón.
Como dije en mi otra respuesta, creo que un principio esencial para las compilaciones de software es que cada proyecto construye exactamente UN entregas binarias o primarias. Esto puede considerarse una aplicación del principio de separación de preocupaciones al proceso de construcción. Esto es particularmente cierto con respecto a un proyecto que hace referencia directamente a la fuente de otro, lo que también es una violación del principio de encapsulation . Otra forma de este tipo de infracción es intentar crear una jerarquía de compilación para construir un sistema o subsistema completo mediante la invocación recursiva de subconstrucciones. Maven recomienda encarecidamente / impone este comportamiento, que es una de las muchas razones por las que no lo recomiendo.
Finalmente, descubro que hay varias cuestiones prácticas que hacen que esta característica sea indeseable. Por un lado, svn:external
tiene algunas características de comportamiento interesantes (pero los detalles se me escapan por el momento). Por otro lado, siempre encuentro que necesito tales dependencias para ser explícitamente visibles para mi proyecto (proceso de compilación), no oculto como algunos metadatos de control de origen.
Entonces, ¿cuál es una manera "segura" de usar esta característica? Lo consideraría así cuando lo usa temporalmente una sola persona, como una forma de "configurar" un entorno de trabajo. Pude ver dónde un programador podría crear su propia carpeta en el repositorio (o uno para cada programador) donde configuraría svn:external
enlaces svn:external
a las otras partes del repositorio en las que están trabajando actualmente. Luego, el pago de esa única carpeta creará una copia de trabajo de todos sus proyectos actuales. Cuando se agrega o finaliza un proyecto, las definiciones de svn:external
se pueden ajustar y la copia de trabajo se puede actualizar adecuadamente. Sin embargo, prefiero un enfoque que no esté vinculado a un sistema de control de fuente en particular, como hacer esto con un script que invoca los checkouts.
Para el registro, mi exposición más reciente a este problema ocurrió durante el verano de 2008 en un cliente de consultoría que estaba usando svn:external
en una escala masiva: TODO fue cruzado para producir una única copia de trabajo maestra. Sus scripts de construcción basados en Ant & Jython (para WebLogic) se construyeron sobre esta copia maestra de trabajo. El resultado neto: NADA podría construirse de forma independiente, había literalmente docenas de subproyectos, pero ninguno era seguro para pagar / trabajar por sí mismo. Por lo tanto, cualquier trabajo en este sistema primero requirió una verificación / actualización de más de 2 GB de archivos (también colocaron binarios en el repositorio). Hacer cualquier cosa fue un ejercicio inútil, y me fui después de intentar durante tres meses (también había muchos otros antipatritos presentes).
EDITAR: Explicar en compilaciones recursivas -
A lo largo de los años (especialmente en la última década), he construido sistemas masivos para compañías de Fortune 500 y grandes agencias gubernamentales que involucran muchas docenas de subproyectos dispuestos en jerarquías de directorios que tienen muchos niveles de profundidad. He utilizado proyectos / soluciones de Microsoft Visual Studio para organizar sistemas basados en .NET, Ant o Maven 2 para sistemas basados en Java, y he comenzado a usar distutils y setuptools (easyinstall) para sistemas basados en Python. Estos sistemas también han incluido enormes bases de datos típicamente en Oracle o Microsoft SQL Server.
He tenido un gran éxito diseñando estas construcciones masivas para facilitar el uso y la repetibilidad. Mi estándar de diseño es que un nuevo desarrollador puede aparecer en su primer día, recibir una nueva estación de trabajo (tal vez directamente de Dell con solo una instalación típica de sistema operativo), recibir un documento de configuración simple (generalmente solo una página de instrucciones de instalación). y poder configurar completamente la estación de trabajo y construir el sistema completo desde la fuente, sin supervisión, sin asistencia, y en medio día o menos. Invocar la compilación en sí implica abrir un shell de comando, cambiar al directorio raíz del árbol de origen y emitir un comando de una línea para compilar TODO.
A pesar de ese éxito, la construcción de un sistema de construcción tan masiva requiere gran cuidado y una estrecha adhesión a los principios de diseño sólido, al igual que con la construcción de una aplicación / sistema masivo y crítico para el negocio. He descubierto que una parte crucial es que cada proyecto (que produce un artefacto / entregable único) debe tener un solo script de compilación, que debe tener una interfaz bien definida (comandos para invocar porciones del proceso de compilación), y debe mantenerse. solo de todos los otros (sub) proyectos. Históricamente, es fácil construir todo el sistema, pero es difícil / imposible construir solo una pieza. Recientemente, he aprendido a asegurarme cuidadosamente de que cada proyecto realmente se desarrolle solo.
En la práctica, esto significa que debe haber al menos dos capas de scripts de compilación. La capa más baja son los scripts de compilación del proyecto que producen cada producto / artefacto. Cada script reside en el directorio raíz de su árbol fuente del proyecto (de hecho, este script define su árbol fuente del proyecto), estos scripts no saben nada sobre el control fuente, esperan ejecutarse desde la línea de comando, hacen referencia a todo en el proyecto relativo al script de compilación, y hacen referencia a sus dependencias externas (herramientas o artefactos binarios, no a otros proyectos de origen) en función de algunas configuraciones configurables (variables de entorno, archivos de configuración, etc.).
La segunda capa de scripts de compilación también se debe invocar desde la línea de comandos, pero estos saben sobre el control de origen. De hecho, esta segunda capa es a menudo un único script que se invoca con un nombre de proyecto y una versión, luego verifica el origen del proyecto nombrado en un nuevo directorio temporal (tal vez especificado en la línea de comandos) e invoca su script de compilación.
Puede ser necesario que haya más variaciones para acomodar servidores de integración continua, plataformas múltiples y varios escenarios de lanzamiento.
En ocasiones se necesita una tercera capa de scripts que invoca la segunda capa de scripts (que invoca la primera capa) con el fin de crear subconjuntos específicos del conjunto de proyectos general. Por ejemplo, cada desarrollador puede tener su propia secuencia de comandos que crea los proyectos en los que están trabajando hoy. Puede haber un script para compilar todo con el fin de generar la documentación maestra o calcular métricas.
A pesar de todo, he descubierto que intentar tratar el sistema como una jerarquía de proyectos es contraproducente. Vincula los proyectos entre sí para que no se puedan compilar libremente solos o en ubicaciones arbitrarias (directorio temporal en el servidor de integración continua) o en un orden arbitrario (suponiendo que se satisfacen las dependencias). A menudo, intentar forzar una jerarquía rompe cualquier integración IDE que se pueda intentar.
Finalmente, construir una jerarquía masiva de proyectos puede ser simplemente demasiado intensivo en el desempeño. Por ejemplo, durante la primavera de 2007, intenté una jerarquía de fuentes modesta (Java más Oracle) que construí utilizando Ant, que finalmente falló porque la compilación siempre abortaba con una excepción OutOfMemoryException de Java. Esto fue en una estación de trabajo RAM de 2 GB con un espacio de intercambio de 3,5 GB para el cual había sintonizado la JVM para poder usar toda la memoria disponible. La aplicación / sistema era relativamente trivial en términos de cantidad de código, pero las invocaciones recursivas de construcción eventualmente agotaron la memoria, sin importar la cantidad de memoria que le di. Por supuesto, también llevó una eternidad ejecutar también (30-60 minutos era común, antes de abortar). Sé cómo sintonizar MUY bien, pero al final simplemente estaba excediendo los límites de las herramientas (Java / Ant en este caso).
Así que hazte un favor, construye tu construcción como proyectos independientes, luego compáralos en un sistema completo. Mantenlo ligero y flexible. Disfrutar.
EDITAR: Más sobre antipatterns
Estrictamente hablando, un antipatrón es una solución común que parece que resuelve el problema pero no lo hace, ya sea porque deja brechas importantes o porque presenta problemas adicionales (a menudo peores que el problema original). Una solución implica necesariamente una o más herramientas más la técnica para aplicarlas al problema en cuestión. Por lo tanto, es difícil referirse a una herramienta o una característica específica de una herramienta como un antipatrón, y parece que las personas están detectando y reaccionando a ese estiramiento, es suficiente.
Por otro lado, dado que parece ser una práctica común en nuestra industria centrarse en las herramientas en lugar de en la técnica, es la herramienta / característica la que llama la atención (una encuesta informal de preguntas aquí en parece ilustrar fácilmente). Mis comentarios y esta pregunta en sí reflejan esa práctica.
Sin embargo, a veces parece particularmente justificado hacer ese estiramiento, como en este caso. Algunas herramientas parecen "guiar" al usuario a técnicas particulares para aplicarlas, hasta el punto en que algunos argumentan que las herramientas moldean el pensamiento (ligeramente reformulado). Es principalmente en ese espíritu que sugiero que svn:external
es un antipattern.
Para establecer el problema de manera más estricta, el antipatrón es diseñar una solución de compilación que incluya vincular proyectos en el nivel fuente, o versionar implícitamente las dependencias entre proyectos, o permitir que dichas dependencias cambien implícitamente, porque cada uno de ellos invoca condiciones muy negativas. Consecuencias. La naturaleza de la característica svn:external
hace que evitar esas consecuencias negativas sea muy difícil.
El manejo adecuado de las dependencias entre los proyectos implica abordar esas dinámicas junto con el problema de base, y las herramientas y técnicas conducen por un camino diferente. Un ejemplo que se debe considerar es Ivy , que ayuda de una manera similar a Maven, pero sin los muchos inconvenientes. Estoy investigando a Ivy, junto con Ant, como mi solución a corto plazo para el problema de compilación de Java. A largo plazo, estoy buscando incorporar los conceptos centrales y las características en una herramienta de código abierto que facilita una solución multiplataforma.
Un hilo viejo, pero quiero abordar la preocupación de que un cambio externo podría romper tu código. Como se señaló anteriormente, esto se debe a un uso incorrecto de la propiedad externa. Las referencias externas deberían, en casi todas las instancias, apuntar a un número de revisión específico en el URI del repositorio externo. Esto asegura que el externo nunca cambiará a menos que lo cambie para apuntar a un número de revisión diferente.
Para algunas de nuestras bibliotecas internas, que utilizamos como elementos externos en nuestros proyectos de usuario final, he encontrado que es útil crear una etiqueta de la biblioteca en la versión Major.Minor, donde no aplicamos cambios de última hora. Con un esquema de control de versiones de cuatro puntos (Major.Minor.BugFix.Build), permitimos que la etiqueta se mantenga actualizada con los cambios de BugFix.Build (una vez más, no se aplican cambios de interrupción). Esto nos permite usar una referencia externa a la etiqueta sin un número de revisión. En el caso de cambios importantes o de otro tipo, se crea una nueva etiqueta.
Los externos en sí no son malos, pero eso no impide que las personas creen malas implementaciones de ellos. No se necesita mucha investigación, solo un poco de lectura a través de algunos documentos, para aprender cómo usarlos de manera segura y efectiva.