¿Son las # regiones un antipatrón o un olor a código?


267

C # permite el uso de #region/ #endregionpalabras clave para hacer que las áreas de código se puedan contraer en el editor. Cada vez que hago esto, lo hago para ocultar grandes porciones de código que probablemente podrían refactorizarse en otras clases o métodos. Por ejemplo, he visto métodos que contienen 500 líneas de código con 3 o 4 regiones solo para que sea manejable.

Entonces, ¿el uso juicioso de las regiones es un signo de problemas? A mí me parece así.


99
FYI: CodeMap prácticamente elimina las necesidades de las regiones. visualstudiogallery.msdn.microsoft.com/… - Haz clic y te llevará al método / atributo / lo que sea. Lo uso todos los días y es sorprendente cuánto ganas en productividad y también en términos cognitivos. Obtendrá una 'vista de pájaro' mucho más clara de la clase.

77
¿Alguien puede hacer de esto un wiki? No hay una respuesta correcta o incorrecta a esta pregunta (bueno, dentro de lo razonable), es casi completamente subjetiva.
Ed S.

66
Por lo que vale, Jeff Atwood los odia . Argumenta que esconden códigos malos.
Brian

3
Code olor es un desarrollador que no se baña y no usa un desodorante.
marko

55
Regiones cuidadosamente elaboradas en código maloliente es lo que hacen unos pocos apretones de Febreeze en un sofá crujiente. Lo hace soportable hasta que encuentre el dinero (tiempo) para reemplazarlo.
Newtopian

Respuestas:


285

Un olor a código es un síntoma que indica que hay un problema en el diseño que potencialmente aumentará el número de errores: este no es el caso para las regiones, pero las regiones pueden contribuir a crear olores de código, como los métodos largos.

Ya que:

Un antipatrón (o antipatrón) es un patrón utilizado en operaciones sociales o comerciales o ingeniería de software que puede usarse comúnmente pero que es ineficaz y / o contraproducente en la práctica.

Las regiones son antipatrones. Requieren más trabajo que no aumenta la calidad o la legibilidad del código, que no reduce la cantidad de errores y que solo puede hacer que el código sea más complicado de refactorizar.

No use regiones dentro de los métodos; refactorizar en su lugar

Los métodos deben ser cortos . Si solo hay diez líneas en un método, probablemente no usaría regiones para ocultar cinco de ellas cuando trabaje en otras cinco.

Además, cada método debe hacer una sola cosa . Las regiones, por otro lado, están destinadas a separar cosas diferentes . Si su método hace A, entonces B, es lógico crear dos regiones, pero este es un enfoque incorrecto; en su lugar, debe refactorizar el método en dos métodos separados.

El uso de regiones en este caso también puede dificultar la refactorización. Imagina que tienes:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    if (!verification)
    {
        throw new DataCorruptedException();
    }

    Do(data);
    DoSomethingElse(data);
    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine();
    auditEngine.Submit(data);
    #endregion
}

El colapso de la primera región para concentrarse en la segunda no solo es arriesgado: podemos olvidarnos fácilmente de la excepción que detiene el flujo (podría haber una cláusula de protección con una return, que es aún más difícil de detectar), sino que también tendría un problema si el código debe ser refactorizado de esta manera:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    var info = DoSomethingElse(data);

    if (verification)
    {
        Do(data);
    }

    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine(info);
    auditEngine.Submit(
        verification ? new AcceptedDataAudit(data) : new CorruptedDataAudit(data));
    #endregion
}

Ahora, las regiones no tienen sentido, y no es posible leer y comprender el código en la segunda región sin mirar el código en la primera.

Otro caso que a veces veo es este:

public void DoSomething(string a, int b)
{
    #region Validation of arguments
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }
    #endregion

    #region Do real work
    ...
    #endregion
}

Es tentador usar regiones cuando la validación de argumentos comienza a abarcar decenas de LOC, pero hay una mejor manera de resolver este problema: la utilizada por el código fuente de .NET Framework:

public void DoSomething(string a, int b)
{
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }

    InternalDoSomething(a, b);
}

private void InternalDoSomething(string a, int b)
{
    ...
}

