Eu sacrifico nomes de variáveis ​​mais curtos por um código "em coluna" mais longo?

17

Eu sou um programador amador em uma aula de CS tentando aprender habilidades de programação adequadas. É assim que meu código fica, as bordas se estendem para 103 colunas.

int extractMessage(char keyWord[25], char cipherText[17424],
                   int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);


    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }

Antes de eu ter nomes de variáveis ​​super longos, eu tinha coisas como i, j, k, mas meu professor insiste em que não devemos usar variáveis ​​como essa no "mundo profissional" e que mesmo variáveis ​​reduzidas como lenWord são insuficientes porque as pessoas podem assumir significa "Literatura Mundial de Lennard". Ele diz para escolher nomes de variáveis ​​significativos, mas ao fazer isso, sinto que violei a Regra de Ouro da codificação para mantê-la em 80 colunas. Como contornar isso?

RaulT
fonte
26
Continue; adicione nomes mais úteis. Você pode pensar em uma maneira de descrever cipherColumn + (rowSize*nextWord) + nextWorda deixar claro o que esse cálculo é de , por exemplo? Aposto que esse nome é mais curto que o cálculo, então você obtém um benefício de legibilidade e um comprimento de linha reduzido. Além disso, não alinhe as atribuições ou precisará movê-las todas se renomear a variável mais longa.
jonrsharpe
2
Hmm .. você está dizendo que eu deveria criar uma nova variável e armazenar o resultado de cipherColumn + (rowSize * nextWord) + nextWord para que eu possa usá-lo ainda mais? É isso que os profissionais fazem? Estou realmente perguntando
RaulT 18/03/19
8
Sim, essa é a minha sugestão. Sou profissional e é o que eu faria, então ... alguns deles, pelo menos.
jonrsharpe
11
regra de ouro é escrever um código que possa ser lido e entendido. nós escrevemos código para outras pessoas (!) não para máquinas. para máquinas existe um código de máquina. para alguns, o código que se parece com o que você descreveu (nomes de letras únicas etc.) é uma falta de respeito por outros programadores (e pelo futuro - porque você esquecerá nas próximas semanas ou meses). não há razão para manter 80 colunas, não é o MS DOS nos anos 80.
rsm
3
@stijn sim, mas é a última vez que precisamos. Assim como eu não compilo meu código c para o processador 8086 de 8 bits, caso precise armazená-lo em cartões perfurados, também não acho que o padrão stardard de 80 colunas tenha algum significado no século 21. devemos expandir essa tecnologia, não nos sentar nos anos 80 e pensar que isso nos torna hackers inteligentes. inteligente é a simplicidade, a legibilidade e a tecnologia ao máximo. temos monitores full-hd, é hora de usá-lo.
precisa

Respostas:

24

Normalmente, quando vejo código publicado aqui como o seu, edito-o, porque odiamos a rolagem horizontal. Mas como isso faz parte da sua pergunta, mostrarei a edição aqui:

int extractMessage(char keyWord[25], char cipherText[17424],
                   int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);


    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }
}

Essa pausa pode ser surpreendente, mas é mais legível do que a versão com rolagem horizontal, e é melhor do que encurtar os nomes de i, je k.

Não é que você nunca deve usar i, je k. Esses são nomes bons ao indexar 3 forloops aninhados . Mas aqui os nomes são realmente minha única pista sobre o que você esperava que estivesse acontecendo. Especialmente porque esse código não faz nada.

A melhor regra a seguir no tamanho do nome da variável é o escopo. Quanto maior a vida de uma variável, mais variáveis ​​variáveis ​​o seu nome deve competir. O nome CandiedOrange é exclusivo na troca de pilhas. Se estivéssemos em uma conversa, você poderia me chamar de "doce". Mas agora, você está em um escopo em que esse nome pode ser confundido com Candide , Candy Chiu ou Candyfloss . Portanto, quanto maior o escopo, maior o nome. Quanto menor o escopo, menor o nome.

O comprimento da linha nunca deve ditar o comprimento do nome. Se você achar que é, encontre uma maneira diferente de definir seu código. Temos muitas ferramentas para ajudá-lo a fazer isso.

