¿Cómo debo organizar mi árbol fuente?

89

Soy un desarrollador individual que trabaja, en gran medida, en proyectos web (W / LAMP) y, a veces, en proyectos C / C ++ (no GUI) de escala media.

A menudo me cuesta estructurar mi árbol de código fuente. De hecho, por lo general, no completo un proyecto sin tirar todo el árbol y reorganizar las piezas tres o cuatro veces, lo que realmente requiere mucho esfuerzo y, además, el resultado final parece un compromiso.

A veces, termino con una clasificación excesiva de la fuente: un árbol muy largo de carpetas y subcarpetas. En otras ocasiones, simplemente termino concentrando todos los archivos en una carpeta particular en función del propósito más amplio que sirven y, por lo tanto, conducen a carpetas 'caóticas' en la fuente.

Me gustaría preguntar:

  • ¿Hay algún principio / lógica / mejores prácticas que me puedan ayudar a estructurar mi árbol fuente?
  • ¿Existen técnicas gráficas / esquemáticas (por ejemplo: DFD en caso de flujo de datos) que puedan ayudarme a visualizar mi árbol fuente de antemano basado en el análisis del proyecto?
  • ¿Qué estrategia adoptar para estructurar el árbol de archivos multimedia asociado con el proyecto?

Acerca de la recompensa : aprecio las respuestas existentes con los miembros que comparten sus propias prácticas, sin embargo, me gustaría alentar respuestas (o recursos) más generales e instructivas y más respuestas de los miembros.

check123
fuente
8
No tengo tiempo para un ensayo en este momento, pero "nombra las cosas como son", "coloca las cosas donde pertenecen", "mantén las cosas similares cerca una de la otra" y, finalmente, "no te preocupes por eso" , es de esperar que tenga un IDE que lo ayude a navegar rápidamente entre fragmentos de código ".
John Saunders
@John, no soy tan bueno con IDE (s), generalmente saco un Notepad ++ o vi dependiendo del sistema operativo. Eso hace las cosas un poco más difíciles. El resto de los puntos son útiles, pero de nuevo se reduce a tomar decisiones difíciles como las funciones de registro (registros de error, etc.) más cercanas a la lógica de la aplicación o DAL o la gestión de la memoria caché o los administradores de vista. Los errores tienen casi la misma probabilidad de ocurrir en cualquiera de ellos.
check123
3
Tal vez una vez que llegue al punto de tener este tipo de preguntas, es hora de dejar que algunas herramientas hagan parte del trabajo por usted. Y el registro es claramente una preocupación interfuncional, utilizada por todas las partes de la aplicación (si está utilizando el tipo de código que necesita registro). Otro pequeño dicho es, "coloque el código sobre el código que lo usa", por lo que el registro debe estar cerca de la parte superior, tal vez en \ utilities.
John Saunders
@John: Muy apreciado. Tal vez debería comenzar a buscar un IDE. Eclipse parece prometedor.
check123
1
@ check123 "... reorganizando las piezas tres o cuatro veces ..." Práctica común: "La pregunta de gestión, por lo tanto, no es si construir un sistema piloto y tirarlo. Harás eso. La única pregunta es si se debe planificar con antelación para construir una de usar y tirar, o para prometen entregar el usar y tirar a los clientes “- Frederick P. Brooks Jr., el mes laboral mítico:. Ensayos sobre Ingeniería de Software
shawnhcorey

Respuestas:

25

El diseño del árbol de origen debe reflejar la arquitectura; Como corolario, una arquitectura bien estructurada puede conducir a un diseño de árbol fuente bien estructurado. Sugiero leer sobre el patrón de capas POSA1 , intentar ajustar su arquitectura en una estructura en capas, luego nombrar cada una de las capas resultantes y usar eso como base para su jerarquía de origen. Tomando una arquitectura común de tres niveles como línea de base:

  • presentation / webService (presentar una interfaz de servicio web a nuestra lógica de negocios)
  • logic / * (los módulos de lógica de negocios entran aquí)
  • almacenamiento / sql (API de almacenamiento de fondo aquí; esto utiliza una interfaz SQL para almacenar en una base de datos)
  • util / * (código de utilidad - utilizable por todas las otras capas, pero eso no se refiere a util externo, va aquí)