No use regiones fuera de los métodos para agrupar

  • Algunas personas los usan para agrupar campos, propiedades, etc. Este enfoque es incorrecto: si su código es compatible con StyleCop, entonces los campos, propiedades, métodos privados, constructores, etc. ya están agrupados y son fáciles de encontrar. Si no es así, es hora de comenzar a pensar en aplicar reglas que garanticen la uniformidad en su base de código.

  • Otras personas usan regiones para ocultar muchas entidades similares . Por ejemplo, cuando tiene una clase con cien campos (que genera al menos 500 líneas de código si cuenta los comentarios y el espacio en blanco), puede verse tentado a colocar esos campos dentro de una región, colapsarlos y olvidarse de ellos. Nuevamente, lo estás haciendo mal: con tantos campos en una clase, deberías pensar mejor en usar la herencia o cortar el objeto en varios objetos.

  • Finalmente, algunas personas se sienten tentadas a usar regiones para agrupar cosas relacionadas : un evento con su delegado, o un método relacionado con IO con otros métodos relacionados con IO, etc. En el primer caso, se convierte en un desastre que es difícil de mantener , Lea y entienda. En el segundo caso, el mejor diseño probablemente sería crear varias clases.

¿Hay un buen uso para las regiones?

No. Hubo un uso heredado: código generado. Aún así, las herramientas de generación de código solo tienen que usar clases parciales en su lugar. Si C # tiene soporte de regiones, es principalmente porque este uso heredado, y porque ahora que demasiadas personas usan regiones en su código, sería imposible eliminarlas sin romper las bases de código existentes.

Piensa en ello como en goto. El hecho de que el idioma o el IDE admitan una función no significa que deba usarse a diario. La regla StyleCop SA1124 es clara: no debe usar regiones. Nunca.

Ejemplos

Actualmente estoy haciendo una revisión del código del código de mi compañero de trabajo. La base de código contiene muchas regiones, y en realidad es un ejemplo perfecto de cómo no usar regiones y por qué las regiones conducen a un código incorrecto. Aquí hay unos ejemplos:

4 000 monstruo LOC:

Recientemente leí en algún lugar de Programmers.SE que cuando un archivo contiene demasiados usings (después de ejecutar el comando "Eliminar usos no utilizados"), es una buena señal de que la clase dentro de este archivo está haciendo demasiado. Lo mismo se aplica al tamaño del archivo en sí.

Mientras revisaba el código, me encontré con un archivo de 4 000 LOC. Parecía que el autor de este código simplemente copiaba y pegaba el mismo método de 15 líneas cientos de veces, cambiando ligeramente los nombres de las variables y el método llamado. Una expresión regular simple permitió recortar el archivo de 4 000 LOC a 500 LOC, simplemente agregando algunos genéricos; Estoy bastante seguro de que con una refactorización más inteligente, esta clase puede reducirse a unas pocas docenas de líneas.

Al usar regiones, el autor se animó a ignorar el hecho de que el código es imposible de mantener y está mal escrito, y a duplicar en gran medida el código en lugar de refactorizarlo.

Región "Do A", Región "Do B":

Otro excelente ejemplo fue un método de inicialización de monstruos que simplemente realizó la tarea 1, luego la tarea 2, luego la tarea 3, etc. Hubo cinco o seis tareas que fueron totalmente independientes, cada una inicializando algo en una clase contenedor. Todas esas tareas se agruparon en un método y se agruparon en regiones.

Esto tenía una ventaja:

  • El método fue bastante claro de entender al observar los nombres de las regiones. Dicho esto, el mismo método una vez refactorizado sería tan claro como el original.

Los problemas, por otro lado, fueron múltiples:

  • No era obvio si había dependencias entre las regiones. Con suerte, no hubo reutilización de variables; de lo contrario, el mantenimiento podría ser una pesadilla aún más.

  • El método era casi imposible de probar. ¿Cómo podría saber fácilmente si el método que hace veinte cosas a la vez las hace correctamente?

Región de campos, región de propiedades, región de constructor:

El código revisado también contenía muchas regiones que agrupaban todos los campos, todas las propiedades, etc. Esto tenía un problema obvio: el crecimiento del código fuente.

Cuando abre un archivo y ve una lista enorme de campos, está más inclinado a refactorizar la clase primero y luego trabajar con el código. Con las regiones, tienes el hábito de colapsar cosas y olvidarte de ellas.

Otro problema es que si lo haces en todas partes, te encontrarás creando regiones de un bloque, lo que no tiene ningún sentido. Este fue realmente el caso en el código que revisé, donde había muchos que #region Constructorcontenían un constructor.

Finalmente, los campos, propiedades, constructores, etc. ya deberían estar en orden . Si lo son y coinciden con las convenciones (constantes que comienzan con una letra mayúscula, etc.), ya está claro en qué parte del tipo de elementos se detiene y comienza otro, por lo que no es necesario crear regiones explícitamente para eso.


