#Regions são antipadrão ou cheiro de código?

266

O C # permite o uso de #region/ #endregionkeywords para tornar áreas de código recolhíveis no editor. Sempre que faço isso, faço isso para ocultar grandes pedaços de código que provavelmente poderiam ser refatorados para outras classes ou métodos. Por exemplo, vi métodos que contêm 500 linhas de código com 3 ou 4 regiões apenas para torná-lo gerenciável.

Então, o uso criterioso das regiões é um sinal de problemas? Parece ser assim para mim.

Craig
fonte
9
FYI: O CodeMap praticamente elimina as necessidades de regiões. visualstudiogallery.msdn.microsoft.com/… - Clique e o levará ao método / atributo / qualquer que seja. Eu uso todos os dias e é incrível o quanto você ganha em produtividade e também em termos cognitivos. Você obtém uma visão mais clara da classe.
7
Alguém pode fazer deste um wiki? Não há resposta certa ou errada para essa pergunta (bem, dentro da razão), é quase completamente subjetiva.
Ed S.
6
Pelo que vale, Jeff Atwood os odeia . Ele argumenta que eles ocultam códigos ruins.
5132 Brian
3
Code cheiro é um desenvolvedor que não toma banho e não usa desodorante!
Marko
5
Regiões cuidadosamente elaboradas em código fedorento é o que um pouco do Febreeze faz em um sofá duro. Torna-o suportável até encontrar o (tempo) dinheiro para substituí-lo.
Newtopian

Respostas:

285

Um cheiro de código é um sintoma que indica que há um problema no design que potencialmente aumentará o número de bugs: esse não é o caso de regiões, mas as regiões podem contribuir para a criação de odores de código, como métodos longos.

Desde a:

Um antipadrão (ou antipadrão) é um padrão usado em operações sociais ou de negócios ou engenharia de software que pode ser comumente usado, mas é ineficaz e / ou contraproducente na prática

regiões são anti-padrões. Eles exigem mais trabalho que não aumente a qualidade ou a legibilidade do código, o que não reduz o número de bugs e que só pode tornar o código mais complicado de refatorar.

Não use regiões dentro de métodos; refatorar

Os métodos devem ser curtos . Se houver apenas dez linhas em um método, você provavelmente não usaria regiões para ocultar cinco delas ao trabalhar em outras cinco.

Além disso, cada método deve fazer uma única coisa . As regiões, por outro lado, pretendem separar coisas diferentes . Se o seu método faz A e B, é lógico criar duas regiões, mas essa é uma abordagem errada; em vez disso, você deve refatorar o método em dois métodos separados.

O uso de regiões nesse caso também pode dificultar a refatoração. Imagine que você tem:

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
}

Colapsar a primeira região a se concentrar na segunda não é apenas arriscado: podemos facilmente esquecer a exceção que interrompe o fluxo (poderia haver uma cláusula de guarda com uma returnalternativa, que é ainda mais difícil de detectar), mas também teria um problema se o código deve ser refatorado desta maneira:

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
}

Agora, as regiões não fazem sentido e você não pode ler e entender o código na segunda região sem examinar o código na primeira.

Outro caso que vejo às vezes é 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
}

É tentador usar regiões quando a validação de argumentos começa a abranger dezenas de LOC, mas existe uma maneira melhor de resolver esse problema: aquele usado pelo código-fonte do .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)
{
    ...
}

Não use regiões fora dos métodos para agrupar

  • Algumas pessoas as usam para agrupar campos, propriedades, etc. Essa abordagem está errada: se o seu código for compatível com StyleCop, os campos, propriedades, métodos privados, construtores, etc. já estarão agrupados e fáceis de encontrar. Caso contrário, é hora de começar a pensar em aplicar regras que garantam uniformidade em toda a sua base de código.

  • Outras pessoas usam regiões para ocultar muitas entidades semelhantes . Por exemplo, quando você tem uma classe com cem campos (que cria pelo menos 500 linhas de código se você contar os comentários e os espaços em branco), poderá ficar tentado a colocar esses campos em uma região, recolhê-los e esquecê-los. Novamente, você está fazendo errado: com tantos campos em uma classe, você deve pensar melhor sobre o uso de herança ou dividir o objeto em vários objetos.

  • Finalmente, algumas pessoas são tentadas a usar regiões para agrupar coisas relacionadas : um evento com seu delegado ou um método relacionado ao IO com outros métodos relacionados ao IO etc. No primeiro caso, torna-se uma bagunça difícil de manter , Leia e compreenda. No segundo caso, o melhor design provavelmente seria criar várias classes.

