Por que precisamos de enumerações em idiomas de tipo dinâmico?

32

Eu estava lendo algum código aqui e vi que um enum é usado para armazenar nomes de tags html. Por que precisamos fazer isso? Que benefício eu recebo usando essa estratégia?

Eu sei que quão úteis são enumerações enumeradas em idiomas compilados ou estaticamente, mas quando vejo enumerações em linguagens dinamicamente, fico curioso, como o código de exemplo que mostrei acima. Portanto, a questão basicamente se resume a por que precisamos de enumerações em linguagem de tipo dinamicamente ou precisamos delas?

CodeYogi
fonte
38
Esta pergunta é basicamente "Por que precisamos de tipos" .
User11153
1
Você pesquisou o repositório para ver como ele é chamado? Isso provavelmente proporcionaria uma melhor compreensão das respostas que você recebeu.
11338 RubberDuck
se você tiver: enum People { YOU, NPC, FOO, BAR }e uma função que deseja um (Pessoas) int, você pode conectar o que quer que seja, em vez de usar um número.
Evan Carslake
3
Você está perguntando sobre o objetivo deste "enum" específico ou sobre o objetivo de enum em geral, em qualquer idioma? Eu assumiria o primeiro, mas todas as respostas atuais parecem pensar o último ...
meriton - em greve

Respostas:

56

Um benefício é que o compilador pode informá-lo se você digitar acidentalmente "ADRESS" ou "FEILDSET" e permitir que você o corrija imediatamente, em vez de se comportar de maneira absurda no tempo de execução.

Embora o benefício seja muito mais útil em linguagens de tipo estaticamente do que dinâmico, ele ainda é útil, mesmo que seja um erro de tempo de execução, pois você receberá uma mensagem indicando um problema com sua declaração de caso e não com seus dados.

whatsisname
fonte
4
@ amon: você poderia, mas a enums fornece um mecanismo útil para garantir que você não tenha colisões.
Whatsisname
75
Um lugar que eu costumava trabalhar para uma vez passou um mês perseguindo um erro causado pela brilhante idéia de alguém para as constantes string uso em vez de enums, fontes editor pobres, e um campo acidentalmente chamado"PROF1LE_"
Gort o robô
8
@amon Go faz exatamente isso. Uma coisa boa sobre enumerações, no entanto, é que o compilador pode verificar se sua instrução switch tem um caso para cada valor de enumeração possível.
Weberc2
15
Este código foi escrito nos anos 80. Você pode não perceber isso, mas isso foi em uma época em que alguns desenvolvedores aprenderam a desenvolver máquinas de escrever físicas, que podem não ter uma única chave . Embora, na verdade, eu perceba que a sequência em questão era "Profi1e" ... já faz vinte e cinco anos, então minha memória obviamente não é perfeita.
Gort the Robot
4
@DarrelHoffman: Estou surpreso que você esteja surpreso. No Perl, freqüentemente me pego digitando $1quando quero dizer $i. (É verdade que eu nunca digito em f1levez de file- o $1erro é causado pelo fato de $1ser muito comum no Perl - mas ainda assim, erros de todos os tipos são comuns. Talvez o desenvolvedor tenha uma senha prof1lenele, preparando-o para digitar errado. profileem contextos sem senha.)
ruakh
22

As enums são úteis para situações em que você tem um conjunto fixo de valores / entidades que são sensíveis. Eles são auto-documentados e permitem ao compilador validar coisas que seriam deixadas no tempo de execução. Eles nunca devem ser usados ​​se o conjunto de valores significativos não for conhecido ou estritamente limitado.

Um exemplo mais útil seria algo como códigos de resposta HTTP. Em vez de ter um método que usa um número e forneça o nome e / ou a descrição do erro, você pode ter um conjunto de enumerações com nomes significativos, um código e uma descrição etc. em um pacote limpo que seja autoritário em quais valores são permitido e precisa ser manuseado.

JimmyJames
fonte
1
"Auto-documentação" é a parte mais importante. Eu prefiro verificar se status === GEOLOCATION_ACQUIREDque status === 3, para que a pessoa que mantém o software entende o que está acontecendo. Como você disse, também impede valores inválidos.
Nicolas Bouliane
11

Enums não têm nada a ver com OOP, e o JavaScript não tem enums. Em vez disso, as enumerações são usadas sempre que houver uma escolha entre um conjunto fixo de valores. Por exemplo, um booleano é uma escolha entre verdadeiro e falso, que pode ser implementado como enum Bool { False, True }. Em uma biblioteca GUI, podemos ter um enum para alinhamentos: enum HAlignment { LEFT = -1, CENTER = 0, RIGHT = 1 }.

Geralmente é irrelevante como o enum é implementado, a parte importante é que cada valor possível é distinto. Muitas linguagens usam números inteiros para enumerações, embora algumas como Java suportem objetos arbitrários.