13
Creo que hay al menos algunos usos defendibles de #regiones, por ejemplo, colapso de cláusulas de protección (comprobación de parámetros de entrada) que, si no se colapsan, restarán la esencia o "carne" del método. Otro ejemplo es el manejo de excepciones en los límites de la API; a menudo no desea afectar el seguimiento de la pila llamando a otros métodos para ajustar la excepción, por lo que tiene varias líneas de código para ajustar y volver a lanzar. Esto a menudo también es un código no relevante y puede contraerse de forma segura.
Daniel B

99
Verificación de la realidad. He visto muchas #regiones entre métodos que fueron útiles. Cuando tenga un método de varios cientos de líneas con lógica de control anidada con docenas a cientos de líneas con algunas de ellas, gracias a Dios, el idiota al menos puso en las regiones.
radarbob

37
@radarbob: en resumen, las regiones son útiles en código basura que no debería existir en primer lugar.
Arseni Mourzenko

41
-1 (si tuviera la reputación). Incluso si los miembros de tipo están bien organizados y separados, puede haber muchos de ellos. Las regiones le ahorran tener que desplazarse más allá de las 10 o 12 propiedades y los captadores y definidores asociados solo para llegar al método en el que desea trabajar. La única alternativa es colapsar todas sus propiedades individualmente, lo cual no es algo de lo que sea fanático. La funcionalidad de mostrar / ocultar a gran escala que proporcionan las regiones es extremadamente útil. Sin embargo, estoy de acuerdo con las regiones dentro del método.
Asad Saeeduddin

14
Estoy totalmente en desacuerdo con esta respuesta: el código maloliente y la región no tienen nada que ver entre sí. Si su código apesta, apestaría con o sin regiones. La forma en que uso las regiones es segregar mis clases en regiones. Sin embargo, generalmente sigo el mismo patrón: propiedades públicas, métodos públicos, campos privados, métodos privados. Ese es el único uso para el que tendría regiones. Cualquier otra cosa, probablemente esté rompiendo el principal de SRP en su código.
Alexus

113

¡Es increíble para mí cuántas personas odian las regiones con tanta pasión!

Estoy completamente de acuerdo con muchas de sus objeciones: insertar código en un #regionpara ocultarlo es algo malo. Dividir una clase en #regionscuándo debería refactorizarse en clases separadas es claramente un error. Usar un #regionpara insertar información semántica redundante es, bueno, redundante.

¡Pero ninguna de esas cosas significa que hay algo intrínsecamente malo con el uso de regiones en su código! Solo puedo suponer que las objeciones de la mayoría de las personas provienen de haber trabajado en equipos donde otros están inclinados a usar las funciones IDE como esta incorrectamente. Tengo el lujo de trabajar en la primaria por mi cuenta, y aprecio la forma en que las regiones han ayudado a organizar mi flujo de trabajo. Tal vez sea mi trastorno obsesivo compulsivo, pero no me gusta ver un montón de código en mi pantalla a la vez, sin importar cuán elegante y elegantemente escrito esté. Separar las cosas en regiones lógicas me permite colapsar el código que no me interesa para trabajar en el código que hago.preocuparse. No estoy ignorando el código mal escrito, no tiene sentido refactorizarlo más de lo que es, y la organización "meta" adicional es descriptiva, más que inútil.

Ahora que he pasado más tiempo trabajando en C ++, programando más directamente a la API de Windows, me encuentro deseando que el soporte para las regiones sea tan bueno como lo es para C #. Podría argumentar que el uso de una biblioteca GUI alternativa haría que mi código sea más simple o más claro, eliminando así la necesidad de eliminar el ruido de código irrelevante de la pantalla, pero tengo otras razones para no querer hacer eso. Soy lo suficientemente competente con mi teclado e IDE que expandir / colapsar el código subdividido en regiones toma menos de una fracción de segundo. El tiempo que ahorro en capacidad mental, tratando de limitar mi enfoque consciente solo al código en el que estoy trabajando actualmente, vale la pena. Todo pertenece en una sola clase / archivo, pero no todos pertenecen a mi pantalla al mismo tiempo.

