Buenas prácticas en soluciones de Visual Studio [cerrado]

10

Esperemos que sea una pregunta simple de relatividad. Estoy empezando a trabajar en un nuevo proyecto interno para crear capacidad de rastreo de dispositivos reparados dentro de los edificios.

La base de datos se almacena de forma remota en un servidor web, y se accederá a través de la API web (salida JSON) y se protegerá con OAuth. La interfaz gráfica de usuario de front-end se realiza en WPF y el código comercial en C #.

A partir de esto, veo las diferentes capas Presentación / Aplicación / Almacén de datos. Habrá un código para administrar todas las llamadas autenticadas a la API, una clase para representar entidades (objetos comerciales), clases para construir las entidades (objetos comerciales), partes para la GUI de WPF, partes de los modelos de vista de WPF, etc.

¿Es mejor crear esto en un solo proyecto, o dividirlos en proyectos individuales?

En mi corazón digo que debería ser múltiples proyectos. Lo he hecho en ambos sentidos anteriormente, y descubrí que las pruebas son más fáciles con una sola solución de proyecto, sin embargo, con múltiples proyectos, pueden surgir dependencias recursivas. Especialmente cuando las clases tienen interfaces para facilitar la prueba, he descubierto que las cosas pueden volverse incómodas.

JonWillis
fuente
1
Los separaría en lo que tiene sentido para el proyecto.
Ramhound
¿Alguien más tiene alguna idea, una en el proyecto para mantener las interfaces como MattDavey sugirió? Utilicé este enfoque antes para evitar las dependencias mencionadas. O si las interfaces para la clase x se sientan en el mismo proyecto que la clase x
JonWillis
Además, ¿qué capas usan todos ustedes? He visto algunas variaciones diferentes, aunque las principales son Presentación / Aplicación / Infraestructura. Algunos también dividen la aplicación en 2 partes, aplicación + servicio. Algunos modelos también mencionan una capa específica para la lógica de negocios, que para mí podría incluirse en los propios objetos de negocios.
JonWillis

Respuestas:

8

Depende del tamaño del proyecto.

Aquí están las pautas que suelo usar

  • Un proyecto pequeño, con un puñado de páginas o menos, casi siempre mantengo un solo proyecto.

  • Si la capa de acceso a datos del proyecto pequeño es grande o compleja, podría separarla en su propia capa, pero de lo contrario simplemente se ubica en su propia carpeta.

  • Si el proyecto es más grande, casi siempre tendré un proyecto separado para el DAL, y cualquier división adicional dependerá de dónde se encuentran los límites entre la funcionalidad de la aplicación.

  • Si la aplicación tiene múltiples propósitos, cada uno con sus propias vistas, modelos de vista, etc., generalmente separaré cada pieza en su propia área. Si cada sección es pequeña, las separo por una carpeta. Si cada sección es grande, las separaré por un proyecto.

  • Si tengo varios proyectos que necesitan para hacer referencia al mismo conjunto de objetos ( ViewModelBase, RelayCommand, etc), voy a crear un proyecto sólo para los objetos de infraestructura compartida.

  • Si tengo una gran cantidad de estilos / plantillas / recursos personalizados compartidos, crearé un proyecto solo para esos.

Como nota al margen, cometí un error con mi primer gran proyecto WPF y los separé poniendo Modelos en un proyecto, Vistas en otro y ViewModels en un tercero. Te puedo decir que ese no es el camino a seguir, ya que el mantenimiento se convierte en una pesadilla :)