Existe um bom uso para regiões?

Não . Havia um uso herdado: código gerado. Ainda assim, as ferramentas de geração de código precisam usar classes parciais. Se o C # tem suporte para regiões, é principalmente porque esse legado é usado e porque agora muitas pessoas usavam regiões em seu código, seria impossível removê-las sem quebrar as bases de código existentes.

Pense nisso como sobre goto. O fato de a linguagem ou o IDE suportar um recurso não significa que ele deva ser usado diariamente. A regra StyleCop SA1124 é clara: você não deve usar regiões. Nunca.

Exemplos

Atualmente, estou revisando o código do meu colega de trabalho. A base de código contém muitas regiões e é realmente um exemplo perfeito de como não usar regiões e por que regiões levam a códigos incorretos. aqui estão alguns exemplos:

4 000 monstro LOC:

Li recentemente em algum lugar no Programmers.SE que quando um arquivo contém muitos usings (após executar o comando "Remover usos não utilizados"), é um bom sinal de que a classe dentro desse arquivo está fazendo muito. O mesmo se aplica ao tamanho do próprio arquivo.

Ao revisar o código, deparei-me com um arquivo LOC de 4.000. Parecia que o autor desse código simplesmente copiou e colou o mesmo método de 15 linhas centenas de vezes, alterando levemente os nomes das variáveis ​​e o método chamado. Um regex simples permitiu cortar o arquivo de 4.000 LOC para 500 LOC, apenas adicionando alguns genéricos; Tenho certeza de que, com uma refatoração mais inteligente, essa classe pode ser reduzida a algumas dezenas de linhas.

Ao usar regiões, o autor encorajou-se a ignorar o fato de que o código é impossível de manter e mal escrito e a duplicar fortemente o código em vez de refatorá-lo.

Região "Fazer A", Região "Fazer B":

Outro excelente exemplo foi um método de inicialização de monstros que simplesmente executava a tarefa 1, depois a tarefa 2, depois a tarefa 3, etc. Havia cinco ou seis tarefas totalmente independentes, cada uma inicializando algo em uma classe de contêiner. Todas essas tarefas foram agrupadas em um método e agrupadas em regiões.

Isso tinha uma vantagem:

  • O método era bem claro de entender, observando os nomes das regiões. Dito isto, o mesmo método, uma vez refatorado, seria tão claro quanto o original.

Os problemas, por outro lado, eram múltiplos:

  • Não era óbvio se havia dependências entre as regiões. Felizmente, não houve reutilização de variáveis; caso contrário, a manutenção poderia ser um pesadelo ainda mais.

  • O método era quase impossível de testar. Como você saberia facilmente se o método que faz vinte coisas de cada vez faz corretamente?

Região de campos, região de propriedades, região de construtor:

O código revisado também continha muitas regiões, agrupando todos os campos, todas as propriedades, etc. Isso tinha um problema óbvio: crescimento do código-fonte.

Quando você abre um arquivo e vê uma lista enorme de campos, você está mais inclinado a refatorar a classe primeiro e depois trabalhar com o código. Com as regiões, você tem o hábito de recolher coisas e esquecê-las.

Outro problema é que, se você fizer isso em qualquer lugar, estará criando regiões de um bloco, o que não faz sentido. Na verdade, esse foi o caso no código que revi, onde havia muitos que #region Constructorcontinham um construtor.

Finalmente, campos, propriedades, construtores etc. já devem estar em ordem . Se eles são e correspondem às convenções (constantes começando com uma letra maiúscula, etc.), já está claro onde o tipo de elemento para e o outro começa, para que você não precise criar regiões explicitamente para isso.