Tenga en cuenta que las capas no contienen código directamente, sino que se usan estrictamente para organizar módulos.

Dentro de un módulo, uso el siguiente tipo de diseño:

  • <module> (ruta al módulo directamente; define la interfaz modular)
  • <module>/impl/<implName> (una implementación específica de la interfaz modular)
  • <module>/doc (Documentación para usar el módulo)
  • <module>/tb (código de prueba de unidad para el módulo)

donde <module>se encuentra en el repositorio de acuerdo con la capa a la que pertenece.

Aidan Cully
fuente
55
+1: el diseño del árbol de origen debe reflejar la arquitectura, algo obvio que estaba pasando por alto.
check123
¿Cómo gestiona los archivos seguros, archivos a los que solo los usuarios autorizados pueden acceder después del inicio de sesión?
check123
@ check123 No estoy seguro de entender la pregunta. Me concentré en la organización de los módulos fuente, en lugar de respaldar los archivos para el proyecto, y el código fuente generalmente está destinado a ser accesible para todos. (Hay excepciones, y uso un directorio dist / sobre todo código con restricciones de uso / modificación no estándar.)
Aidan Cully
48

Realmente no puedo darle muchos consejos relacionados con los proyectos web, pero así es como estructuro mi árbol en un proyecto de programación (principalmente desde una perspectiva C / C ++):

  • / /
    • src: archivos de origen escritos por mí mismo
    • ext - Contiene bibliotecas de terceros
      • libname-1.2.8
        • incluir - Encabezados
        • lib - Archivos compilados de lib
        • Donwload.txt: contiene un enlace para descargar la versión utilizada
    • ide : aquí almaceno los archivos del proyecto
      • vc10 : organizo los archivos de proyecto según el IDE
    • bin - Exe compilado va aquí
    • build : los archivos de compilación del compilador
    • doc - Documentación de cualquier tipo
    • LÉAME
    • INSTALAR EN PC
    • PROCESO DE COPIAR

Algunas notas

  1. Si estoy escribiendo una biblioteca (y estoy usando C / C ++), primero voy a organizar mis archivos de origen en dos carpetas llamadas "incluir" y "src" y luego por módulo. Si se trata de una aplicación, los organizaré solo por módulo (los encabezados y las fuentes irán en la misma carpeta).

  2. Los archivos y directorios que enumeré anteriormente en cursiva no los agregaré al repositorio de código.

Pablo
fuente
¿Cuál es la diferencia entre ide y build ?
M. Dudley
3
idees justo donde guardo los archivos del proyecto ellos mismos. buildcontiene los archivos de objetos generados por el compilador. Diferentes IDEs pueden usar el mismo compilador, por eso mantengo los archivos del proyecto IDE separados de los archivos de objetos creados por el compilador.
Paul
entonces build == obj (el término utilizado por muchos otros sistemas)
gbjbaanb
@gbjbaanb Sí, supongo. Realmente no importa, ya que ese directorio no se envía al repositorio. :) Lo llamé 'construir' porque así lo llamaba el IDE que estaba usando att (Visual Studio).
Paul
¿Qué pasa si su exe necesita algo de dll para ejecutarse? ¿Copia todos los archivos dll al mismo directorio que exe? ¿Utiliza algunos eventos posteriores a la compilación?
Wakan Tanka
14

Si bien el diseño de directorio estándar de Maven es específico para Java, pero también puede servir como una buena base para otros tipos de proyectos.

Aquí está la estructura básica (puede reemplazar los directorios 'java' con 'php', 'cpp', etc.):

src/main/java       Application/Library sources 
src/main/resources  Application/Library resources  
src/main/filters    Resource filter files 
src/main/assembly   Assembly descriptors 
src/main/config     Configuration files 
src/main/webapp     Web application sources 
src/test/java       Test sources 
src/test/resources  Test resources 
src/test/filters    Test resource filter files 
src/site            Site 
LICENSE.txt         Project's license 
NOTICE.txt          Notices and attributions required by libraries
README.txt          Project's readme