Rachel
fuente
Curioso, ¿qué problemas de mantenimiento tuvo al separar las capas?
Ian
@ Rachel, usaré WPF. Por lo tanto, estaría interesado en saber cómo organizó el proyecto al final. Creo que puedo recordar que un pequeño proyecto de MVC fue un dolor al separar 3 partes en 3 dlls. Para WPF, Mi vista será la GUI, la entidad / objeto comercial que se va a cambiar y el ViewModel la interacción entre ellos. ViewModel se ocuparía de la lógica de llamar a un repositorio para cargar / guardar las reparaciones (que a su vez tienen fábricas / API web, etc.).
JonWillis
1
@Ian El mayor problema fue que la mayoría de los cambios menores, como agregar un solo campo, me obligaron a buscar el Modelo, la Vista, el Modelo de vista y el DAL en 4 bibliotecas separadas. El proyecto en el que estaba trabajando en ese momento era bastante grande, y perdí más tiempo del que me importaba buscando archivos específicos. Desde entonces he cambiado a mantener objetos relacionados entre sí, por lo que, por ejemplo, nada de búsqueda relacionados, tales como SearchView, SearchViewModely SearchResultModeltodos serían agrupadas en una carpeta y lo he encontrado hace que la aplicación más fácil de mantener.
Rachel
@Ian También recuerdo haber tenido problemas de dependencia y encontrar referencias circulares, porque a pesar de mis mejores esfuerzos, algunas capas necesitaban hacer referencia a otras, pero esa capa hacía referencia a ellas, por lo que tuve algunas soluciones feas hasta que refactoricé
Rachel
1
@ JonWillis La mayoría de mis proyectos de WPF se desglosan en función de los puntos especificados en mi respuesta. Por lo general, el DAL es su propia capa, y cada módulo o sección del proyecto se agrupa (en su propia carpeta, espacio de nombres o proyecto, dependiendo del tamaño del proyecto). Entonces, por ejemplo, todos los objetos de búsqueda estarían juntos, incluida la Interfacecapa de datos, pero la capa de acceso a datos real para la búsqueda estaría en la biblioteca DAL. Muy a menudo tengo una Infrastructureo Commonbiblioteca que contiene clases básicas comunes, interfaces y clases auxiliares.
Rachel
14

He visto los mejores resultados con un proyecto por capa, más un proyecto de prueba por capa. He visto pocas aplicaciones que no se pueden lograr en 10 o menos proyectos en la solución, donde la solución lo abarca todo .

No caigas en la trampa de usar proyectos donde realmente quieres espacios de nombres. Toneladas de proyectos no agrega nada más que gastos generales sin ganancia.

Bryan Boettcher
fuente
9

En mi humilde opinión, casi siempre es mejor. Casi siempre separo mi capa de datos a menos que el proyecto sea 100% trivial. La razón es porque la capa de datos tiende a pasar más a menudo. Raramente conectará una GUI a múltiples capas de datos y esperará que funcione bien. El escenario mucho más común es que tiene una sola capa de datos y desea que se distribuya entre múltiples GUI (ASP.Net, WPF y una aplicación Silverlight, por ejemplo). Es increíble cuando puedes construir el proyecto de capa de datos y poner ese dll como referencia en la próxima GUI que construyas.

Morgan Herlocker
fuente
+1 Cuando comienzo nuevos proyectos, a menudo construyo una capa de datos simulados que contiene los datos en la memoria. Me permite seguir construyendo el resto de la aplicación primero. Luego puedo cambiarlo por una capa de acceso a datos "real" más tarde ..
MattDavey
¿Consideraría que las entidades (DTO), las fábricas y las clases utilizadas para comunicarse con el servidor web forman parte de la capa de datos?
JonWillis
@ JonWillis - No, probablemente no todos. Pondría las fábricas y las clases para el servidor web en un espacio de nombres de un proyecto de biblioteca de clases. Mi capa de datos típica no contiene más que los archivos dbml y / o edmx necesarios. Como regla, sin embargo, doy cosas de "biblioteca / marco" su propio proyecto. Definitivamente no necesitan ser incluidos en el proyecto GUI, aunque veo que la gente hace eso todo el tiempo.
Morgan Herlocker
Sin embargo, de manera realista, ¿cuánto tiempo le tomaría tomar algunos espacios de nombres y dividirlos en un nuevo proyecto? Siento que es un trabajo de refactorización bastante fácil.
Didier A.
4

Para mí, 4 * es el número mágico. Un proyecto para cada capa y un proyecto que define todas las interfaces / DTO necesarios para comunicarse entre ellos.

* 7 si cuentas las pruebas unitarias

MattDavey
fuente
2

Siempre he usado una única solución si estoy trabajando en esas capas diferentes, o si hay un acoplamiento estrecho con ellas. Quiero llegar a F5 y hacer que todos los proyectos se reconstruyan si es necesario. No creo que haya una forma "correcta" de hacerlo.

