Pregunta

El proyecto en el que estoy trabajando acaba de alcanzar las 4200 líneas en el archivo C # principal, lo que hace que IntelliSense tarde unos segundos (a veces hasta 6 o más) en responder, durante el cual Visual Studio se bloquea. Me pregunto cómo todos los demás dividen sus archivos y si hay un consenso.

Intenté buscar algunas guías y encontré guía de C ++ de Google , pero no pude ver nada sobre la semántica, como el tamaño de las funciones y el tamaño de los archivos; tal vez esté ahí, no lo he mirado por un tiempo.

Entonces, ¿cómo divides tus archivos? ¿Agrupas tus métodos por las funciones que sirven? ¿Por tipos (manejadores de eventos, privados / públicos)? ¿Y en qué límite de tamaño dividen las funciones?

Para aclarar, la aplicación en cuestión maneja los datos, por lo que su interfaz es una cuadrícula grande y todo gira alrededor de la cuadrícula. Tiene algunos formularios de diálogos para la administración, pero se trata de los datos. La razón por la que es tan grande es que hay muchas comprobaciones de errores, manejo de eventos y también la cuadrícula configurada como detalle maestro con tres cuadrículas más para cada fila (pero estas se cargan en la fila maestra expandida). Espero que esto ayude a aclarar de qué estoy hablando.

¿Fue útil?

Solución

Creo que tu problema se resume con el término que usas: " Main C # file " ;.

A menos que te refieras a main (como en el método main ()) no hay lugar para ese concepto.

Si tiene una clase de utilidad general u otros métodos comunes, debe dividirlos en partes funcionales similares.

Normalmente, mis archivos son solo asignaciones de clases uno a uno.

A veces, las clases que están muy relacionadas están en el mismo archivo.

Si su archivo es demasiado grande, es una indicación de que su clase es demasiado grande y general.

Intento mantener mis métodos en media pantalla o menos. (Cuando se trata de un código que escribo desde cero, generalmente es de 12 líneas o menos, pero últimamente he estado trabajando en el código existente de otros desarrolladores y tuve que refactorizar las funciones de 100 líneas ...)

A veces es una pantalla, pero se está haciendo muy grande.

EDITAR:

Para responder a su pregunta sobre el límite de tamaño acerca de las funciones, para mí es menos sobre el tamaño (aunque eso es un buen indicador de un problema) y más sobre cómo hacer una sola cosa y mantener cada una SIMPLE.

Otros consejos

En el libro clásico " Programación estructurada " Dijkstra escribió una sección titulada: "Sobre nuestra incapacidad para hacer mucho". Su punto era simple. Los humanos no son muy inteligentes. No podemos hacer malabares con más de unos pocos conceptos en nuestra mente al mismo tiempo.

Es muy importante mantener tus clases y métodos pequeños. Cuando un método supera una docena de líneas más o menos, se debe dividir. Cuando una clase supera un par de cientos de líneas, debe dividirse. Esta es la única manera de mantener el código bien organizado y manejable. He estado programando durante casi 40 años, y con cada año que he pasado, me doy cuenta de lo importante que es la palabra "pequeño" es al escribir software.

En cuanto a cómo haces esto, este es un tema muy grande que se ha escrito muchas veces. Se trata de la gestión de dependencias, la ocultación de información y el diseño orientado a objetos en general. Aquí hay una lista de lectura.