La estructura básicamente se descompone en 'src / main' y 'src / test' y luego se agrupa por tipo.

Michal Miller
fuente
5

Realmente no sé acerca de las convenciones, pero todos mis proyectos principales se realizan utilizando Symfony Framework y me he acostumbrado a una estructura de árbol como la siguiente:

raíz/

  • aplicaciones
  • nombre de la aplicación
    • config (archivos de configuración específicos de la aplicación)
    • lib (archivos php específicos de la aplicación)
    • módulos (distribución modular de funcionalidad)
      • Nombre del módulo
        • plantillas (html)
        • acciones (código php)
  • confing (archivos de configuración del proyecto)
  • lib (código php que podría usarse en un proyecto de agujero)
  • modelo (clases que representan la información del proyecto)
    • base
  • formulario (archivos php que manejan formularios, esto podría ser bastante difícil de lograr sin Symfony)
    • base (clases de formulario base)
  • web
  • css
    • imágenes
    • file.css
  • js
  • log (archivos de registro que podrían generarse)
  • datos (información específica de datos, como parches sql, o lo que sea)
  • sql
  • plugins (bibliotecas utilizadas que podrían fusionarse con cualquier aplicación del proyecto)

Si está interesado, lea la documentación de Symfony sobre el asunto para obtener más información ( MVC y Code Organization on Symfony ).

Guiman
fuente
¿Está centralizada su carpeta CSS? ¿Quiero decir que todos tus CSS (en todo el proyecto) están en el mismo directorio?
check123
No necesariamente, podría dividirlo, pero como la mayoría de mis proyectos tienden a tener solo 2 aplicaciones (frontend y backend), no hay tantos archivos css (los complementos siempre tienen su propia carpeta web para la abstracción)
guiman
5

Idealmente, la organización tiene un repositorio único, cuya estructura está destinada a aumentar el compromiso entre ingeniería y negocios y promover la reutilización.

...\products\
...\products\productName\
...\products\productName\doc\

...\systems\
...\systems\systemName\
...\systems\systemName\doc\
...\systems\systemName\res\
...\systems\systemName\build\
...\systems\systemName\test\

...\library\
...\library\libraryName\
...\library\libraryName\doc\
...\library\libraryName\build\
...\library\libraryName\test\

...\devops\

productos

Una carpeta por producto; ayuda a comunicar cómo el software apoya al negocio.

Idealmente, cada "producto" es poco más que un archivo de configuración que indica qué sistemas invocar y cómo se configurarán. La subcarpeta de documentos podría contener el resumen de nivel superior \ spec y cualquier material promocional, etc.

Al separar los productos y los sistemas, comunicamos el potencial de reutilización al lado del negocio orientado al cliente, y desglosamos los silos por producto. (Esto contrasta con el enfoque de "línea de productos" para el mismo problema)

sistemas

Una carpeta por sistema; ayuda a comunicar las capacidades principales y la oportunidad / valor de los contenidos del repositorio.

  1. Archivos de "gestión de configuración" que especifican entornos de compilación y despliegue.
  2. Configuración de prueba a nivel del sistema (podría ser una cantidad significativa).
  3. Lógica y funcionalidad de nivel superior; La mayor parte del trabajo pesado lo realizan las funciones de la biblioteca.

biblioteca

Componentes reutilizables invocados por varios sistemas. La mayoría de las actividades de desarrollo se organizan en torno a la producción de bibliotecas, en lugar de sistemas, por lo que la reutilización se "integra" en el proceso de desarrollo.

devops

Compilación, integración continua y otras funciones de automatización del desarrollo.

Conclusión

El árbol fuente es una pieza clave de documentación, y da forma al enfoque, la estructura y la psicología de la relación del negocio con su tecnología patentada.

Los controladores para este enfoque se explican con un poco más de profundidad en mi respuesta a esta pregunta: https://softwareengineering.stackexchange.com/questions/43733/who-organizes-your-matlab-code/59637#59637

William Payne
fuente
Nota: Puede ser útil nombrar carpetas de una manera que sea compatible con el tipo de jerarquías de productos discutidas en el manual de ingeniería de sistemas INCOSE.
William Payne
3

