Implementação de conjunto de valores específicos vs. uso de algum tipo de conjunto genérico com verificações avançadas

8

Atualmente, estou trabalhando em uma implementação definida em JavaScript. Isso deve simular genéricos conhecidos como Java ou C #. Eu preciso de uma versão mutável disso (permite adicionar / remover valores definidos) e uma versão imutável.

Minha assinatura do construtor é assim:

new GenericSet( 'number', [ 10, 20, 30 ] );

,

 // mutable set of mixed values (allows to add further values via "add")
 new MutableGenericSet( '*', [ 'foo', 42, {}, /./ ] );

ou

// DataValues.prototype.equals will be used by the set for determining equality.
new GenericSet( { type: DataValue, valueComparison: 'equals' }, [ dv1, dv2, dv3 ] );

Apenas GenericSet ou implementação de um conjunto por tipo?

Inicialmente, meu principal objetivo para isso era ter conjuntos de valores de um tipo. Por exemplo, um DataValuesSet que aceitaria apenas valores de dados. Eu poderia então definir interfaces com funções que requerem uma instância DataValuesSet . Eu não podia usar herança (e acho que seria ruim de qualquer maneira), então usaria composição e teria uma instância GenericSet / MutableGenericSet internamente.

Uma abordagem alternativa seria sempre levar GenericSet, implementar e usar, o GenericSet.requireSetOfType( type )que geraria um erro se o tipo de conjunto não fosse o necessário. Minha preocupação em fazer dessa maneira é que minhas definições de interface pareçam menos explícitas.

Toma

/**
 * @param DataValuesSet dataValues
 */
function printDataValues( dataValues ) {
    if( !( dataValues instanceof DataValuesSet ) ) {
        throw Error( '...' );
    }
    // ...
}

vs.

/**
 * @param GenericSet<DataValue>
 */
function printDataValues( dataValues ) {
    // Throws error if dataValues is not a set or it it is a set with values of wrong type.
    GenericSet.requireSetOfType( dataValues, DataValue );
    // ...
}

talvez usar @param GenericSet(DataValues) dataValuespara documentar a segunda opção seria bom? Alguém vê outras implicações com a segunda abordagem ou há sugestões alternativas? Para mim, o segundo parece mais intuitivo e minha preocupação com o primeiro é que eu criaria mais sobrecarga com os construtores enquanto não vejo nenhuma vantagem clara no momento.

Daniel AR Werner
fonte
6
Por que os genéricos importam em uma linguagem como JS, que é fracamente tipada?
Yazad 23/04
1
Isso não é possível em uma linguagem como JavaScript, que é fraca e dinamicamente digitada. Basta usar uma variante JS digitada como TypeScript.
precisa saber é o seguinte

Respostas:

3

Eu costumava tentar resolver esse tipo de problema com JavaScript, o que só servia para complicar implementações de ... Bem ... Qualquer coisa. Se você não quiser usar algo como o Typecript, documente o que espera. Se as pessoas ignoram sua documentação, elas entram em território desconhecido.

Não tente forçar um pino redondo em um buraco quadrado que qualquer pessoa possa moldar em um buraco redondo. Isso é JavaScript. Abrace-o. Não lute, querida. Documente e volte a escrever código.

Greg Burghardt
fonte
0

Eu diria que o primeiro exemplo é mais legível. Isso não implica que um erro seja gerado para o conjunto digitado incorretamente. Diz que esta função leva a DataValueSet. Ser explícito no seu código adiciona clareza.

GenericSet.requireSetOfTypeofusca a intenção da verificação de tipo na função de impressão. Parece que está verificando itens com o tipo DataValue.

Hasen
fonte
A legibilidade não parece ser um argumento forte o suficiente para mim aqui. Você poderia fazer a documentação perfeitamente claro em ambos os casos usando DataValuesSetvs. GenericSet<DataValue>. Talvez, em vez de GenericSet.requireSetOfTypenomear a função GenericSet.assertSetOfTypeou similar, fosse mais claro.
Daniel AR Werner
0

Dadas as opções que você apresenta, eu preferiria a primeira solução, porque é mais legível que a segunda. Mas, se você realmente deseja fazer uma solução no estilo JS, crie uma função de construtor, se os objetos são do mesmo tipo ou devem ser do tipo misto ( MakeStrictCollectionvs MakeMixedCollection). Na função de construtor, você poderia testar, se o tipo de cada membro de sua coleção dado é do mesmo tipo ou não, e lançar um erro ou retornar um objeto de cada construtor, que tem um atributo tipo adicional "type":"strict"vs "type":"mixed".


Além disso:

Você deve dar uma olhada no Typescript , que pode ser o que você está procurando. E há um pacote que parece atender às suas necessidades com coleções genéricas .

Thomas Junk
fonte
Para -1 MakeStrictCollection vs MakeMixedCollection. Em relação aos exemplos de código acima, a printDataValuesfunção mudaria para verificar se o objeto fornecido era instanceof StrictCollectione qual era o seu tipo DataValues. GenericSet.requireSetOfTypepode ser exatamente isso - portanto, sua sugestão parece ser apenas um detalhe de implementação da GenericSetabordagem.
Daniel AR Werner