Arseni Mourzenko
fonte
13
Eu acho que existem pelo menos alguns usos defensáveis ​​de #regions - por exemplo, colapso de cláusulas de guarda (verificação de parâmetros de entrada) que, se deixados sem colapso, diminuem a essência ou a "carne" do método. Outro exemplo é o tratamento de exceções nos limites da API; muitas vezes você não deseja impactar o rastreamento da pilha chamando outros métodos para quebrar a exceção; portanto, você tem várias linhas de código para quebrar e mostrar novamente. Geralmente, esse código também não é relevante e pode ser recolhido com segurança.
Daniel B
9
Verificação da realidade. Eu já vi várias regiões entre métodos que foram úteis. Quando você tem um método de várias centenas de linhas com lógica de controle aninhada com dezenas a centenas de linhas com algumas delas - graças a Deus o idiota pelo menos colocou em regiões.
Radarbob 27/03
37
@radarbob: em resumo, as regiões são úteis no código de baixa qualidade que não deveria existir em primeiro lugar.
Arseni Mourzenko 28/03
41
-1 (se eu tivesse reputação). Mesmo que os membros do seu tipo sejam bem organizados e separados, pode haver muitos deles. As regiões evitam que você tenha que percorrer 10 ou 12 propriedades e os getters e setters associados apenas para chegar ao método em que deseja trabalhar. A única alternativa é recolher todas as suas propriedades individualmente, o que não é algo de que eu sou fã. A funcionalidade de mostrar / ocultar em grande escala que as regiões fornecem é extremamente útil. Eu concordo com as regiões intra-método.
Asad Saeeduddin
14
Não concordo totalmente com esta resposta: o fedor e a região do código não têm nada a ver um com o outro. Se seu código fede, fede com ou sem regiões. O modo como uso as regiões é segregar minhas classes em regiões. Geralmente, mantenho o mesmo padrão: Propriedades Públicas, Métodos Públicos, Campos Privados, Métodos Privados. Esse é o único uso para o qual eu teria regiões. Além disso, você provavelmente está quebrando o principal do SRP em seu código.
Alexus19
113

É incrível para mim quantas pessoas odeiam regiões tão apaixonadamente!

Eu concordo completamente com muitas de suas objeções: colocar código em um #regionpara ocultá-lo é uma coisa ruim. Dividir uma classe em #regionsquando deve ser refatorada em classes separadas é claramente um erro. Usar um #regionpara incorporar informações semânticas redundantes é, bem, redundante.

Mas nenhuma dessas coisas significa que há algo inerentemente errado em usar regiões no seu código! Só posso supor que as objeções da maioria das pessoas vêm de trabalhar em equipes em que outras pessoas estão inclinadas a usar recursos IDE como este incorretamente. Tenho o luxo de trabalhar primária sozinho e aprecio a maneira como as regiões ajudaram a organizar meu fluxo de trabalho. Talvez seja o meu transtorno obsessivo-compulsivo, mas não gosto de ver um monte de código na tela de cada vez, por mais organizado e elegante que seja. Separar as coisas em regiões lógicas me permite recolher o código que não me interessa trabalhar no código que façose importar. Não estou ignorando código mal escrito, não faz sentido refatá-lo mais do que é, e a organização "meta" adicional é descritiva, e não inútil.

Agora que passei mais tempo trabalhando em C ++, programando mais diretamente a API do Windows, me vejo desejando que o suporte para regiões fosse tão bom quanto para C #. Você poderia argumentar que o uso de uma biblioteca GUI alternativa tornaria meu código mais simples ou mais claro, eliminando assim a necessidade de obter ruído de código irrelevante na tela, mas tenho outros motivos para não querer fazer isso. Sou proficiente o suficiente com meu teclado e IDE para que a expansão / recolhimento do código subdividido em regiões leve menos de uma fração de segundo. O tempo que economizo em inteligência, tentando limitar meu foco consciente apenas ao código em que estou trabalhando atualmente, vale mais que isso. Tudo pertence a uma única classe / arquivo, mas nem tudo pertence à minha tela ao mesmo tempo.

O ponto é que usar #regionspara separar e dividir logicamente seu código não é uma coisa ruim a ser evitada a todo custo. Como Ed aponta, não é um "cheiro de código". Se seu código cheirar, você pode ter certeza de que ele não vem das regiões, mas de qualquer código que você tentou enterrar nessas regiões. Se um recurso ajuda você a ser mais organizado ou a escrever um código melhor, eu digo que o use . Se isso se tornar um obstáculo, ou se você o usar incorretamente, pare de usá-lo. Se o pior acontecer, e você for forçado a trabalhar em uma equipe com pessoas que o usam, memorize o atalho do teclado para desativar o esquema de código: Ctrl+ M, Ctrl+P. E pare de reclamar. Às vezes, sinto que essa é outra maneira pela qual aqueles que querem ser vistos como programadores "verdadeiros" e "hardcore" gostam de tentar provar a si mesmos. Não é melhor evitar regiões do que evitar a coloração de sintaxe. Isso não faz de você um desenvolvedor mais machista.