Lo que intento hacer para cada proyecto es similar a:

  • src : archivos de origen, una carpeta para cada espacio de nombres / paquete para recuperar fácilmente archivos (incluso archivos de encabezado para C / C ++)
  • ext : para bibliotecas externas / de terceros, es simple agregar externos (como repositorios SVN). En el interior, una carpeta para cada biblioteca (archivos binarios e incluidos)
  • bin : para los archivos binarios creados, podría exportarse rápidamente para su lanzamiento
    • inc : para el archivo de encabezados C / C ++ (copiado por IDE / makefile / etc ...)
  • out : para todos los archivos generados temporalmente (.class, .obj, etc.) y podría ignorarse (por ejemplo, SVN)
  • doc : para cualquier documentación, generalmente generada con Doxygen
  • res : al colocar los recursos aquí, es posible separar los archivos fuente de texto y los recursos binarios utilizados por el programa. Realmente no tengo una jerarquía específica dentro.
    • config - para algunos archivos de configuración
    • dibujable : para algunas imágenes o iconos

Todos los archivos o archivos MAKE de IDE se guardan directamente en la raíz si solo usa uno de ellos.

Ninfomane
fuente
2

Hago algo como esto Funciona bien para un juego multiplataforma que estoy haciendo en mi tiempo libre. Desafortunadamente en el trabajo, las cosas están mucho menos organizadas ...

Output                      <-- Build outputs
Docs
External
   <libname>
      Include
      Lib
Data
<ProjectName>.xcodeproj
<ProjectName>VS2010
Source
Temp                        <-- Intermediate stuff from builds and other tools
Tools
Coronel Panic
fuente
2

Para mis equipos, tratamos de hacer cumplir una estructura estándar en todos los proyectos para que sea fácil encontrar cosas a medida que el equipo cambia de contexto y evitar tener que volver a aprender cada vez. No todos los proyectos necesitan todos los sistemas, así que comenzamos con el conjunto mínimo.

/ Fuente / Componente / Idioma

/ Fuente / Componente / Tercero /

/Requisitos de documentación

/ Documentación / Diseño

/ Pruebas / Automatizado / Unidad

/ Pruebas / Automatizado / ToolName

/ Pruebas / Manual

Esto da como resultado cierta duplicación, especialmente bajo el código y las bibliotecas de terceros, pero al menos nunca olvidamos la respuesta a algo como "¿Qué utiliza el Editor RogueWave?"

Christopher Bibbs
fuente
1
Los componentes de ruta en mayúscula me parecen realmente tontos y sin sentido. ¿Por qué todo en minúsculas? Eso es mucho más fácil de escribir para humanos (aunque las herramientas no les importan, incluidos los administradores de archivos WIMP ), y se lee igualmente bien gracias a los separadores de ruta. Una victoria definitiva para mí.
ulidtko
2

Me gustan las ideas presentadas en esta página www.javapractices.com/topic/TopicAction.do?Id=205 . Básicamente, la recomendación es organizar su proyecto en características (o módulos, componentes). Además de los motivos presentados allí:

  1. Menos carga cognitiva cuando piensa en el alcance del código en el que está trabajando, ya que tiene la garantía de que cualquier código en la función en la que está trabajando es "privado de características".
  2. Hay una sensación adicional de seguridad cuando se garantiza que solo está modificando el código para una característica dada. Por ejemplo, no romperá nada más que la función en la que está trabajando. De nuevo, esto se debe a la "característica privada".
  3. Menos carga cognitiva simple porque hay menos archivos que puede ver para un paquete dado. Estoy seguro de que todos han visto un paquete que contiene más de 15 archivos.

Tenga en cuenta que esto se centra en los paquetes Java (también conocidos como espacios de nombres). Para proyectos grandes, recomiendo, por las mismas razones, dividir el proyecto en múltiples proyectos (como en varios proyectos de Maven) que representa una característica comercial. Para proyectos maven, recomiendo esta lectura .