Uma das primeiras coisas que procuro é barulho desnecessário para me livrar. Infelizmente, este exemplo não faz nada, por isso é um ruído desnecessário. Eu preciso de algo para trabalhar, então primeiro vamos fazer alguma coisa.

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }
    return cipherColumn;
}

Lá, agora faz alguma coisa.

Agora que faz alguma coisa, posso ver do que posso me livrar. Esse material de comprimento nem é usado. Isso continuetambém não faz nada.

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

Vamos fazer alguns ajustes menores no espaço em branco, porque vivemos em um mundo de controle de origem e é bom quando a única razão pela qual uma linha é relatada como alterada é porque ela está fazendo algo diferente, não porque parte dela teve que se alinhar em uma coluna.

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn = 0;
    int cipherColumn = 0;
    int offset = 1;
    int nextWord = 1;

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

Sim, eu sei que é um pouco menos legível, mas, caso contrário, você enlouquecerá as pessoas que usam as ferramentas vdiff para detectar alterações.

Agora vamos corrigir essas quebras de linha tolas que temos, porque estamos tentando permanecer abaixo dos limites de comprimento de linha.

int calcCipherColumn(
        char keyWord[25], 
        char cipherText[17424],
        int rowSize, 
        char message[388]
) {
    int keyColumn = 0;
    int keyOffset = 1;

    int nextWord = 1;
    int cipherColumn = 0;
    int cipherOffset = (rowSize * nextWord) + nextWord;

    char key = keyWord[keyColumn];
    char keyNext = keyWord[keyColumn + keyOffset];

    while (key != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyNext != cipherText[cipherColumn + cipherOffset]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

Agora, a lógica do loop está focada no que muda no loop. De fato, tudo, exceto cipherColumnpoderia ser marcado final. E ei! Olhe para isso. Agora temos espaço para fazê-lo.

Tudo o que fiz foi adicionar mais 3 variáveis, renomear uma e reorganizá-las um pouco. E o resultado aconteceu para tornar as linhas curtas o suficiente para caber sem quebras de linha !=.

Claro que os nomes keye keyNextnão são tão descritivos, mas cada um deles é usado apenas uma vez, não dura tanto tempo e, o mais importante, não está fazendo nada tão interessante no circuito. Então eles não precisam ser. Ao introduzir variáveis ​​extras, agora temos espaço para prolongar seus nomes, se necessário. As coisas mudam, então, eventualmente, podemos precisar. Se o fizermos, é bom termos espaço para respirar.

Também tomei a liberdade de mostrar a você o estilo variante de Jeff Grigg, no formato 6 , de definir parâmetros de entrada para respeitar as restrições de comprimento de linha.

candied_orange
fonte
Uau, isso é descritivo! Sim, eu sei que o código realmente não faz nada, provavelmente eu deveria ter postado mais do que um pequeno trecho dele, mas acho que estava tentando ter uma idéia geral do que os profissionais fazem em relação ao comprimento da coluna de código e nomes de variáveis, mas sua resposta mostrou algumas mudanças muito boas que definitivamente implementarei em meus códigos a partir de agora! Mais uma pergunta que tenho é: onde você acha adequado fazer quebras de linha? Antes dos operadores? Existe um "padrão" aceito?
RaulT 18/03/19
1
O @RaulT passa algum tempo lendo a base de código em que está trabalhando. Ele dará uma idéia do que você pode usar que não surpreenderá outros codificadores. Siga um documento de normas, se você tiver um. Mas o melhor é perguntar a outros programadores e perguntar o quão legível é o seu material. Ah, e confira codereview.stackexchange.com
candied_orange 18/17/17
Eu adicionaria um comentário abaixo em cipherOffset e explicaria o cálculo porque essa fórmula não é óbvia. Você esquecerá o porquê em três semanas.
28617 Nelson Nelson
15

Outros já fizeram algumas sugestões úteis, deixe-me resumir:

  • 80 caracteres por linha podem ter sido uma regra de ouro nos anos 80. Atualmente, a maioria das pessoas concorda que 100 a 130 caracteres estão bem.
  • Use quebras de linha dentro de suas expressões.
  • Divida expressões longas introduzindo resultados intermediários.

Eu gostaria de acrescentar outra recomendação: não seja dogmático sobre nomes longos! Quanto maior o escopo de uma variável, mais informações devem ser colocadas em seu nome. E geralmente é uma boa idéia manter o escopo das variáveis ​​pequeno.

Por exemplo, se você possui uma variável para a coluna da tabela de criptografia de palavras-chave e fica claro que existe apenas uma tabela usada no escopo da variável, é bom chamá-la columnou mesmo col. Se o escopo for maior e houver várias tabelas envolvidas, faz sentido chamá-lo keyWordEncryptionTableColumn.

Outro exemplo: se você tem um loop com um corpo que abrange duas ou três linhas e precisa usar um índice para acessar elementos de uma matriz, não há nada de errado em chamar o índice i. Nesse contexto, é muito mais legível (pelo menos para a maioria das pessoas) do que, digamos arrayIndexOfMyVerySpecialDataSet.

Frank Puffer
fonte
1
Eu concordo com você responder. No trabalho, usamos 80 caracteres / linha para c / c ++ por motivos herdados e porque usamos revisão. Para caracteres / linha C # 100, às vezes eu quebrei a regra e fui um pouco acima de 100 para manter a legibilidade.
peval27
Uau, que ótima resposta !! Todas essas respostas foram ótimas, obrigado pela ajuda, eu agradeço!
RaulT
Concordo plenamente em pressionar a ideia de que 80 linhas de caracteres estão desatualizadas. Ele ainda se aplica a determinados projetos e locais (principalmente por consistência), mas para muitos é simplesmente desnecessário. Muitos desenvolvedores estão usando algo como Visual Studio ou IntelliJ em um monitor completo e têm um segundo monitor para outras coisas (documentação, etc.). Eles têm, portanto, muitas propriedades de tela para seu código. Se você estiver usando apenas 80 caracteres por linha, provavelmente terá muito espaço não utilizado. E o limite de 80 caracteres machuca você! Especialmente quando você considera que a lib padrão pode forçar nomes longos.
Kat
1
Meu argumento é que, em alguns idiomas, não há como evitar o fato de 80 caracteres ser uma grande limitação. Então, por que tê-lo desnecessariamente? Ele também menciona que praticamente todos os grandes editores de nomes e IDEs têm excelente quebra de linha inteligente nos dias de hoje, o que permite que você não limite o comprimento das linhas. Você pode permitir que os comprimentos das linhas sejam o que o leitor puder ver. Eles podem redimensionar sua janela para obter um resultado mais ideal. Eu pessoalmente achei essa abordagem ideal algumas vezes. E ainda estou desapontado com o funcionamento desse invólucro suave.
21417 Kat
Sempre que você usa nomes simples de variáveis, DEVE 100% de certeza do escopo. Passei três horas para aprender sobre o fechamento do JavaScript.
28617 Nelson Nelson
3

Eu geralmente concordo com você professor. No entanto, se você tiver uma variável que usará muito em um pedaço grande de código com falha, pode ser melhor usar um formato abreviado para isso depois de ser explícito sobre seu significado. Como quando você tem muitas expressões e atribuições aritméticas complexas, elas não são lidas muito bem com nomes de variáveis ​​longos.

Sobre o esboço:

ExtractMessage(char keyWord[25], char cipherText[17424],
               int rowSize, char message[388]) 

Isso não serve para nada, apenas limitar o comprimento da linha não a torna mais legível. Se você quiser que isso seja legível, faça o seguinte:

ExtractMessage(
  char keyWord[25],
  char cipherText[17424],
  int rowSize,
  char message[388]
  )
{

E então você pode até alinhar identificadores de tipo (adicione um espaço após int). No entanto, seja cuidadoso / restritivo ao descrever initalizações ou listas de argumentos como esta:

int keyColumn    = 0;
int cipherColumn = 0;
int offset       = 1;
int nextWord     = 1;

O problema é que, quando você altera um nome ou adiciona uma variável, pode ser necessário reformatar o bloco inteiro para manter a aparência bonita. Não é tanto para o trabalho quanto para as mudanças sem sentido que você introduziria, seria horrível em um sistema de controle de versão. Seu colega de trabalho veria que você alterou o arquivo e faria uma comparação com a versão anterior para ver o que você fez. Então todas as linhas acenderiam como mudadas, obscurecendo a mudança real. Isso dependeria um pouco da qualidade da ferramenta de comparação usada, como isso seria realmente ruim, mas, em geral, não é uma boa idéia tornar o código muito pessoal e / ou ter a formatação de uma linha dependente da outra.

Às vezes, esboçar pode servir a um propósito; se você tiver dezenas de linhas consecutivas quase iguais, será fácil identificar onde elas são diferentes se você as esboçar.

Observe que um local de trabalho pode ter alguma formatação automatizada que irá erradicar qualquer formatação sofisticada que você faça no seu código antes de enviá-lo ao sistema de controle de versão.

Martin Maat
fonte
1
Pessoalmente, o primeiro bloco de código na sua resposta é muito mais legível para mim do que o segundo.
Route de milhas
1
nunca faça o terceiro, é um pesadelo de manutenção mantê-lo assim.
jwenting
3

Isenção de responsabilidade: estou exagerando um pouco aqui para deixar meu argumento mais claro. Portanto, tome qualquer superlativo com um grão de sal.

Seu professor está 100% certo: não há mais "regra de ouro" com cerca de 80 caracteres (a menos que você esteja escrevendo código linux). Essa regra foi estabelecida por causa do tamanho dos terminais da época, mas hoje em dia, você coloca facilmente mais de 150 caracteres na janela do enditor. E mesmo se você exceder esse limite, esperamos que o editor enrole a linha de maneira suave, para que você não precise rolar.E o único motivo para não exceder 80 caracteres foi a necessidade de rolagem .

Dito isto, é realmente necessário não deixar suas linhas crescerem indefinidamente. Quanto maior a linha, mais difícil se torna para um ser humano analisar. Mas nomes curtos de variáveis ​​não são o remédio para o problema das longas filas .

O remédio é dividir suas expressões logicamente, introduzindo variáveis ​​nomeadas ainda mais adequadamente . Não tente ser inteligente com espaços em branco. Apenas identifique qualquer subexpressão que possa ser nomeada adequadamente e crie uma variável para ela. Isso simplifica o código que calcula a variável e o código que usa essa variável .


Não faz parte da sua pergunta, mas gostaria de comentar de qualquer maneira: é uma péssima idéia alinhar verticalmente seus =operadores.

Existem três razões para isso:

  1. A edição de um bloco contendo operadores alinhados verticalmente é uma PITA. Sempre que o comprimento da maior variável for alterado (renomear, adicionar, excluir), você precisará retocar todas as linhas do bloco para recuperar seu layout "agradável".

    Obviamente, esse problema pode ser reduzido um pouco usando um editor competente, por isso é o menor motivo. A verdadeira razão é a segunda:

  2. Essas mudanças espaciais de espaço em branco introduzidas pelo realinhamento não funcionam muito bem com sistemas modernos de controle de versão git. Eles tendem a criar quantidades significativas de conflitos de mesclagem onde nenhum conflito real ocorreu e onde nenhum conflito seria sinalizado se o alinhamento não fosse usado. Cada um desses conflitos espúrios custará um valioso tempo para nada .

  3. O alinhamento carrega zero significado semântico . É inútil. Não há nada que você possa entender melhor com o alinhamento. Cada linha do seu bloco precisa ler por si só para entender o que faz, a conexão com as linhas acima e abaixo é de natureza puramente sintática.

Como o alinhamento não possui significado semântico, mas produz custos significativos, você deve desaprender o hábito antes que isso lhe custe mais tempo.


Se você gosta tanto do limite de 80 caracteres, tente alguma programação fortran. É verdade que os padrões mais recentes aumentaram o limite de linha do fortran para 132 caracteres, mas ele permanece em vigor como sempre prejudicando a compilação de qualquer programa que exceda o limite. Se você é bom em programação, em breve passará a odiar o fortran, incluindo seu limite de comprimento de linha. Depois disso, você será curado pelo resto da vida.

Eu mesmo tive que fazer alguma programação de fortran profissionalmente, e eu digo a você, isso me ensinou a odiar muito mais esse limite de comprimento de linha. Não há absolutamente nada mais frustrante do que ter que dividir uma linha simples e legível em partes apenas porque o compilador não a compila mais corretamente. Definitivamente, existem linhas de código que são mais simples quando expressas como uma única linha.

cmaster - restabelece monica
fonte
3

Muitas convenções estilísticas (não regras!) Surgiram ao longo dos anos devido a limitações nos ambientes de programação. Nos dias de cartões perfurados, você tinha um limite rígido no número de caracteres que podiam aparecer em uma linha de origem física (e foi por isso que o Fortran reservou a coluna 6 para caracteres de continuação de linha). Não foi há muitas décadas que eu estava trabalhando em um terminal VT220 âmbar sobre preto 80x24; enquanto os editores que eu usei não limitavam as linhas a 80 caracteres, a vida era muito mais fácil se você fizesse o possível para evitar a rolagem horizontal.

Nas versões mais antigas do Fortran (até 77, IINM), nem era possível ter identificadores com mais de 6 a 8 caracteres. Mesmo nos anos 80, C só garantiria que os 8 primeiros caracteres em nomes externos fossem significativos (e é por isso que algumas funções da biblioteca têm nomes maravilhosamente descritivos, como strpbrk).

É claro que, duas décadas depois do século XXI, não temos mais esses limites. Não há razão para não usar identificadores mais descritivos.

A coisa é, nos contextos certas, ie je ksão perfeitamente razoáveis, nomes significativos . Se eu estiver percorrendo uma matriz ou vetor em um loop e precisar apenas de algo para identificar o elemento atual, ifuncionará perfeitamente. Eu não usaria um nome como currentElement- não é mais significativo nesse contexto e apenas adiciona confusão visual.

Dito isto, seu professor não está errado em forçar você a pensar em termos de nomes mais longos e mais descritivos para tudo - a vida será mais fácil para você se você adotar esse hábito primeiro e depois aprender onde economizar conforme necessário. Como alguém que foi forçado a encaixar tudo em 8 caracteres ou menos, é definitivamente melhor errar ao lado de mais informações do que menos. À medida que ganha mais experiência, você aprenderá onde pode economizar no tamanho do identificador e onde precisa ser um pouco mais descritivo.

John Bode
fonte
-1

Não tenho certeza se isso funciona para c ou não, mas existe uma maneira de dividir fórmulas em várias linhas? Eu sei que algo assim existe para python.

Veja se você pode iniciar + (rowSize * nextWord) + nextWord]) {em uma nova linha. (Como pressione enter no seu IDE e veja se o recua para que C saiba que a expressão anterior está sendo concluída na linha atual)

Krio
fonte
1
Sim, isso definitivamente é possível. C reconhece linhas e linhas de código até você adicionar algo como ponto e vírgula. O problema disso é que nossas funções não podem exceder 50 linhas e, embora meu código de exemplo não tenha 50 linhas, é apenas uma fração da minha função total. Sinto-me fortemente constrangido a escrever em uma caixa de 50 por 80, algoritmos com variáveis ​​significativas que podem desempenhar as funções de que também preciso. Eu poderia continuar armazenando esses longos blocos de código em novas funções, mas sinto que vou terminar com tantas chamadas de função que as pessoas se perderão lendo o código.
Rault
5
"Sinto que terminarei com tantas chamadas de função que as pessoas se perderão lendo o código". Pelo contrário! A extração de código em métodos separados permite fornecer nomes descritivos, aumentando a legibilidade (principalmente do método do qual você está extraindo). Se você acabar com muitos métodos, sua classe pode estar fazendo muito (princípio de responsabilidade única). A extração de métodos em uma classe separada novamente permite que você atribua um nome descritivo a essa coisa.
Roman Reiner
Qualquer função que esteja se aproximando de 50 linhas é provavelmente muito longa e muito complexa (com a possível exceção da inicialização de dados com uma complexidade de 1), mas geralmente quando limites como esse são discutidos, são linhas de código e não linhas de texto, dividindo uma única linha de código, ou seja, o ponto e vírgula geralmente não conta como uma linha extra; verifique com o Prof!
9788 Steve Barnes