El punto es que usar #regionspara separar y dividir lógicamente su código no es algo malo que deba evitarse a toda costa. Como señala Ed, no es un "olor a código". Si su código huele mal, puede estar seguro de que no proviene de las regiones, sino de cualquier código que haya intentado enterrar en esas regiones. Si una función te ayuda a ser más organizado o a escribir mejor código, entonces digo que lo uses . Si se convierte en un obstáculo, o te encuentras usándolo incorrectamente, entonces deja de usarlo. Si lo peor llega a ser peor, y te ves obligado a trabajar en un equipo con personas que lo usan, entonces memoriza el atajo de teclado para desactivar el esquema del código: Ctrl+ M, Ctrl+P. Y deja de quejarte. A veces tengo la sensación de que esta es otra forma en que a los que quieren ser vistos como programadores "verdaderos" y "incondicionales" les gusta probar y demostrar su valía. No es mejor evitar las regiones que evitar la coloración de sintaxis. No te hace un desarrollador más machista.

Dicho todo esto, las regiones dentro de un método son pura tontería. Cada vez que desees hacer eso, deberías refactorizar a un método separado. No hay excusas.


99
Bien dicho. El uso de regiones para la organización no es más dañino que alternar la opción "ver espacios en blanco" del IDE. Es una preferencia personal.
Josh

24
Al trabajar en WPF con ViewModels que tienen 10 o 20 propiedades que simplemente envuelven las propiedades de mi modelo, me encantan las regiones: puedo guardar esas propiedades en una región (nunca necesitan ser tocadas) y mantener mis ojos en el código relevante .
Kirk Broadhurst

44
Totalmente de acuerdo. En .NET 2.0, las propiedades tienen aproximadamente 8-10 líneas de largo. Cuando tienes más de 20 propiedades en una clase, ocupan mucho espacio. Las regiones son perfectas para colapsarlas.
Kristof Claes

66
@ Kristof: al igual que las propiedades en .NET 4.0 que hacen una validación de entrada simple. Las propiedades automáticas simplemente no han sido tan mágicas para mis propósitos.
Cody Gray

8
Estoy dispuesto a apostar mi bola izquierda a que las personas que odian las regiones nunca desarrollaron una aplicación WPF o nunca utilizaron las funcionalidades definitorias de WPF, como el enlace de datos y el enlace de comandos. Simplemente configurar su código para que esos trabajos ocupen mucho espacio y, por lo general, no tiene que volver a mirarlos.
l46kok

70

En primer lugar, ya no soporto el término "olor a código". Se usa con demasiada frecuencia y es utilizado por personas que no podrían reconocer un buen código si lo mordiera. De todos modos ...

Personalmente no me gusta usar muchas regiones. Me resulta más difícil obtener el código, y el código es lo que me interesa. Me gustan las regiones cuando tengo una gran porción de código que no es necesario tocar con mucha frecuencia. Aparte de eso, parecen interponerse en mi camino y regiones como "Métodos privados", "Métodos públicos", etc., me vuelven loco. Son similares a los comentarios de la variedad i++ //increment i.

También agregaría que el uso de regiones no puede ser realmente un "antipatrón", ya que ese término se usa comúnmente para describir patrones de diseño / lógica de programa, no el diseño de un editor de texto. Esto es subjetivo; usa lo que funciona para ti. Nunca terminarás con un programa que no se puede mantener debido al uso excesivo de las regiones, de eso se tratan los antipatrones. :)


2
Normalmente te votaría negativamente por el comentario del código, pero en este caso es exactamente exacto. El no código no puede ser un olor a código. +2!

77
Jaja, bueno, no quiero decir que el término "olor a código" no se pueda usar con precisión. Puede, pero lo veo tanto en estos días que mi reacción inmediata es solo molestia, especialmente cuando se trata de personas que realmente solo están repitiendo lo que escuchan sin entenderlo o pensar críticamente. Las afirmaciones como "más de 5 variables locales en una función es un olor a código" solo muestran la poca experiencia que esa persona realmente tiene.
Ed S.

13
No estoy seguro de entender tu comentario sobre los olores de código. Los olores de código no indican que haya un problema, solo puede haber un problema.
Craig

77
+1 por enfrentarse al término código olor. Me cansé cuando vi una publicación que decía que los métodos privados eran un olor a código. Pero, en general, no estoy de acuerdo con su disgusto por las regiones. Me distraigo fácilmente. De hecho, me encantaría que VS tuviera un modo VB4 en el que pudiera mostrar un solo método a la vez.
Josh

77
Solo quería intervenir y decir que el mal uso de una metáfora perfectamente buena no debería devaluar la metáfora. El "código de olor" es una gran metáfora, una que se entiende instantáneamente, se recuerda fácilmente y se usa fácilmente. Todavía hay muchos lugares donde aplicar la metáfora del "olor a código" sigue siendo la mejor manera de transmitir un punto.
Eric King