Hasta ahora, los proyectos en los que estuve / estoy involucrado no siguen estos. Hay muchas razones, pero aquí hay algunas:

  1. El malentendido del modificador de acceso predeterminado de Java (el modificador de acceso más incomprendido según este libro )
  2. "Argumentum ad populum": Cultivo predominante de paquete por capa (probablemente causado por la Razón # 1)

Creo que hay una oportunidad perdida para evitar la complejidad si la organización fuente del proyecto no se toma en serio al comienzo del proyecto, como dijo el arquitecto Alexander:

"Como cualquier diseñador le dirá, son los primeros pasos en un proceso de diseño los que cuentan más. Los primeros trazos, que crean la forma, llevan dentro de ellos el destino del resto". - Christopher Alexander

Dependiendo del tamaño y la complejidad de un proyecto, la oportunidad perdida de reducir costos o ROI puede ser realmente grande. (Estoy interesado en ver un estudio para ver los números exactos de esto)

tercero
fuente
2

Mi recomendación es descargar una variedad de frameworks o motores y ver cómo los grandes equipos de desarrollo manejaron el diseño de sus carpetas.

Hay tantas formas de organizar los archivos que es mejor elegir uno e intentar mantenerlo en cualquier proyecto. Cumplir con una convención particular hasta su finalización o renovación para evitar errores y perder tiempo innecesario.

Puede descargar los marcos de Laravel, Symphony o Codeigniter para que los proyectos web tengan un diseño de carpeta instantánea que funcione.

Así que intentaré transmitir un diseño de carpetas común a cualquier desarrollo:

MVC (Model View Controller) ofrece un buen paradigma de organización.

El código fuente raíz podría ser src (C ++) o aplicación (desarrollo web)

Una estructura de archivos que no tiene un objetivo claro para las clases que agrupa definitivamente causará confusión. No es solo para organizar el código, sino que puede soportar cargadores automáticos, fábrica de clases, almacenamiento local envolvente, almacenamiento remoto y espacio de nombres.

Esta estructura de carpetas se deriva y simplifica de Laravel Framework . Mi preferencia en esta publicación es la denominación en plural, pero uso palabras singulares en mis proyectos.


src / storage (modelos / implementaciones de almacenamiento de archivos / api / mysql / sql-lite / memcached / redis)

src / repositorios (Un contenedor de 'implementaciones de almacenamiento' con cierta lógica de almacenamiento, una interfaz común y una convención de resultados de retorno).

src / servicios | lógica | entidades (lógica de negocio de la aplicación)

src / controllers (Utilizado en el desarrollo web para enrutar solicitudes del servidor a sus servicios)

src / modules | sistemas ( sistemas modulares que amplían la funcionalidad general de su marco. Los servicios pueden usar módulos pero no viceversa)

src / helpers (Clases de ayuda o envoltura como, por ejemplo, manipulación de cadenas. Muchas veces esto podría estar en libs | vendor cuando es un tercero)

src / types (enumeraciones nombradas)

publico | construir | salida (web o c ++)

config (archivos de configuración. YAML se está volviendo popular para los archivos de configuración multiplataforma)

cache

registros

lang (es / es / ru / ...)

bootstrap (inicia el marco y la aplicación)

docs (documentación escrita en formato markdown .md)

pruebas ( pruebas unitarias)

base de datos / migraciones (Crear estructura de base de datos desde cero)

base de datos / semillas (llena su base de datos con datos ficticios para probar)

libs | proveedor (todo el software de terceros. 'libs' en C ++ y 'proveedor' generalmente en php)

activos | recursos (imágenes / sonidos / scripts / json / cualquier medio)

Heroselohim
fuente
1

Con lenguajes orientados a objetos, tiene la capacidad de construir espacios de nombres. Ese desglose lógico utilizado para separar partes de la aplicación para evitar el acoplamiento es la fuente principal del desglose de la ubicación del archivo lógico. Usar el acoplamiento como una razón para separar los espacios de nombres es un buen lugar para comenzar http://en.wikipedia.org/wiki/Software_package_metrics .

Otros han hablado sobre la configuración del proyecto en relación con la compilación, pero una vez que ingresa a la fuente en sí, se trata de lo que tiene sentido: solo use la forma de separar lógicamente el código de todos modos.

Travis
fuente