Até agora, poderíamos também usar constantes, por exemplo const int LEFT = -1, CENTER = 0, RIGHT = 1. No entanto, um compilador sabe que os valores da enumeração pertencem um ao outro. Portanto, quando alterno os valores de enumeração switch(value) {case LEFT: ...; case RIGHT: ...;}, o compilador pode me avisar que esqueci o CENTERcaso. Isso pode economizar bastante tempo. Em idiomas sem enumerações ou sem uma construção de caixa de mudança, isso pode ser simulado com o Padrão de Visitante, embora seja mais útil na presença de digitação estática.

A outra vantagem é que as enums podem ser tratadas como um tipo separado. Por exemplo, posso declarar que um método aceita um HAlignmentparâmetro, em vez de qualquer número inteiro. O código falhará na compilação se eu fornecer algo além de um dos três valores possíveis de HAlignment. No entanto, as enumerações de C não são bem encapsuladas e as constantes de enumeração podem ser usadas de forma intercambiável com números inteiros. Outros idiomas são mais rigorosos aqui.

Em JavaScript, não obtemos nenhum desses benefícios. O exemplo dado declara um objeto que é tratado como uma enumeração. Isso tem algumas vantagens para o programador, por exemplo, facilita a documentação, agrupa todas as “constantes” em um único objeto,…. No entanto, é apenas uma convenção de que esse objeto é semelhante a enum.

O ponto aqui é que o HTML tem apenas um conjunto finito e conhecido de tags. Você pode olhar para a especificação HTML5 e colocar esses nomes de elementos como uma enumeração em seu código e, portanto, dificulta a inserção de uma <blink>tag em seu programa. É melhor codificar esse conhecimento em um único local para desarrumar seu código com literais de strings especiais (ou pior, números mágicos).

amon
fonte
Nesse caso, se eu passar <blink>para algum método em javascript, nada poderia me parar, certo? mas em javaOlá Breaks Loose :)
CodeYogi
@ CodeYogi sim, porque o JS não possui um sistema de tipo estático e, em particular, não tem conceito de tipos de enumeração. No entanto, eu posso documentar um parâmetro de método como "leva um TagName", o que levaria um programador a invocá-lo como foo(TagName.STRONG)um pouco melhor. Seria ainda melhor se o JS reclamasse se o campo não existir, mas aqui só temos um undefinedse eu tentar TagName.BLINK. Não vale muito em JS, mas é um começo.
amon
Hmm, o link de código que mencionei acima usa o compilador de fechamento, portanto, faz sentido lá.
CodeYogi
Clojure é uma linguagem funcional, por isso não tenho certeza de como o OOP é relevante para a questão, mas, além disso, é importante distinguir entre enums que geralmente são apenas um conjunto de números inteiros (não OO) e o padrão 'Typesafe enum' que é OO e o que Java suporta.
JimmyJames
@JimmyJames estou falando JS, não sobre Clo j ure (que, em execução na plataforma Java, também suporta OOP até certo ponto). A questão foi marcada com oop , e é por isso que eu a mencionei no começo. Eu realmente não ver como typesafe enums estão ligados a OOP, isso é apenas uma característica do sistema tipo (muitas línguas não-OOP têm sistemas do tipo :-))
amon
3

Mesmo que sua linguagem não exija compilação, você provavelmente usará algum tipo de IDE ou ferramentas de desenvolvimento, que podem oferecer um suporte muito melhor para algo como um enum do que apenas para strings.

Se você usar um literal de objeto de enumeração em javascript, por exemplo, seu editor fornecerá a conclusão do código e seu verificador de código como JSHint ou JSLint o alertará, se você acidentalmente usar o valor errado.

hansmaad
fonte
Penso que muitas das outras respostas falham ou ultrapassam esse ponto. Usar um 'emum' em uma linguagem dinâmica pode não fazer nada para um compilador, mas pode realmente ajudar certos IDEs, ferramentas de documentação e também não esquecer os seres humanos que estão tentando entender o código.
Robert
2

O objetivo dessa enumeração pode ser fornecer ao Js Api (goog) um conjunto / pacote de tags permitidas. Quais? Os definidos pelo W3C HTML 4.01 ( consulte a documentação do enum ). Portanto, são os limites das configurações.

Pode ou não ser esse o objetivo real, mas funcionaria bem para esse fim.

Se você sabe como o Javascript funciona, o que o código está fazendo é definir uma matriz indexada por strings :-). Qual valor é uma string, mas pode ser qualquer outro componente com atributos, funções, etc ... Deixe sua imaginação correr livre e você verá benefícios em todos os lugares.

Javascript à parte, eu uso muito enums para modelar e gerenciar máquinas de estado .

INÍCIO> IN_PROGRESS> CONFIRMADO> CONCLUÍDO> ...

No java switch permite enumerações, é muito fácil validar estados em uma máquina de estados , fazer um loop por toda a enumeração, definir prioridades fazendo enumerações complexas, ...

Também os uso para definir constantes digitadas e não modificáveis:

  • Sim não

Também enumerações complexas (que permitem realizar transformações / analisadores seguros)

  • Sim (1, verdadeiro), Não (0, falso)

Como as enums geralmente pertencem à minha camada de modelo (core), seus recursos são acessíveis a todo o sistema, tornando-se um modelo funcional e mantendo um baixo acoplamento.

O que a enumeração fornece (entre outras coisas) é limites e tipificação

Laiv
fonte