23

Sí, las regiones son un código de olor!

Estaría feliz de ver regiones eliminadas del compilador por completo. Cada desarrollador presenta su propio esquema de aseo inútil que nunca será de valor para otro programador. Tengo todo que ver con los programadores que desean decorar y embellecer a su bebé, nada que tenga ningún valor real.

¿Puedes pensar en un ejemplo en el que pensaste "caramba, me gustaría que mi colega haya usado algunas regiones aquí"?

A pesar de que puedo configurar mi IDE para expandir automáticamente todas las regiones, siguen siendo un dolor ocular y no leen el código real.

Realmente me importaría menos si todos mis métodos públicos están agrupados o no. ¡Felicidades, conoce la diferencia entre una declaración de variable y una inicialización, no es necesario mostrarla en código!

Aseo sin valor!

Además, si su archivo necesita y 'arquitectura de información' a través del uso de regiones, es posible que desee combatir el problema central: ¡Su clase es demasiado grande! Dividirlo en partes más pequeñas es mucho más beneficioso y, cuando se hace correctamente, agrega una verdadera semántica / legibilidad.


¿Son #regions parte del compilador? Pensé que eran solo una directiva para el IDE que podría ignorarse.
Steve Rukuts

2
El compilador necesitaría ignorarlos al analizar su código C #. Si no los ignora, los vomitaría. Lo digo de esa manera.
Joppe

1
"¿Puedes pensar en un ejemplo en el que pensaste" caramba, me gustaría que mi colega haya usado algunas regiones aquí! " Sí mucho así. Cuando tengo una clase con métodos privados y métodos públicos, los separo en regiones porque al refactorizar los métodos públicos, no necesariamente es necesario tocar el código privado y viceversa.
Anshul

Obviamente nunca has visto código subcontratado. Tantas veces las regiones habrían sido geniales para ver en el código subcontratado. Aunque el código apesta, al menos hubiera sido mucho más fácil de comprender si se hubiera agrupado en algún sentido lógico. Sin embargo, si su código no es lógico, es probable que las regiones tampoco lo sean, por lo que probablemente lo hubiera empeorado. Sin embargo, las regiones son excelentes cuando se usan correctamente.
Nickmccomb

15

Personalmente uso regiones como una forma de agrupar varios tipos de métodos o partes de código.

Entonces, un archivo de código podría verse así al abrirlo:

  • Propiedades publicas
  • Constructores
  • Guardar métodos
  • Editar métodos
  • Métodos de ayuda privada

No pongo regiones dentro de los métodos. En mi humilde opinión eso es una señal de código de olor. Una vez me encontré con un método que tenía más de 1200 líneas de largo y tenía 5 regiones diferentes. Fue un espectáculo aterrador!

Si lo está utilizando como una forma de organizar su código de una manera que acelere la búsqueda de cosas para otros desarrolladores, no creo que sea una señal de problemas. Si lo está utilizando para ocultar líneas de código dentro de un método, diría que es hora de repensar ese método.


14
Ugh Sé que este es un tema subjetivo, pero hombre, realmente no puedo soportar este esquema. En mi experiencia, la 'organización' agregada no ayuda en absoluto y solo hace que navegar por el código sea un dolor de cabeza. También prefiero los métodos de agrupación no solo por modificador de acceso sino también por responsabilidad lógica. Para la interfaz pública, generalmente agrupo cada método / propiedad, pero a menudo un método protegido puede llamar a una función auxiliar privada, y en ese caso prefiero que la función auxiliar (que solo se puede usar allí) esté por encima o por debajo de método que lo llama.
Ed S.

3
@Ed S. - por eso dije "podría verse". Es muy subjetivo. No estoy diciendo que todos los archivos deberían verse así. Me sorprendería si lo hicieran. Solo un ejemplo sobre un tema complejo. :)
Tyanna

Oh lo sé, como dije; Es subjetivo. Lo que sea que funcione para usted / su equipo. Solo lo tengo para este esquema porque no funciona (para mí), pero tuve que mantener un proyecto que hizo exactamente esto. Me volvió loco.
Ed S.

3
@EdS. Así que vaya a sus opciones en vs y apague las regiones. Problema resuelto.
Andy