Tudo isso dito, regiões dentro de um método são pura bobagem. Sempre que você desejar fazer isso, refatorá-lo para um método separado. Sem desculpas.

Cody Gray
fonte
9
Bem dito. O uso de regiões para organização não é mais prejudicial do que alternar a opção "exibir espaço em branco" do IDE. É uma preferência pessoal.
Josh
24
Trabalhando no WPF com ViewModels que possuem 10 ou 20 propriedades que simplesmente agrupam propriedades no meu modelo, eu amo regiões - eu posso simplesmente colocar essas propriedades em uma região (elas nunca precisam ser tocadas) e manter meus olhos no código relevante .
Kirk Broadhurst
4
Concordo plenamente. No .NET 2.0, as propriedades têm cerca de 8 a 10 linhas. Quando você tem mais de 20 propriedades em uma classe, elas ocupam muito espaço. As regiões são perfeitas para colapsá-las.
9117 Kristof Claes
6
@ Kristof: assim como as propriedades no .NET 4.0 que fazem validação simples de entrada. As propriedades automáticas simplesmente não foram tão mágicas para meus propósitos.
Cody Grey
8
Estou disposto a apostar na minha bola esquerda que as pessoas que odeiam regiões nunca desenvolveram um aplicativo WPF ou nunca usaram realmente as funcionalidades de definição do WPF, como vinculação de dados e vinculação de comando. Basta configurar seu código para fazer com que esses trabalhos ocupem muito espaço e você geralmente não precisa vê-los novamente.
L46kok #
70

Primeiro, eu não aguento mais o termo "cheiro de código". É usado com muita frequência e é usado na maioria das vezes por pessoas que não conseguiam reconhecer um bom código se ele o mordesse. Enfim...

Eu pessoalmente não gosto de usar muitas regiões. Isso dificulta o acesso ao código, e o código é o que me interessa. Gosto de regiões quando tenho um grande pedaço de código que não precisa ser tocado com muita frequência. Além disso, eles parecem me atrapalhar, e regiões como "Métodos Privados", "Métodos Públicos" etc. etc. me deixam louco. Eles são parecidos com comentários da variedade i++ //increment i.

Eu também acrescentaria que o uso de regiões não pode realmente ser um "antipadrão", pois esse termo é comumente usado para descrever padrões de lógica / design de programa, não o layout de um editor de texto. Isso é subjetivo; Use o que funciona para você. Você nunca vai acabar com um programa impossível de manter devido ao uso excessivo de regiões, que é o objetivo dos anti-padrões. :)

Ed S.
fonte
2
Normalmente, eu recomendaria o comentário de cheiro de código, mas, neste caso, é exatamente preciso. Não código não pode ser um cheiro de código. +2!
7
Haha, bem, não quero dizer que o termo "cheiro de código" não possa ser usado com precisão. Pode, mas eu vejo tantas coisas nos dias de hoje que minha reação imediata é apenas um aborrecimento, especialmente quando vem de pessoas que estão apenas repetindo o que ouvem sem entender ou pensar criticamente. Declarações como "mais de 5 variáveis ​​locais em uma função são um cheiro de código" mostram apenas a pouca experiência que essa pessoa realmente tem.
Ed.
13
Não sei se entendi seu comentário sobre cheiros de código. O cheiro do código não indica que há um problema, apenas pode haver um problema.
Craig
7
+1 por defender o termo cheiro de código. Fiquei de saco cheio quando vi uma postagem afirmando que métodos privados eram um cheiro de código. Mas, no geral, eu discordo de sua aversão por regiões. Eu sou facilmente distraído. Na verdade, eu adoraria se o VS tivesse um modo VB4 onde você pudesse exibir apenas um único método de cada vez.
Josh
7
Só queria gritar e dizer que o mau uso de uma metáfora perfeitamente boa não deveria desvalorizá-la. O "cheiro do código" é uma ótima metáfora, que é instantaneamente entendida, lembrada e usada com facilidade. Ainda existem muitos lugares em que a aplicação da metáfora do "cheiro do código" ainda é a melhor maneira de se expressar.
Eric Rei
23

Sim regiões são um cheiro de código!