Divida sus tipos donde sea natural dividirlos, pero tenga cuidado con los tipos que están haciendo demasiado. A unas 500 líneas (de Java o C #) me preocupa. Aproximadamente a 1000 líneas empiezo a ver si el tipo debería dividirse ... pero a veces simplemente no puedo / no debería ser.

En cuanto a los métodos: no me gusta cuando no puedo ver todo el método en la pantalla a la vez. Obviamente, eso depende del tamaño del monitor, etc., pero es una regla general razonable. Aunque prefiero que sean más cortos. Una vez más, hay excepciones: algunas lógicas son realmente difíciles de desentrañar, especialmente si hay muchas variables locales que, naturalmente, no se quieren encapsular juntas.

A veces tiene sentido que un solo tipo tenga lot de métodos, como System.Linq.Enumerable pero las clases parciales pueden ayudar en tales casos, si puede dividir el tipo en grupos lógicos (en el caso de Enumerable , agrupar por agregación / operaciones de conjuntos / filtrado, etc. parecería natural). Sin embargo, estos casos son raros en mi experiencia.

El libro de Martin Fowler Refactorización Creo que te da un buen punto de partida para esto. Da instrucciones sobre cómo identificar " olores de código " y cómo refactorizar su código para corregir estos " olores. " El resultado natural (aunque no es el objetivo principal) es que termines con clases más pequeñas y fáciles de mantener.

EDIT

A la luz de su edición, siempre he insistido en que la buena práctica de codificación para el código de back-end es la misma en el nivel de presentación. Algunos patrones muy útiles a considerar para las refactorizaciones de la interfaz de usuario son Comando, Estrategia, Especificación y Estado.

En resumen, su vista solo debe tener código para manejar eventos y asignar valores. Toda lógica debe estar separada en otra clase. Una vez que haga esto, descubrirá que es más obvio dónde puede refactorizar. Las cuadrículas hacen que esto sea un poco más difícil porque hacen que sea demasiado fácil dividir su estado de presentación entre la lógica de presentación y la vista, pero con un poco de trabajo, puede hacer una indirección para minimizar el dolor causado por esto .

No codifique de manera procesal, y no terminará con 4,200 líneas en un archivo.

En C # es una buena idea adherirse a algunos SOLID Principios de diseño orientados a objetos. Cada clase debe tener una y solo una razón para cambiar. El método principal simplemente debe iniciar el punto de inicio de la aplicación (y configurar su contenedor de inyección de dependencia, si está usando algo como StructureMap).

Por lo general, no tengo archivos con más de 200 líneas de código, y los prefiero si tienen menos de 100.

No hay reglas estrictas y rápidas, pero hay un acuerdo general de que más funciones más cortas son mejores que una sola función grande y que las clases más pequeñas son mejores que una clase grande.

Las funciones de más de 40 líneas deben hacerte considerar cómo puedes dividirlo. Observe especialmente los bucles anidados, que son confusos y, a menudo, fáciles de traducir a llamadas de función con buenos nombres descriptivos.

Divido las clases cuando siento que hacen más de una cosa, como mezcla de presentación y lógica. Una clase grande es menos problemática que un método grande, siempre que la clase haga 1 cosa.

El consenso en las guías de estilo que he visto es agrupar métodos por acceso, con constructores y métodos públicos en la parte superior. Cualquier cosa consistente es genial.

Debes leer sobre el estilo de C # y la refactorización para comprender realmente los problemas que estás abordando.

Los elementos del estilo C # son una buena guía de estilo C # del árbol muerto, y esta blog post tiene varios enlaces a buenas guías de estilo en línea.

Finalmente, considere usar FxCop y StyleCop . Esto no ayudará con las preguntas que hizo, pero puede detectar otros problemas de estilo con su código. Ya que has sumergido tu dedo del pie en el agua, también podrías saltar.

Eso es mucho, pero desarrollar gusto, estilo y claridad es una gran diferencia entre los buenos desarrolladores y los malos.

Cada clase debe hacer una pequeña cosa y hacerlo bien. ¿Es tu clase un formulario? Entonces no debería tener NINGUNA lógica de negocios en ella.

¿Representa un concepto único, como un usuario o un estado? Entonces no debería tener ningún dibujo, cargar / guardar, etc ...

Cada programador pasa por etapas y niveles. Está reconociendo un problema con su nivel actual y está listo para abordar el siguiente.

Por lo que dijo, parece que su nivel actual es " Solucionar un problema " ;, lo más probable es que esté usando un código de procedimiento, y necesita comenzar a buscar nuevas formas de abordarlo.

Recomiendo ver cómo hacer realmente el diseño OO. Hay muchas teorías que probablemente has escuchado que no tienen sentido. La razón por la que no lo hacen es que no se aplican a la forma en que está programando actualmente.

Déjame encontrar una buena publicación ... Mira esto para comenzar:

how-do-i-break-my-procedural-coding -habita

are-there-any-rules-for-oop

orientado a objetos-mejores-prácticas-heredadas-v -composition-v-interfaces

También hay publicaciones que lo remitirán a buenos libros de diseño de OO. Una " Refactorización " El libro es probablemente uno de los mejores lugares en los que podrías comenzar.

Ahora mismo estás en un buen momento, pero no creerías lo lejos que tienes que ir. Espero que estés emocionado al respecto porque algunas de estas cosas en tu futuro cercano son algunas de las mejores programaciones "Experiencias de aprendizaje" lo tendrás alguna vez.

Buena suerte.

Puede buscar pequeñas cosas para cambiar y cambiar cada una lentamente con el tiempo.

  • ¿Se usan todos los métodos solo en esa clase? Busque los métodos de soporte, como la validación, la manipulación de cadenas, que pueden trasladarse a las clases helper / util.

  • ¿Está utilizando alguna sección #region? Las agrupaciones lógicas de métodos relacionados en una #región a menudo se prestan a ser divididas en clases separadas.

  • ¿La clase es un formulario? Considere utilizar Controles de usuario para los controles de formulario o grupos de controles de formulario.

A veces, las clases grandes evolucionan con el tiempo debido a que muchos desarrolladores hacen correcciones rápidas / nuevas características sin considerar el diseño general. Revise algunos de los enlaces de teoría de diseño que otros han proporcionado aquí y considere el apoyo continuo para hacerlos cumplir, como revisiones de código y talleres de equipo para revisar el diseño.

Bueno, me da miedo decir que es posible que tenga un problema mayor que un tiempo de carga lento. Va a encontrar problemas de código estrechamente acoplado y problemas de mantenimiento / legibilidad.

Existen muy buenas razones para dividir los archivos de clase en archivos más pequeños (e igualmente buenas razones para mover archivos a diferentes proyectos / ensamblajes).

Piensa en cuál es el propósito que se supone que tu clase debe lograr. Cada archivo realmente debería tener un solo propósito. Si está demasiado generalizado en su objetivo, por ejemplo, "Contener lógica de la cesta de la compra", entonces vas por el camino equivocado.

También, como se mencionó, el término que usa: " Archivo C # principal " Sólo apesta que tienes una mentalidad muy procesal. Mi consejo sería detenerse, retroceder y leer rápidamente algunos de los siguientes temas:

  • Principios generales de OOP
  • diseño basado en dominio
  • Pruebas unitarias
  • IoC Contenedores

Buena suerte con tus búsquedas.

Usa clases parciales. Básicamente, puedes dividir una sola clase en varios archivos.

Quizás el OP pueda responder: ¿está su proyecto utilizando programación orientada a objetos? El hecho de que use la palabra " archivo " sugiere que no lo es.

Hasta que no entienda la orientación a objetos, no hay esperanza de mejorar su código de manera importante. Sería mejor no dividir el archivo en absoluto, esperar hasta que crezca para que sea insoportablemente lento y con errores, luego, en lugar de soportarlo más, vaya a aprender OO.

El analizador Intellisense en Visual Studio 2008 parece ser considerablemente más rápido que el de 2005 (sé que hicieron mucho trabajo específicamente en esta área), por lo que aunque debería analizar la posibilidad de dividir el archivo en algún momento como otros Como se ha mencionado, Visual Studio 2008 puede resolver su problema de rendimiento inmediato. Lo he usado para abrir un archivo Linq a SQL de 100 K + sin mucho problema.

Divida el código para que cada clase / archivo / función / etc. solo hace One Thing ™. El principio de responsabilidad única es una buena guía para dividir la funcionalidad en clases.

Hoy en día, las clases más grandes que escribo tienen aproximadamente 200 líneas, y los métodos son en su mayoría de 1 a 10 líneas.

Si tiene regiones de código dentro de una clase, un método simple es usar la palabra clave parcial y desglosar la definición de la clase en ese archivo. Normalmente hago esto para clases grandes.

La convención que utilizo es tener el ClassName_RegionName.cs. Por ejemplo, si quiero desglosar una clase que administra el esquema para una conexión de base de datos y llamé a la clase DatabaseConnection, crearía un archivo llamado DatabaseConnection.cs para la clase principal y luego DatabaseConnection_Schema.cs para la funcionalidad de esquema.

Algunas clases solo tienen que ser grandes. Eso no es mal diseño; son solo de implementación pesada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top