¿Por qué sus objetos tienen métodos de guardar? :(
TheCatWhisperer

10

El uso de #regionbloques para hacer que una clase muy grande sea legible suele ser una señal de violación del Principio de responsabilidad única. Si se están utilizando para agrupar el comportamiento, entonces también es probable que la clase esté haciendo demasiado (una vez más violando SRP).

Siguiendo con la línea de pensamiento "olor a código", los #regionbloques no son olores de código en sí mismos, sino que son más "Febreze for code" en el sentido de que intentan ocultar olores. Si bien los he usado una tonelada en el pasado, a medida que comienzas a refactorizar, comienzas a ver menos porque terminan sin esconderse mucho.


5

La palabra clave aquí es "juicioso". Es difícil imaginar un caso en el que poner una región dentro de un método sea juicioso; eso es muy probable que sea código oculto y pereza. Sin embargo, puede haber buenas razones para tener algunas regiones aquí y allá en el código.

Si hay muchas regiones, creo que es un olor a código. Las regiones son a menudo un indicio de un posible lugar para futuras refactorizaciones. Muchas regiones significan que alguien nunca está captando la indirecta.

Usados ​​juiciosamente, proporcionan un buen punto medio entre la estructura de una sola clase con muchos métodos y la estructura de muchas clases con solo unos pocos métodos en cada uno. Son más útiles cuando una clase comienza a acercarse al punto en el que debería refactorizarse en varias clases, pero aún no está allí. Al agrupar métodos relacionados, facilito más adelante extraer un conjunto de métodos relacionados en su propia clase si continúan creciendo en número. Por ejemplo, si tengo una clase que se acerca a las 500 líneas de código, ese conjunto de métodos que usan 200 líneas de código en total reunidas en una región es probablemente una buena pieza para refactorizar de alguna manera, y esa otra región con 100 líneas de código en su Los métodos también pueden ser un buen objetivo.

Otra forma en que me gusta usar regiones es reducir uno de los efectos negativos de refactorizar un método grande: muchos métodos pequeños, concisos y fácilmente reutilizables por los que un lector tiene que desplazarse para llegar a otro método mayormente no relacionado. Una región puede ser una buena manera de metaencapsular un método y sus ayudantes para los lectores, por lo que alguien que esté trabajando con un aspecto diferente de la clase puede colapsarlos y descartar rápidamente esa parte del código. Por supuesto, esto solo funciona si sus regiones están realmente bien organizadas y esencialmente se utilizan como otra forma de documentar su código.

En general, encuentro que las regiones me ayudan a mantenerme organizado, me ayudan a "documentar" mi código y me ayudan a encontrar lugares para refactorizar mucho antes que si no uso regiones.


4

Utilizo principalmente regiones para clases de servidor CRUD para organizar los diversos tipos de operaciones. Incluso entonces, con gusto podría ir sin ellos.

Si se usa ampliamente, levantaría una bandera roja. Estaría atento a las clases que tienen demasiada responsabilidad.

En mi experiencia, un método con cientos de líneas de código es definitivamente un olor.


4

Mi regla general es: si tiene más de 5 regiones en un archivo, es un olor a código

Es decir, podría estar bien delinear el campo, los métodos, las propiedades y los constructores, pero si está comenzando a ajustar cualquier otro método en una región propia, algo está muy mal

... y sí, he estado en muchos proyectos donde ese es el caso, a menudo debido a los estándares de codificación deficientes, la generación de código o ambos. Se vuelve rápido tener que alternar todos los esquemas en Visual Studio para obtener una buena visión general del código.


4

LAS REGIONES TIENEN SU USO

Los he usado personalmente para eventos de interfaz de "codificación manual" antes para aplicaciones de formularios de Windows.

Sin embargo, en mi trabajo usamos un generador de código para manejar SQL y automáticamente usa regiones para ordenar sus tipos de métodos de selección, actualización, eliminación, etc.

Entonces, aunque no los uso a menudo, están perfectamente bien para eliminar grandes fragmentos de código.


1
He usado generadores de código similares y prefiero usar clases parciales para eliminar el código generado.
Craig

Lo hacemos, las regiones están dentro del código generado para que sea más fácil de leer o depurar (si es necesario).
Ken

4

Si tiene regiones en el código IN , ciertamente tiene un problema (salvo el caso del código generado). Poner regiones en el código es básicamente decir "refactorizar esto".

Sin embargo, hay otros casos. Una que me viene a la mente que hice hace un tiempo: una mesa con un par de miles de elementos precalculados. Es una descripción de la geometría, salvo un error en la tabla, nunca habrá una ocasión para mirarlo. Claro, podría haber obtenido los datos de un recurso o similar, pero eso impediría usar el compilador para facilitar la lectura.


1
Ese es un mejor caso de uso para una clase parcial con la almacenada en un archivo separado, o tal vez un IMyDataSource inyectado con una implementación HardcodedDataSource.
Bryan Boettcher

3

En un proyecto reciente, había un método de línea 1700 con varias regiones incrustadas en él. Lo interesante es que las regiones demarcaron distintas acciones que se estaban realizando dentro del método. Pude hacer un refactor -> método de extracción en cada una de las regiones sin afectar la funcionalidad del código.

En general, las regiones utilizadas para ocultar el código de la placa de la caldera son útiles. Aconsejaría no usar regiones para ocultar propiedades, campos y similares, porque si son demasiado difíciles de ver cuando se trabaja dentro de la clase, probablemente sea una señal de que la clase debería desglosarse aún más. Pero como regla general, si está colocando una región dentro de un método, probablemente sea mejor extraer otro método que explique lo que está sucediendo que envolver ese bloque en una región.


3

¿Se pueden usar regiones en código de buena calidad? Probablemente. Apuesto a que lo son, en muchos casos. Sin embargo, mi experiencia personal me deja muy sospechoso: he visto regiones mal utilizadas casi exclusivamente. Yo diría que estoy cansado, pero aún optimista.

Puedo dividir aproximadamente el código que usa la región que he visto hasta la fecha en tres categorías:

  • Código factorizado deficientemente: la mayor parte del código que he visto usa regiones como una herramienta de factorización de los pobres. Por ejemplo, una clase que ha crecido hasta el punto en que tiene sentido especializarse para diferentes propósitos podría dividirse en regiones separadas, una para cada propósito.

  • Código escrito usando las bibliotecas incorrectas, y a veces el lenguaje incorrecto, para el dominio del problema A menudo, cuando un programador no está usando el conjunto correcto de bibliotecas para el dominio del problema, verá que el código se vuelve increíblemente detallado, con muchas pequeñas funciones auxiliares que realmente no pertenecen (probablemente pertenecen a su propia biblioteca).

  • Código escrito por estudiantes o recién graduados. Algunos programas y cursos parecen intentar inculcar a los estudiantes con el uso de regiones para todo tipo de propósitos extraños. Verá regiones que ensucian el código fuente hasta el punto donde la proporción de etiquetas de región a líneas de código está en el rango de 1: 5 o peor.


3

Yo diría que es un "olor a código".

Los antipatrones son generalmente problemas estructurales fundamentales en una pieza de software, mientras que las regiones, por sí mismas, solo causan un comportamiento desagradable en un editor. El uso de regiones no es realmente inherentemente malo, pero usarlas mucho, especialmente para ocultar fragmentos de código, puede indicar que hay otros problemas independientes y mayores que ocurren en otros lugares.


@Andrew Grimm: sí
cuál es el nombre del

3

Solo uso regiones para una cosa (al menos no puedo pensar en otros lugares donde las uso): agrupar pruebas unitarias para un método.

Por lo general, tengo una clase de prueba por clase y luego agrupo las pruebas unitarias para cada método usando regiones que tienen el nombre del método. No estoy seguro si eso es un olor a código o algo así, pero dado que la idea básica es que las pruebas unitarias no necesitan cambiar a menos que se rompan porque algo cambió en el código, me resulta más fácil encontrar todas las pruebas para un método específico bastante rápido.

Puede que haya usado regiones para organizar el código en el pasado, pero no recuerdo la última vez que lo hice. Sin embargo, me quedo con mis regiones en las clases de pruebas unitarias.


1
¿Alguna vez ha tenido pruebas que prueban más de un método?
Marcie

Realmente no entiendo la pregunta o a qué la estás apuntando. La respuesta es: No, una prueba unitaria siempre está dirigida a un solo método o más bien a un cierto aspecto de un método.
Anne Schuessler

2

Creo que son un anti patrón y francamente creo que deberían eliminarse. Pero si se encuentra en la desafortunada situación de trabajar en un lugar donde son estándar, Visual Studio ofrece una herramienta increíble para minimizar la cantidad que le gustaría vomitar cada vez que vea una región que odio #Regiones

Este complemento maximizará el tamaño de fuente de las regiones realmente pequeñas. También se expandirán para que no tenga que presionar ctr + m + l para abrir todas las regiones. No soluciona esta forma de código de cáncer, pero lo hace soportable.


0

Utilizo regiones para contener cada combinación de visibilidad y tipo de miembro. Entonces todas las funciones privadas van a una región, etc.

La razón por la que hago esto no es para poder plegar el código. Es porque tengo mi editor programado para poder insertar, por ejemplo, una referencia a un proxy:

#region "private_static_members"
 /// <summary>
 /// cache for LauncherProxy
 /// </summary>
private static LauncherProxy _launcherProxy;
#endregion

#region "protected_const_properties"
protected LauncherProxy LauncherProxy{
  get{
    if(_launcherProxy==null) {
      if (!God.Iam.HasProxy(LauncherProxy.NAME)) {
        God.Iam.RegisterProxy(new LauncherProxy());
      }
      _launcherProxy=God.Iam.Proxy(LauncherProxy.NAME) as LauncherProxy;
    }
    return _launcherProxy;
  }
}
#endregion

en el código y haga que cada parte esté perfectamente metida en la región adecuada.

En este caso, la macro analizaría mi proyecto, me daría un cuadro de lista de proxies e inyectaría el código para el que quiero. Mi cursor ni siquiera se mueve.

Al comienzo de aprender C #, había considerado el uso de regiones para mantener la comunidad en común, pero esa es una propuesta impredecible porque no es una relación uno a uno en todo momento. Quién quiere preocuparse por un miembro utilizado por dos regiones, o incluso comenzar a dividir las cosas en esos términos.

El único otro tipo de segregación son los métodos: dividiré los métodos en Comandos, Funciones y Controladores, para tener una región para los comandos públicos, privados, etc., etc.

Esto me da granularidad, pero es una granularidad consistente e inequívoca en la que puedo confiar.


-1 tan pronto como obtenga 125 puntos para votar a favor. Está agregando líneas de código innecesarias. POR QUÉ POR QUÉ POR QUÉ pondrías una región alrededor de una propiedad ... if (God.Iam.AbusingRegions () == true) myName = "Mark"
DeadlyChambers

1
@DeadlyChambers La razón se indica en el segundo párrafo: estoy usando macros de editor para inyectar patrones de código comunes en el archivo, las regiones ayudan a mantener el archivo estructurado para que se agrupen elementos similares. No estoy poniendo una región alrededor de una propiedad singular, pero todas las propiedades caen en una región designada dependiendo de sus atributos "protected_const_properties". ¿Leíste la publicación?
Mark

1
Probablemente pueda refactorizar eso en: LauncherProxy protegido LauncherProxy => God.Iam.GetOrAddProxy <LauncherProxy> (ref _launcherProxy); y ahora no necesitas región. También _launcherProxy puede renombrarse como _launcherProxyCache para que no necesite región ni comentarios allí.
aeroson

0

Las regiones son expresiones de preprocesador; en otras palabras, el compilador las trata como comentarios y básicamente las ignora. Son puramente una herramienta visual utilizada en Visual Studio. Por lo tanto, #region no es realmente un olor a código, porque simplemente no es código. El código de olfato es más bien el método de 800 líneas que tiene muchas responsabilidades diferentes incrustadas, etc. Entonces, si ve 10 regiones en un método, probablemente se esté utilizando para ocultar un código de olfato. Una vez dicho esto, los he visto utilizados de manera extremadamente efectiva para hacer que una clase sea más agradable a la vista y más navegable, ¡también en una clase muy bien escrita y estructurada!


0

Las regiones eran una idea organizativa ingeniosa, pero no tuvieron en cuenta algunas tendencias de los desarrolladores para querer sobrecategorizar todo, y en general innecesarias de acuerdo con la mayoría de las prácticas modernas de OOP ... son un "olor", en el sentido de que su uso a menudo indica que su clase / método es demasiado grande y debe ser refactorizado, ya que probablemente está violando la "S" de los principios SÓLIDOS ... pero como cualquier olor, no necesariamente significa que algo va mal.

Las regiones tienen más propósito en el código funcional en lugar del código orientado a objetos, IMO, donde tiene largas funciones de datos secuenciales que tiene sentido dividir, pero ha habido ocasiones en que personalmente las he usado en C #, y casi siempre enfóquese en el código que no necesita / desea mirar. Para mí, estas eran generalmente constantes de cadena SQL sin procesar en la base de código utilizada para NPoco o sus variantes. A menos que realmente te importe cómo llegan los datos para completar el objeto POCO a través de tu ORM, estos fueron completamente inútiles de ver ... y si te importaba, ¡oye, solo expande la región y BAM! Más de 150 líneas de alguna consulta SQL complicada para su placer visual.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.