Ficaria feliz em ver regiões removidas do compilador por completo. Todo desenvolvedor cria seu próprio esquema inútil de preparação que nunca será de valor para outro programador. Eu tenho tudo a ver com programadores que querem decorar e embelezar seu bebê, nada a ver com qualquer valor real.

Você pode pensar em um exemplo em que "nossa, eu gostaria que meu colega usasse algumas regiões aqui!"?

Embora eu possa configurar meu IDE para expandir automaticamente todas as regiões, elas ainda são dolorosas e prejudicam a leitura do código real.

Eu realmente me importaria menos se todos os meus métodos públicos fossem agrupados ou não. Parabéns, você sabe a diferença entre uma declaração de variável e inicialização, não é necessário exibi-la no código!

Preparação sem valor!

Além disso, se o seu arquivo precisar e 'arquitetura da informação' através do uso de regiões, você poderá combater o problema principal: Sua classe é muito grande! Dividir em partes menores é muito mais benéfico e, quando feito corretamente, adiciona verdadeira semântica / legibilidade.

Joppe
fonte
#Regions fazem parte do compilador? Eu pensei que eles eram apenas uma diretiva para o IDE que poderia ser ignorada.
Steve Rukuts
2
O compilador precisaria ignorá-los ao analisar seu código C #. Se não os ignora, vomitaria neles. Eu falo assim.
Joppe
1
"Você pode pensar em um exemplo em que" nossa, eu gostaria que meu colega usasse algumas regiões aqui! "?" Sim muito mesmo. Quando eu tenho uma classe com métodos privados e públicos, eu os divido em regiões porque, ao refatorar os métodos públicos, você não precisa necessariamente tocar no código privado e vice-versa.
Anshul
Você obviamente nunca viu código terceirizado. Muitas vezes as regiões teriam sido ótimas em código terceirizado. Mesmo que o código seja péssimo, pelo menos teria sido muito mais fácil compreender se fosse agrupado em algum sentido lógico. Embora, se o código não for lógico, as regiões também não seriam, provavelmente o tornaria pior. As regiões são ótimas quando usadas corretamente.
Nickmccomb
15

Eu pessoalmente uso as regiões como uma maneira de agrupar vários tipos de métodos ou partes de código.

Portanto, um arquivo de código pode ficar assim ao abri-lo:

  • Propriedades Públicas
  • Construtores
  • Métodos de salvamento
  • Métodos de edição
  • Métodos de Auxiliar Privado

Eu não coloco regiões dentro de métodos. IMHO que é um sinal de cheiro de código. Uma vez me deparei com um método com mais de 1200 linhas e cinco regiões diferentes. Foi uma visão assustadora!

Se você o estiver usando como uma maneira de organizar seu código de maneira a tornar mais rápido encontrar coisas para outros desenvolvedores, não acho que seja um sinal de problema. Se você estiver usando para ocultar linhas de código dentro de um método, eu diria que é hora de repensar esse método.