Jeremy
fuente
2

Su gusto personal, lo más importante es ser consistente . Personalmente, tengo un proyecto separado para cada capa de la aplicación, por lo que la separación es obvia.

Tom Squires
fuente
¿A qué capas se separan? ¿Tiene capas separadas de aplicaciones / servicios? De ser así, ¿en qué se diferencian realmente? ¿Su lógica empresarial está contenida en la aplicación / servicio, o son métodos en los objetos comerciales reales?
JonWillis
1

El aumento en el número de proyectos tiene que ver con habilitar las pruebas unitarias y simplificar el gráfico de dependencia hasta el punto en que las cosas no son tan complejas que los cambios en una parte de la aplicación rompen las cosas en partes aparentemente no relacionadas de la aplicación.

Funciona cuando estoy haciendo algún tipo de inversión de dependencia, para poner todos los "contratos", interfaces, clases abstractas, objetos de transferencia de datos en un solo ensamblaje. En otra asamblea puse todo lo que habla a la base de datos. Las pruebas unitarias obtienen su propio ensamblaje. Si la interfaz de usuario es fundamentalmente no comprobable (por ejemplo, Win.NET ASP.NET), entonces hay un beneficio significativo al dividir la interfaz de usuario en código comprobable y código no comprobable, un ensamblaje cada uno. A veces, comienza a aparecer un código que no tiene nada que ver con la base de datos, la interfaz de usuario o cualquier cosa que haya mencionado hasta ahora; es un código que deseaba que estuviera en el marco .NET. Ese código lo pondré en un conjunto de utilidades, o al menos lo pondré en el conjunto raíz (probablemente el que tiene las interfaces.

Si todos los ensamblajes hacen referencia a todos los ensamblajes, o casi, entonces deberían fusionarse nuevamente en un ensamblaje único. Si usted o las personas de su equipo carecen de la disciplina para evitar colocar el código del nivel de datos en la interfaz de usuario y la interfaz de usuario en el nivel de datos, entonces simplifique las cosas fusionando todo en una sola capa.

Algunas ediciones de Visual Studio se encuentran con problemas de rendimiento en aproximadamente 15 ensamblados, a veces depende de qué tipo de proyecto hay. Sin embargo, la descarga estratégica de archivos de proyecto a veces puede ayudar.

MatthewMartin
fuente
Soy el único desarrollador de la compañía, por el momento. Y también recién salido de la universidad, tratando de inculcar buenas prácticas en los proyectos más grandes lo antes posible. Estoy interesado en que sea mantenible porque la especificación del sistema ha cambiado mucho antes de que incluso comenzara a documentarlo, en contra de las solicitudes de querer que el sistema sea lo antes posible. En su opinión, ¿un ensamblado que contenga solo interfaces sería una solución adecuada? De esa manera, la dependencia solo debe estar en las interfaces y las clases de fábrica.
JonWillis
1
Si. Es mejor comprender la motivación de la división de la asamblea, pero si usted (o los miembros de su equipo) no lo asimilan, sigue siendo una maniobra económica. Por lo tanto, incluso si termina con todos los ensamblajes dependientes de todos los ensamblajes y sin esperanza de pruebas unitarias, mover cosas que se comportan como contratos (interfaces, clases abstractas) a su propio ensamblaje, es un paso en la dirección correcta y tiene pocas desventajas.
MatthewMartin
-2

La única buena razón para tener más de un proyecto es si necesita compartir un conjunto de clases y archivos en múltiples aplicaciones.

Si los proyectos son utilizados por una sola aplicación, no deberían haberse realizado en primer lugar. Use espacios de nombres en su lugar. Ahórrese el problema de las referencias circulares, la sobrecarga de dll y la confusión del proyecto al buscar archivos.

Lea este artículo para obtener una explicación más detallada de por qué es así: http://lostechies.com/chadmyers/2008/07/16/project-anti-pattern-many-projects-in-a-visual-studio- archivo-solución /

Y como dice el artículo, agradecería a cualquiera que tenga una razón válida para tener múltiples proyectos, aparte del código compartido en la aplicación, que me diga qué es, porque dudo que haya alguno.

Didier A.
fuente
Se agradecerán los argumentos en contra del voto negativo.
Didier A.