Tyanna
fonte
14
Ugh. Eu sei que esse é um tópico subjetivo, mas, cara, eu realmente não suporto esse esquema. Na minha experiência, a 'organização' adicionada não ajuda em nada e apenas torna a navegação no código uma dor no pescoço. Também prefiro métodos de agrupamento, não apenas por modificador de acesso, mas por responsabilidade lógica. Para a interface pública, normalmente agrupo cada método / propriedade, mas muitas vezes um método protegido pode chamar uma função auxiliar privada e, nesse caso, eu prefiro muito a função auxiliar (que só pode ser usada lá) estar acima ou abaixo da função método que chama.
Ed S.
3
@ Ed S. - é por isso que eu disse "pode ​​parecer". É muito subjetivo. Não estou dizendo que todo arquivo deve ser assim. Eu ficaria surpreso se eles fizessem. Apenas um exemplo sobre um tópico complexo. :)
Tyanna
Ah, eu sei, como eu disse; é subjetivo. Tudo o que funciona para você / sua equipe. Eu só tenho esse esquema porque não funciona (para mim), mas tive que manter um projeto que fiz exatamente isso. Isso me deixou louco.
Ed S.
3
@EdS. Portanto, entre nas opções vs e desative as regiões. Problema resolvido.
Andy Andy
Por que seus objetos têm métodos de salvamento? :(
TheCatWhisperer 17/03/2019
10

Usar #regionblocos para tornar uma classe muito grande legível geralmente é um sinal de violação do Princípio de Responsabilidade Única. Se eles estão sendo usados ​​para agrupar comportamentos, também é provável que a classe esteja fazendo muito (mais uma vez violando o SRP).

Seguindo a linha de pensamento "cheiro de código", os #regionblocos não são cheiros de código por si só, mas são mais "Febreze para código", na medida em que tentam esconder cheiros. Enquanto eu os usei muito no passado, quando você começa a refatorar, você começa a ver menos porque eles acabam não se escondendo muito.

Austin Salonen
fonte
5

A palavra-chave aqui é "criteriosa". É difícil imaginar um caso em que colocar uma região dentro de um método seja criterioso; é muito provável que oculte código e preguiça. No entanto, pode haver boas razões para ter algumas regiões aqui e ali no código de alguém.

Se existem muitas regiões, acho que é um cheiro de código. As regiões costumam ser uma sugestão de um local possível para refatoração futura. Muitas regiões significam que alguém nunca está realmente entendendo a dica.

Usados ​​criteriosamente, eles fornecem um bom meio termo entre a estrutura de uma única classe com muitos métodos e a estrutura de muitas classes com apenas alguns métodos em cada. Eles são mais úteis quando uma classe começa a se aproximar do ponto em que deve ser refatorada em várias classes, mas ainda não está lá. Ao agrupar métodos relacionados, eu facilito mais tarde extrair um conjunto de métodos relacionados para sua própria classe, se eles continuarem a crescer em número. Por exemplo, se eu tiver uma classe que se aproxima de 500 linhas de código, esse conjunto de métodos usando 200 linhas de código coletadas em uma região provavelmente é uma boa peça para refatorar de alguma forma - e essa outra região com 100 linhas de código em sua região. métodos também podem ser um bom alvo.

Outra maneira que eu gosto de usar regiões é reduzir um dos efeitos negativos da refatoração de um método grande: muitos métodos pequenos, concisos e facilmente reutilizados que um leitor precisa percorrer para chegar a outro método não relacionado. Uma região pode ser uma boa maneira de encapsular um método e seus auxiliares para os leitores, para que alguém que esteja trabalhando com um aspecto diferente da classe possa recolhê-los e descartar rapidamente essa parte do código. Obviamente, isso só funciona se suas regiões estiverem realmente bem organizadas e estiverem sendo usadas como outra maneira de documentar seu código.

Em geral, acho que as regiões me ajudam a me manter organizado, a "documentar" meu código e a encontrar lugares para refatorar muito mais cedo do que se eu não usasse regiões.

Ethel Evans
fonte
4

Uso principalmente regiões para classes de servidor CRUD para organizar os vários tipos de operações. Mesmo assim, eu poderia alegremente ficar sem eles.

Se usado extensivamente, levantaria uma bandeira vermelha. Eu estaria atento a aulas com muita responsabilidade.

Na minha experiência, um método com centenas de linhas e um código é definitivamente um cheiro.

TaylorOtwell
fonte
4

Minha regra de ouro é: se você tem mais de 5 regiões em um arquivo, é um cheiro de código

Ou seja, pode ser bom delinear campos, métodos, propriedades e construtores, mas se você estiver começando a agrupar todos os outros métodos em uma região própria, algo está seriamente errado

..e sim, já participei de muitos projetos onde esse é o caso, geralmente por causa de padrões de codificação ruins, geração de código ou ambos. É muito rápido ter que alternar todos os tópicos no visual studio para obter uma boa visão geral do código.

Homde
fonte
4

AS REGIÕES TÊM SEU USO

Eu os usei pessoalmente para eventos de interface de "codificação manual" antes para aplicativos de formulários do Windows.

No entanto, no meu trabalho, usamos um gerador de código para lidar com SQL e ele automaticamente usa regiões para classificar seus tipos de métodos de seleção, atualização, exclusão, etc.

Portanto, embora eu não os use com frequência, eles são perfeitamente adequados para remover grandes pedaços de código.

Ken
fonte
1
Eu usei geradores de código semelhantes e prefiro usar classes parciais para remover o código gerado.
Craig
Sim, as regiões estão dentro do código gerado para facilitar a leitura ou a depuração (se necessário).
Ken
4

Se você tiver regiões IN código certamente terá um problema (exceto o caso do código gerado). Colocar regiões no código é basicamente dizer "refatorar isso".

No entanto, existem outros casos. Alguém que me lembra que fiz um tempo atrás: uma mesa com alguns milhares de itens pré-calculados. É uma descrição da geometria. Com exceção de um erro na tabela, nunca haverá uma ocasião para examiná-la. Claro, eu poderia ter obtido os dados de um recurso ou algo parecido, mas isso impediria o uso do compilador para facilitar a leitura.

Loren Pechtel
fonte
1
Esse é um caso de uso melhor para uma classe parcial com a armazenada em um arquivo separado, ou talvez um IMyDataSource injetado com uma implementação HardcodedDataSource.
Bryan Boettcher
3

Em um projeto recente, havia um método de linha de 1700 com várias regiões incorporadas. O interessante é que as regiões demarced ações distintas que estavam sendo feitas dentro do método. Consegui fazer um método refactor -> extract em cada uma das regiões sem afetar a funcionalidade do código.

Em geral, as regiões usadas para ocultar o código da placa da caldeira são úteis. Eu desaconselharia o uso de regiões para ocultar propriedades, campos e afins, porque se eles forem muito difíceis de serem vistos ao trabalhar dentro da classe, provavelmente é um sinal de que a classe deve ser mais detalhada. Mas como regra geral, se você estiver colocando uma região dentro de um método, provavelmente será melhor extrair outro método que explique o que está acontecendo do que agrupar esse bloco em uma região.

Michael Brown
fonte
3

As regiões podem ser usadas em código de boa qualidade? Provavelmente. Aposto que são, em muitos casos. No entanto, minha experiência pessoal me deixa muito desconfiada - vi regiões quase exclusivamente mal utilizadas. Eu diria que estou cansado, mas ainda otimista.

Posso dividir aproximadamente o código de região que vi até agora em três categorias:

  • Código mal fatorado: a maior parte do código que eu vi usa regiões como uma ferramenta de fator pobre. Por exemplo, uma classe que cresceu a ponto de fazer sentido especializá-la para propósitos diferentes pode ser dividida em regiões separadas, uma para cada finalidade.

  • Código escrito usando as bibliotecas erradas e, às vezes, a linguagem errada, para o domínio do problema Freqüentemente, quando um programador não está usando o conjunto certo de bibliotecas para o domínio do problema, você vê o código se tornando incrivelmente detalhado - com muitas pequenas funções auxiliares que realmente não pertencem (provavelmente pertencem à sua própria biblioteca).

  • Código escrito por estudantes ou recém-formados. Alguns programas e cursos parecem tentar inculcar os alunos no uso de regiões para todos os tipos de propósitos estranhos. Você verá regiões espalhando o código-fonte até o ponto em que a proporção de tags de região e linhas de código está no intervalo de 1: 5 ou pior.

blueberryfields
fonte
3

Eu diria que é um "cheiro de código".

Antipadrões são geralmente problemas estruturais fundamentais em um software, enquanto regiões, por si só, causam um comportamento desagradável em um editor. Usar regiões não é realmente inerentemente ruim, mas usá-las bastante, especialmente para ocultar trechos de código, pode indicar que existem outros problemas independentes e maiores acontecendo em outros lugares.

whatsisname
fonte
@Andrew Grimm: yeah
whatsisname
3

Uso regiões apenas para uma coisa (pelo menos não consigo pensar em outros lugares em que as uso): agrupar testes de unidade para um método.

Normalmente, tenho uma classe de teste por classe e, em seguida, agrupo os testes de unidade para cada método usando regiões que têm o nome do método. Não tenho certeza se é um cheiro de código ou algo assim, mas como a idéia básica é que os testes de unidade não precisam ser alterados, a menos que quebrem porque algo no código mudou, fica mais fácil encontrar todos os testes para um método específico bem rápido.

Talvez eu tenha usado regiões para organizar código no passado, mas não me lembro da última vez que o fiz. Mas eu continuo com minhas regiões nas aulas de teste de unidade.

Anne Schuessler
fonte
1
Você já fez testes que testam mais de um método?
Marcie
Eu realmente não entendo a pergunta ou o que você está pretendendo. A resposta é: Não, um teste de unidade sempre é direcionado a apenas um método ou melhor, a um certo aspecto de um método.
Anne Schuessler 02/03
2

Acredito que sejam anti-padrão e, francamente, acho que eles devem ser eliminados. Mas se você estiver na situação infeliz de trabalhar em um local onde eles são um padrão, o Visual Studio oferece uma ferramenta incrível para minimizar a quantidade que você gostaria de vomitar toda vez que vir uma região que eu odeio # Regiões

Este plugin irá maximizar o tamanho da fonte das regiões muito pequenas. Eles também serão expandidos para que você não precise pressionar ctr + m + l para abrir todas as regiões. Ele não corrige essa forma de câncer de código, mas a torna suportável.

DeadlyChambers
fonte
0

Uso regiões para conter cada combinação de visibilidade e tipo de membro. Assim, todas as funções privadas vão para uma região, etc.

A razão pela qual faço isso não é para que eu possa dobrar o código. É porque eu tenho meu editor em script para poder inserir, por exemplo, uma referência a um 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

no código e coloque cada parte cuidadosamente na região apropriada.

Nesse caso, a macro analisaria meu projeto, me forneceria uma caixa de listagem de proxies e injetaria o código para o que eu quero. Meu cursor nem se move.

No começo do aprendizado do C #, eu havia considerado o uso de regiões para manter a comunalidade unida, mas essa é uma proposta de acerto e fracasso, porque não é um relacionamento individual em todos os momentos. Quem quer se preocupar com um membro usado por duas regiões, ou mesmo começar a dividir as coisas nesses termos.

O único outro tipo de segregação são os métodos - dividirei os métodos em Comandos, Funções e Manipuladores, para ter uma região para comandos públicos, privados, etc.

Isso me dá granularidade, mas é uma granularidade consistente e inequívoca em que posso confiar.

Marca
fonte
-1 assim que eu receber 125 pontos para votar. Você está adicionando linhas de código desnecessárias. Porque porque porque você colocaria uma região em torno de uma propriedade ... if (God.Iam.AbusingRegions () == true) myName = "Mark"
DeadlyChambers
1
@DeadlyChambers O motivo é exposto no segundo parágrafo - estou usando macros de editor para injetar padrões de código comuns no arquivo, as regiões ajudam a manter o arquivo estruturado para que itens semelhantes sejam agrupados. Não estou colocando uma região em torno de uma propriedade singular, mas todas as propriedades caem em uma região designada, dependendo de seus atributos "protected_const_properties". Você leu o post??
Mark
1
Você provavelmente pode refatorar isso em: LauncherProxy protegido LauncherProxy => God.Iam.GetOrAddProxy <LauncherProxy> (ref _launcherProxy); e, portanto, agora você não precisa de região. Também _launcherProxy pode ser renomeado para _launcherProxyCache, para que você não precise de região nem de comentar lá.
Aerosson
0

Regiões são expressões de pré-processador - em outras palavras, são tratadas como comentários e basicamente ignoradas pelo compilador. Eles são puramente uma ferramenta visual usada no Visual Studio. Portanto, #region não é realmente um cheiro de código, porque simplesmente não é código. O cheiro do código é bastante o método das 800 linhas, com muitas responsabilidades diferentes incorporadas, etc. Portanto, se você ver 10 regiões em um método - provavelmente está sendo usado para ocultar o cheiro do código. Dito isto, eu os vi usados ​​de maneira extremamente eficaz para tornar uma aula mais agradável aos olhos e mais navegável - em uma aula muito bem escrita e estruturada também!

BKSpurgeon
fonte
0

As regiões eram uma idéia organizacional bacana, mas não levaram em conta algumas tendências dos desenvolvedores de querer colocar categorias demais em tudo, e geralmente desnecessárias de acordo com as práticas modernas de OOP dos dias de hoje ... elas são um "cheiro", no sentido de que usá-las frequentemente indica que sua classe / método é muito grande e deve ser refatorada, pois você provavelmente está violando o "S" dos princípios do SOLID ... mas, como qualquer cheiro, não necessariamente significa algo está indo mal.

As regiões servem mais a propósito no código funcional do que no código orientado a objeto, IMO, onde você tem longas funções de dados sequenciais que faz sentido desmembrar, mas houve momentos em que eu os usei pessoalmente em c #, e eles quase sempre concentre-se no código que você não precisa / deseja ver. Para mim, essas eram geralmente constantes de string SQL brutas na base de código usada para o NPoco ou suas variantes. A menos que você realmente se importe com a forma como os dados preenchem o objeto POCO através do seu ORM, eles são completamente inúteis de se olhar ... e se você se importa, ei, basta expandir a região e o BAM! Mais de 150 linhas de algumas consultas SQL complicadas para o seu prazer.

Jeremy Holovacs
fonte