Moment: tornar o momento quase imutável

Criado em 3 jul. 2014  ·  163Comentários  ·  Fonte: moment/moment

Tem havido muitas discussões sobre isso. Aqui está a proposta:

Os seguintes métodos mutáveis ​​se tornarão imutáveis ​​no 3.0.0: utc , local , zone , add , subtract , startOf , endOf , lang , também em duration : add , subtract e lang .

Para começar, todos os métodos serão duplicados com methodNameMute variantes. Também precisamos de variantes imutáveis ​​chamadas methodNameImmute . A partir da versão 3.0, os métodos simples e antigos começarão a usar a opção imutável por padrão.

O que é discutível é:

  • deve lang ser tornado imutável
  • todos os getters / setters (incluindo get / set ) também devem ser imutáveis
  • nomeação das versões mutáveis ​​e imutáveis ​​dos métodos
  • e, claro - devemos fazer a mudança ou apenas parar na API imutável

A parte boa é que podemos fazer versões imutáveis ​​dos métodos hoje e decidir mais tarde o que fazer. Se mudarmos, isso também significaria que o branch 2.x estaria disponível por algum tempo após o encerramento de 3.x .

@icambron @timrwood @gregwebs @yang @lfnavess @soswow @langalex

Enhancement

Comentários muito úteis

Meu dois centavos é que devemos ir para a imutabilidade total ou não. Ter alguns métodos imutáveis ​​( startOf , add ) e outros não ( year , get ) é apenas confuso e os desenvolvedores terão que acompanhar quais são quais.

Todos 163 comentários

Meu dois centavos é que devemos ir para a imutabilidade total ou não. Ter alguns métodos imutáveis ​​( startOf , add ) e outros não ( year , get ) é apenas confuso e os desenvolvedores terão que acompanhar quais são quais.

Eu também preferiria tudo imutável por padrão. Os getters já não são imutáveis?

Aqui estão os grandes problemas que vejo com a mudança para a imutabilidade.

Pseudo-Imutabilidade

Devido à natureza do javascript, nunca seremos capazes de ter a verdadeira imutabilidade.

O melhor que podemos fazer é criar uma cópia, alterar e devolver essa cópia. Podemos envolver cuidadosamente todos os métodos públicos para ter certeza de que estamos sempre copiando e modificando, em vez de apenas modificando, mas isso não impede que alguém faça m._d = new Date() ou mesmo m._d.setHours(1) .

Concordo com @icambron , se passarmos para a imutabilidade, deve haver uma mudança completa. Qualquer método que pudesse alterar uma propriedade em um momento, em vez disso, criaria uma cópia do momento e faria uma alteração na cópia.

Área de Superfície Api

A desvantagem de mudar para a pseudoimutabilidade é que muitas novas apis precisam ser criadas se quisermos ainda oferecer suporte à mutabilidade.

Antes, mudar de um momento de mutação para clonagem e mutação de um momento era tão simples quanto adicionar .clone() no lugar certo. Agora, teríamos que criar interfaces mutáveis ​​para todos os configuradores, o que aumenta consideravelmente a área de superfície da API.

Isso inclui os ~ 20 métodos setter, adicionar / subtrair, local / utc / zone / tz, startOf / endOf, lang e quaisquer outros métodos usados ​​em plug-ins de terceiros.

Preocupações com a memória

Como agora estamos criando cópias toda vez que queremos alterar um valor, o uso de memória aumentará. Claro, os novos momentos serão coletados no lixo, mas o custo adicional associado a essa mudança é algo para se ter em mente.

Teríamos que tomar muito cuidado para ter certeza de que não estamos criando toneladas de clones descartáveis ​​com métodos que usam outros setters.

Para rastrear quais métodos estão sendo chamados, usei este pequeno wrapper de função.

for (var method in moment.fn) {
  moment.fn[method] = (function (fn, method) {
    return function () {
      console.log(method);
      return fn.apply(this, arguments)
    }
  })(moment.fn[method], method)
}

Agora, ao executar um método, podemos ver como outros métodos no protótipo são usados. Nem todos esses métodos precisariam clonar no momento, então adicionei comentários sobre aqueles que exigiriam clonagem.

moment().isSame(moment(), 'year')
isSame
clone        // clone
startOf      // clone
month        // clone
date         // clone
year         // clone
date         // clone
hours        // clone
minutes      // clone
seconds      // clone
milliseconds // clone
valueOf
local        // clone
zone         // clone
startOf      // clone
month        // clone
date         // clone
year         // clone
date         // clone
hours        // clone
minutes      // clone
seconds      // clone
milliseconds // clone
valueOf

São 21 cópias que são criadas e imediatamente descartadas. Obviamente, poderíamos otimizar isso usando alguns métodos internos que são mutáveis ​​e apenas expõem as versões imutáveis, mas isso aumentará significativamente a complexidade interna tentando manter um registro de quais momentos ainda precisam de clonagem e quais não.

Preocupações de desempenho

A clonagem de um momento é muito mais lenta do que a mutação de um momento. Eu fiz alguns testes jsperf para isso.

http://jsperf.com/moment-cloning

http://jsperf.com/moment-cloning-2

Acho que o segundo teste é uma representação muito melhor das perdas de desempenho ao alternar para a pseudoimutabilidade. Se multiplicarmos esses resultados pelas 21 instâncias de clonagem observadas acima, os tempos de execução serão muito mais lentos.

Tenho certeza de que poderíamos otimizar o caminho para clonagem por um momento, mas precisaríamos torná-lo 50x mais rápido para ter um desempenho comparável. Tenho certeza de que isso é impossível.

Resumo

Mudar para a imutabilidade aumenta muito a complexidade das ápis internas e externas e apresenta grandes problemas de desempenho e memória. Não acho que esses custos compensem os benefícios que a imutabilidade proporcionaria.

Acho que as questões de desempenho listadas aqui estão perdendo o ponto:

De modo geral, um .clone () inicial é necessário para garantir a correção antes de executar a mutação.

Não podemos fingir que clone () não é necessário com a API atual. O principal caso aqui que é diferente é a realização de múltiplas mutações sequenciais. Esse caso é resolvido com a criação de uma API do construtor de forma que todas as mutações sejam executadas como mutações em um único clone.

Estou perdendo outros casos de uso comuns?

Meu problema original era sobre os métodos startOf e endOf especificamente. Por alguma razão, esses nomes para mim eram como "começa-me começarOf um mês", não "defina este momento para o inícioOf um mês". Métodos como add e subtract estão perfeitamente ok no sentido de semântica. É perfeitamente normal adicionar algo a um objeto sem criar um novo.
Para mim, pessoalmente, renomear os métodos startOf e endOf para smth como toStartOf e toEndOf (como "mover este momento para o início de um mês") resolveria o edição. Na minha humilde opinião

@gregwebs Desculpe, eu quis dizer set acima.

Eu discordo de @soswow; Acho que precisa ser consistente. Na verdade, acho que toStartOf implica imutabilidade ainda mais fortemente, como se estivesse fornecendo uma apresentação alternativa a la toISOString . Mais importante, acho que precisamos ser capazes de fazer afirmações como "Os configuradores de momentos mudam momentos" ou "Os configuradores de momentos retornam cópias", e não "bem, para esses métodos ..."

Sobre as preocupações de @timrwood :

O fato de os objetos JS não serem verdadeiramente imutáveis ​​não me incomoda. A questão é que a API fornece um contrato imutável. É claro que o usuário pode trapacear mexendo nas propriedades sublinhadas, e trapacear é geralmente possível mesmo em linguagens onde a imutabilidade é a principal maneira de fazer as coisas.

Sobre a área de superfície e sobre o desempenho: acho que precisaremos usar os mutadores internamente para evitar o uso de toda a CPU e memória [1], então teremos que suportá-los em algum nível. Então, podemos também expô-los externamente, como setYear() , etc. Isso adiciona um monte de área de superfície, mas realmente não adiciona muita complexidade; para mutadores não explícitos, clone externamente, modifique internamente.

Uma maneira de ver isso é que o usuário precisa clonar em seu código, então o Moment pode muito bem estar fazendo por ele. Isso apresenta um problema com o encadeamento em locais sensíveis ao desempenho, que poderia ser combatido por uma interface de construtor (pela ideia de Greg) ou permitindo que o usuário apenas use mutadores lá. O construtor adiciona muita complexidade [2], então acho que sou a favor de alternativas mutator explícitas. Acho que a realidade é que, na maioria das vezes, o Moment não está sendo usado em situações sensíveis ao desempenho, então essas situações não precisam ser as mais convenientes em termos de API. Eu prefiro ter uma boa API imutável com um perf hatch para quando eu precisar.

[1] Os garotos legais da terra do FP resolvem isso com _compartilhamento estrutural_, mas isso provavelmente não é prático aqui.

[2] Tradicionalmente, as pessoas fazem construtores que são objetos separados, mas isso seria muito prolixo aqui, já que você teria que copiar toda a API setter. Apenas cuspindo, mas uma alternativa é que .chain() cria um momento clone que tem apenas uma bandeira isBuilding definida nele. Em seguida, os clones internos são ignorados, apenas retornando o objeto para mutação. Então build() desfaz o sinalizador e retorna aquele clone. O problema é que você precisa de seus getters para gritar um assassinato sangrento se a bandeira for ativada, ou as pessoas vão acabar usando o usando os Momentos acorrentados, mas não construídos, que de repente se transformam. Em seguida, você precisa diferenciar externamente e internamente chamados getters. Blech. Outra alternativa é decompor internamente a funcionalidade necessária pelo construtor em um mixin e usá-la tanto no construtor quanto no Moment, mas isso provavelmente não é viável de uma perspectiva de organização de código.

o que funcionou para mim foi adicionar um parâmetro extra às funções, um sinalizador (me chamei de self) para denotar mutabilidade, por padrão está em inmutável (retornar uma cópia ou novo objeto), e quando eu detectar desempenho, configurei o sinalizador para verdadeiro

este ponto de vista resolveu muitos conflitos,
tendo funções com nome semelhante executando quase o mesmo código,
ou ter que mudar o nome da função e provavelmente os parâmetros quando eu detectar pontos de desempenho
em meus métodos públicos, eu começo o código chamando as funções com uma cópia e as chamadas seguintes com o sinalizador em true
com isso eu também posso encadear as funções

no meu código eu trabalho com matrizes de matrizes, (como uma tabela, matriz de linhas)
então eu tenho funções para filtrar, unir, etc, que anteriormente retransmite um novo array com o reult, e eu detecto que para obter o resultado final eu chamei várias vezes a mesma função, agora a primeira chamada é criar uma cópia e não alterar a matriz inicial, e as chamadas seguintes, eu trabalho com a mesma linha de eliminação de matriz que não preciso

um exemplo básico que poderia estar aqui:
moment.add = function (medir, quantia, self) {
}

moment.add = function (medir, quantia, self) {
var $ moment = self? este: this.clone ();
// o código real
return $ moment;
}

Obrigado a todos por seus 2 centavos :)

Para o protocolo, concordo com a última postagem de @icambron em todos os pontos.

Restam duas grandes questões.

O mais fácil é como deve ser a nova API, duas opções:
1.1 métodos com nomes diferentes (mutáveis ​​e imutáveis) year / setYear , startOf / setStartOf
1.2 ou builder api chain().mutators().build() , que é a versão não hacky do que @lfnavess propôs.

A API do construtor definitivamente parece mais sexy, mas deve-se tomar cuidado para que os objetos não fiquem no modo de construção por muito tempo, o que adiciona outra fonte de problemas para nós e para os usuários.

Agora o problema difícil - migrar para a nova versão. Vejo duas opções aqui:
Os desenvolvedores 2.1 têm que reescrever seu código (regex louco pode funcionar em 1.1 e solução de nível AST para 1.2 - dado que ninguém usa year e month como os nomes de seus próprios métodos). python adotou essa abordagem - todos nós podemos ver o resultado - uma nova linguagem nasceu!
2.2 opção para ativar a API do construtor sempre (o mesmo que agora) e uma forma de desativá-la para novo código. Isso parece mais _evolucionário_, mas a quantidade de confusão que causaria provavelmente não vale a pena. Cada momento agora tem dois sinalizadores: é mutável e, caso seja - é estritamente mutável (sem getters) ou transicionalmente mutável (getters ok). Sem falar em receber objetos de momento em funções - você deve verificar qual é o modo, certifique-se de mantê-lo ... que bagunça!


E agora uma ideia maluca que me veio agora

Clone de cópia na gravação

m = moment();
funcIDontTrust(m.clone());  // doesn't actually clone

function funcIDontTrust(m) {
  m.year(2005);  // perform the clone here
  console.log(m);
}

Não tenho certeza de quanto pode ser obtido com essa abordagem, dados os momentos em que são muito leves. Além disso, todos os mutadores agora precisam realizar uma verificação.

Existem algumas maneiras de implementar com desempenho variável em cenários diferentes. A boa notícia é que é compatível com as versões anteriores e pouparemos a nós e aos nossos usuários um grande esforço. E acho que isso é mais importante do que reinventar a roda.

Não tenho certeza do que estamos ganhando aqui.

Mudar para a imutabilidade tem muitos custos associados e talvez eu esteja perdendo isso, mas
Eu realmente não vejo benefícios comparáveis.

Os principais benefícios parecem ser a preferência do desenvolvedor. É tudo para que os desenvolvedores não tenham
pensar na propriedade de um momento ao passá-lo?

Não acho que mudar para a imutabilidade tornará os bugs menos frequentes, apenas
alterar o tipo de bugs. O exemplo de @ichernev mostra até mesmo o tipo exato de bugs que
superfície, que são igualmente difíceis de rastrear.

m = moment();
funcIDontTrust(m.clone());  // doesn't actually clone

function funcIDontTrust(m) {
  m.year(2005);  // perform the clone here
  // m is still in 2014
  // m.year(2005) created a clone but did not assign it to anything
  // it should be `m = m.year(2005)`
  console.log(m);
}

Aqui está uma lista de prós / contras entre mutabilidade e imutabilidade. Se eu perdi alguma coisa,
me avise e vou editar este comentário.

| Imutável | Mutável |
| --- | --- |
| Alguns desenvolvedores preferem | Alguns outros desenvolvedores preferem |
| Evita bugs na passagem de momentos | Evita bugs ao esquecer de atribuir momentos clonados |
| Com algumas dezenas de novos métodos de API, a mutabilidade também será suportada | Com o método .clone () existente, a imutabilidade já é suportada |
| | Uma ordem de magnitude mais rápida |
| | Usa muito menos memória |

Eu acho que a imutabilidade é útil, mas não acho que seja um bom ajuste em JavaScript. Acho que uma interface imutável pode fazer sentido para uma linguagem como o Elm, onde a imutabilidade é esperada, mas para o JavaScript, acho que a mutabilidade é esperada.

Muitas das apis para typeof a === "object" embutidos são mutáveis. Array#push,pop,reverse,sort,shift,splice,unshift todos alteram o conteúdo de um array em vez de retornar um novo array. Todos os 16 métodos Date#setX alteram sua instância.

Acho que estamos vendo muitas pessoas reclamando sobre os momentos serem mutáveis, mas se mudarmos, acho que teremos a mesma quantidade de pessoas reclamando. Isso já aconteceu com os métodos eod/sod dois anos atrás.

Depois de olhar para um monte de problemas antigos sobre mutabilidade, acho que provavelmente estou soando como um disco quebrado aqui. Em ambos os lados, são os mesmos pontos que foram levantados nos últimos anos. Eu só queria ter certeza de que um argumento para manter uma API mutável foi representado na discussão.

@timrwood essas são boas comparações, mas está bastante claro que você não teve tempo para entender o caso de uso imutável. Já discutimos por que as comparações de desempenho que você postou pressupõem uma API mal implementada e não fazem sentido.

A comparação do bug também é inválida. Como o momentjs suporta uma API de encadeamento, pode-se esperar que seja imutável.

var newM = m.year(2005) // wrong, these are both the same!

Portanto, tanto imutáveis ​​quanto mutáveis ​​têm o mesmo problema agora. Você poderia evitá-lo com a versão mutável atual se você se livrasse da API de encadeamento.

Portanto, a API imutável é preferível a mutável porque você pode passar um momento com segurança entre as funções. Com os momentos mutáveis ​​atuais, se eu passar um momento entre as funções, tenho 2 opções

1) O jeito insano de bugs (que provavelmente é o mais comum): investigue todo o código-fonte para ter certeza de que não há mutações indesejadas. Escreva testes de unidade para garantir que mutações indesejadas não ocorram.
2) A maneira sã (vamos supor que todos estejam fazendo isso), programação defensiva: lembre-se de chamar a função clone () antes de sofrer mutação em minha função.

Com a API imutável, não precisamos nos lembrar de chamar clone () todas as vezes. Em vez disso, temos que nos lembrar de chamar a função API que nos permite evitar a clonagem, mas isso é apenas uma otimização de desempenho, não uma questão de correção.

está bem claro que você não teve tempo para entender o caso de uso imutável

Essa é uma declaração injusta. Meu argumento é que vejo os benefícios, mas não acho que eles superem os custos.

você pode passar um momento com segurança entre as funções

não temos que lembrar de chamar clone

Não é este o caso de uso da imutabilidade? Se houver algo mais que eu não tenha tido tempo para entender, por favor, me avise, mas esse parece ser o único argumento nos últimos anos.

@timrwood sim, esse é todo o caso.

Mas eu não vejo nenhum sinal de você reconhecendo que seu caso _contra_ imutabilidade (desempenho horrível, promove um tipo diferente de bug não presente na API mutável) não é válido.

Acho que devemos nos ater ao ponto de vista do ecmascript 5 e talvez adicionar uma função que congele profundamente o objeto atual ou um sinalizador global que crie automaticamente objetos frezee

http://blogorama.nerdworks.in/preventextensionssealandfreeze/

talvez um parâmetro extra no construtor para criar um objeto congelado, porque um objeto congelado não pode ser descongelado

@lfnavess Pensei em freeze antes de mencionar a cópia na gravação. O problema é que ... ninguém o usa / sabe sobre ele, nem ajuda quando não lança uma exceção (no modo não estrito) - ele na verdade cria bugs malucos para você rastrear.

@timrwood Acho que não deixei meu exemplo claro. Na linha m.year(2014) // clone here eu quis dizer que internamente o momento realmente faria um clone (alocará mais memória) em apontaria para essa nova memória, automaticamente. Bem, isso basicamente significa que clone() também deve alocar um pouco de memória de shell (algo para apontar para a representação de data interna), só não tenho certeza de quanto ganharia com isso.

Criar uma versão meia-boca de clone , que clona apenas a interface e a capacidade de alterar os dados subjacentes (de armazenamento compartilhado para específico de instância) - realmente depende de quão caros os objetos Date são. A desvantagem é que cada função precisa fazer this._storage._d vez de this._d , e não tenho certeza se isso superaria o benefício.

Não recebi nenhum comentário sobre como lidar com a migração das bibliotecas / usuários existentes no momento. Eu realmente não gosto de nenhuma das opções que listei acima.

A compatibilidade reversa é, IMO, o argumento mais forte contra isso. Se fizermos isso, só temos que aceitar que é uma grande mudança revolucionária. Se não queremos aceitar isso, não devemos fazer.

Vale a pena mencionar re: perf que também existem algumas vantagens enormes que você pode obter com a imutabilidade; não é um hit de desempenho monotônico. Por exemplo, você pode armazenar em cache as coisas no nível do objeto, porque elas nunca serão alteradas. Eu também acho que devemos ser capazes de otimizar a merda viva de clone() ; AFAIK envolve clonar uma data e copiar cinco valores; Acho que devemos apenas codificá-los como newThing._offset = oldThing._offset .

Edit, arg, no - os plug-ins também adicionam campos (por exemplo, aqui ).

dado o forte desejo de compatibilidade com versões anteriores e ainda de manter as coisas leves, acho que a melhor solução é fazer um fork dos códigos-fonte javascript (nos códigos-fonte deste projeto ou iniciar um projeto inteiramente novo). Há espaço para mais de 1 biblioteca de tempo para a internet.

Além disso: re: a ideia de @ichernev sobre compartilhamento estrutural, uma possibilidade é usar herança de protótipo em vez de envolver um objeto de estado compartilhado.

Nós da WhoopInc estivemos espreitando nesta discussão por um bom tempo. Como a discussão aqui parece estar andando em círculos, tirei algum tempo neste fim de semana para explorar como pode ser uma versão imutável do momento com uma API de construtor. (Não tenho intenção de enviar um PR contra o momento, a menos que seja convidado a fazê-lo, já que estou deliberadamente fazendo mudanças na API mais estridentes do que eu esperava ver implementadas no momento.) Aqui está o resultado: https: // github. com / WhoopInc / frozen-moment

Estou apenas algumas horas lá dentro, então tudo é realmente difícil em torno das bordas, mas com base nos resultados dos testes, acho que a maior parte da funcionalidade do momento central está funcionando. Vou continuar acompanhando essa conversa e gostaria de receber comentários específicos sobre nossa bifurcação nos problemas de repo.

Tentarei publicar alguns documentos atualizados nesse repositório hoje à noite, mas basicamente divido todos os métodos setter e de mutação em um objeto builder separado. Portanto, usar a API pode ser semelhante a frozenMoment("2014-07-21").thaw().subtract(1, "day").startOf("day").freeze().format("YYYY-MM-DD") . (Embora neste exemplo particular seja mais eficiente apenas iniciar a cadeia com um construtor em vez de inicializar um construtor de um frozenMoment, usando frozenMoment.build("2014-07-21").subtract... )

FWIW, quando comecei a usar o momento, presumi que ele seguia os princípios do FP e retornaria o mesmo valor toda vez que chamar uma função:

var now = moment();
var yesterday = now.subtract(1, 'days');
var dayBeforeYesterday = now.subtract(2, 'days');

Claro, não obtive os resultados que esperava. Isso me pegou desprevenido como um novo usuário.

Considere este pseudocódigo, que demonstra como eu esperava que o código se comportasse:

var now = now;
var yesterday = now - 1day;
var dayBeforeYesterday = now - 2days;

Mas, em vez disso, acabou funcionando assim, o que me parece estranho:

var now = now;
var yesterday = now = now - 1day;
var dayBeforeYesterday = now = now - 2days;

Por enquanto, embora seja bastante tedioso, apenas cuidadosamente .clone() todos os lugares.

var now = moment();
var yesterday = now.clone().subtract(1, 'days');
var dayBeforeYesterday = now.clone().subtract(2, 'days');

IMO, Javascript está sujeito a erros sutis e eu sinto que os princípios do FP ajudam a minimizar esses erros.

Compreendo que esta seja uma decisão difícil de tomar. Agradeço seu trabalho. Moment.js é incrível.

+1 para 100% de imutabilidade.

Sinceramente, é meio frustrante não ser imutável.

+1 para 100% de imutabilidade na versão 3

Definitivamente deve haver uma API imutável. Como um usuário de outras bibliotecas de data (notavelmente, .NET DateTime e Joda Time / Noda Time), eu intuitivamente espero que o método add não modifique o objeto de data.

+1 para imutabilidade

+1 para 100% de imutabilidade

Se a decisão for tomada pela imutabilidade, estou disposto a dar meu tempo para que isso aconteça. Talvez pareando por uma chamada de vídeo. Gostaria de contribuir mais com o código aberto, mas preciso aprender o básico.

Para mim, a imutabilidade é preferível, mas deveria ter sido feita desde o início. Esta é uma mudança drástica de rompimento. Uma bifurcação deste projeto com foco na imutabilidade seria uma ideia melhor.

@dsherret É para isso que serve o

Porém, com algum esforço, pode ser introduzida como uma opção de configuração: "Você quer tudo imutável? Verdadeiro ou Falso". O padrão seria falso.

Plug-in não oficial de momento imutável ymmv não suportado aqui: https://gist.github.com/timrwood/fcd0925bb779f4374a7c

Haha! Fiquei surpreso de vir aqui muito mais tarde e descobrir que fui um dos primeiros proponentes de uma API mais imutável .. :)

E sim, recebo +1 de imutabilidade para a próxima versão principal.

Outro +1 para o momento imutável por padrão de mim.
E aqui está minha mistura 'imoment': https://gist.github.com/idrm/a91dc7a4cfb381dca24e (use por sua própria conta e risco!). Basta substituir suas chamadas moment () por imoment () e isso deve ser o suficiente. Todas as chamadas de função moment.xyz () estáticas (por exemplo, moment.min (), moment.max (), etc.) devem permanecer como estão.

+ 1 milhão de dólares

+1 para imutabilidade

Também posso adicionar um +1 a uma sugestão anterior deste tópico de discussão para renomear algumas das funções para que sejam mais fáceis de ler ("startOf" para "toStartOf", "add" para "plus", "month" para "withMonth ", etc.)? Ou seja, supondo que você siga a rota imutável por padrão. Eu uso muito o Joda Time e é muito fácil descobrir o que, por exemplo, "date.withDayOfMonth (1) .withDayOfWeek (DateTimeConstants.MONDAY)" significa.
Eles também não precisam estar na distro JS principal; um add-on que os coloque em cima do JS baunilha funcionaria da mesma forma (diabos, estou pensando seriamente em escrever um add-on Joda alinhado ao tempo para combinar com meu mod "imoment").

@ichernev , @icambron , você já tomou uma decisão sobre isso? Os momentos serão imutáveis ​​no 3.0? Se sim: quando você espera que o 3.0 saia? Estou perguntando porque estou pensando em usar o momento congelado ou escrever um pequeno invólucro - e me pergunto se devo esperar.

Para sua informação, o frozen-moment tem estado em um padrão de espera recentemente - eu transferi um monte de PRs do Moment upstream, mas realmente não trabalhei em nenhuma das outras refatorações que idealmente deveriam acontecer naquela bifurcação.

Dito isso, o momento congelado deve funcionar muito bem se você precisar apenas do local padrão em inglês. (Tudo funciona para meus casos de uso e eu mantive a alta cobertura de teste de unidade do Moment.) Os códigos de idioma diferentes do inglês são corrompidos porque não os atualizei depois de portar as APIs de código de idioma recentemente refatoradas do Moment.

Assim que tivermos uma decisão sobre o Moment 3.0, planejarei trabalhar um pouco mais a sério no trabalho de imutabilidade no Moment ou na bifurcação do momento congelado, conforme apropriado. Meu objetivo inicial seria consertar o suporte local e manter a paridade de recursos com a API do Moment 3.0.

+1 para imutabilidade

1 para imutabilidade. E o método format que também transforma o objeto?

+1 para um moment.js imutável
Ou talvez um fork do moment.js? immutable-moment.js? Uma vez que esta será definitivamente uma mudança significativa.

: 100:
faça os imootables!

+1 nos dias de hoje, a imutabilidade é algo que espero em qualquer boa API JS

: +1: Sim, por favor, gostaríamos muito disso. Atualmente espalhamos .clone () em todos os lugares.

+1 isso seria uma melhoria muito boa

: +1: todas as coisas imutáveis

+1 para imutável

Torne tudo imutável. Estou cansado de clonar cada variável de momento (agora) antes de operar na variável agora e depois agora é alterado novamente.

+1 para imutabilidade

Eu não teria esperado que startOf('day') sofresse uma mutação (embora eu admita que está bem documentado se eu tivesse lido com mais atenção). Isso causou um bug divertido em meu aplicativo.

Eu definitivamente concordo que a maioria dos operadores moment.js são estranhos em sua mutabilidade. mmnt.startOf('day') é super contra-intuitivo na medida em que muda mmnt .

Eu uso o moment.js para casos de uso do tipo calendário com muitos loops e comparações de datas. Eu tenho problemas de desempenho com clone() e eles são terríveis. Ter algum controle sobre quais clones e quais sofrem mutações é essencial para mim e provavelmente para outros.
Mesmo que ter clone() todos os lugares pareça estranho no início, o que isso faz é claro e tornou a refatoração para desempenho muito fácil para mim.

Se todos os métodos começarem cegamente usando clone() internamente para ter uma API melhor, acho que não entendemos.

meus 2 ¢ :-)

@jdurand eu prefiro mutar explicitamente do que clonar explicitamente.

@dsherret Não me importo explicitamente com nada. Minha principal preocupação é não clonar implicitamente , pois é uma operação muito cara.
Alguém mencionou que os setters precisariam devolver uma cópia clonada e isso me assustou; Seria muito ineficiente.

@jdurand pode ser mais ineficiente, mas acho que um clone implícito beneficiaria a maioria dos aplicativos em que a diferença entre objetos clonados e mutados não faria diferença perceptível na experiência do usuário final. Acho que a facilidade do desenvolvedor e a tentativa de evitar erros do desenvolvedor devem ter precedência sobre alguns milissegundos salvos, já que a maioria dos desenvolvedores não está fazendo milhares de operações de data ao mesmo tempo. Para aqueles que são, eles poderiam dizer explicitamente que desejam sofrer mutação em vez de clonar.

Nota: com essa mudança, acho que algumas melhorias de desempenho poderiam ser feitas ... por exemplo, a clonagem poderia ser eliminada referenciando o objeto imutável passado e, em seguida, armazenar a operação a ser feita para este objeto (ex. add(1, 'days') ). O resultado seria então calculado executando as operações quando algo como .toString() , .format() , .toDate() , .day() , etc ... é chamado. Isso seria uma mudança dramática e pode não acabar sendo mais rápido ... alguns testes de unidade precisariam ser feitos para comparar o desempenho (além disso, pode haver outros problemas que eu não considerei, pois nunca olhei nenhum código em moment.js diferente de como ele clona).

@dsherret Eu gosto da abordagem _builder _ / _ preguiçosa_; em retrospectiva, provavelmente deveria ter sido construído assim desde o início.
Como você disse, acho que um fork imutável com compatibilidade de API em mente seria o melhor.

Mais 2 centavos:

  1. Devemos realmente nos preocupar com o desempenho, quando o momento é claramente construído para a conveniência e não para o desempenho? Eu acho que analisar 'ano' em m.add ('ano', 1) é muito mais lento do que clonar.
  2. A menos que haja um fork total (nome diferente, documento diferente), será um pé no saco manter 2 versões. Acho que alguém inteligente deveria ter uma ideia para gerar moment.immutable.min.js e moment.min.js a partir da mesma base de código ...

Desde quando temos tanto medo de interromper mudanças? A versão atual é estável e as pessoas ainda podem usá-la sem refatorar sua base de código.

Manter duas bases de código é uma dor, deixa você mais lento e não vale a pena apenas ter uma versão mutável / imutável.

Então, vamos seguir com um momento totalmente imutável, bater a versão principal e pronto: dançarinos:

Encontrei este tópico quando comecei a usar esta biblioteca, mas tenho puxado meu cabelo depurando alguns códigos e lidando com o que para mim parece ser efeitos colaterais imprevisíveis de ser mutável. Adoraria ver uma versão totalmente imutável da biblioteca!

Plugue sem vergonha: cansei de esperar por uma decisão firme aqui. Nos últimos dias, ressuscitei o Frozen Moment e o reescrevi para funcionar como um plugin para o próprio Moment. Gorjeta para @wyantb por me ajudar a fazer o primeiro lançamento de amostra no fim de semana.

O Frozen Moment fornece um tipo imutável que funciona exatamente como o Moment. Basicamente, a versão imutável envolve a funcionalidade do Moment e chama .clone() para você sempre que apropriado.

Para aqueles que gostam de APIs de construtor, eu o desafio a pensar no próprio Moment como uma implementação muito boa de um objeto de construtor! O Momento Congelado adiciona o tipo principal imutável que todos nós queremos e um mecanismo para construir um Momento Congelado imutável a partir de um Momento mutável.

Para aqueles que desejam apenas trabalhar com uma API imutável conveniente - bem, pretendo oferecer suporte a isso também. Ainda não construí um construtor que construirá diretamente uma instância de Frozen, mas está na lista TODO . A curto prazo, a solução alternativa é criar tudo com moment().freeze() ou moment.utc().freeze() .

O Frozen Moment é obviamente uma base de código jovem, então provavelmente existem algumas arestas - mas eu encorajaria qualquer um aqui a tentar e arquivar problemas para qualquer coisa que não funcione da maneira que você esperava.

Ah, mais uma coisa: não estou anunciando isso ainda, mas as instâncias do Frozen Moment devem "simplesmente funcionar" com a maioria dos plug-ins do Moment. Apenas certifique-se de que todos os seus outros plug-ins do Moment se registrem antes do Frozen Moment. Se você encontrar um plugin que não funciona como esperado com Frozen Moments imutáveis, registre um bug e eu o examinarei.

+1 na imutabilidade

+1 para imutável

Alguém olhou para o momento de implementação em cima do JS Imutável ? É uma biblioteca otimizada para imutabilidade em JS, ela reutiliza partes inalteradas de um objeto imutável, reduzindo as preocupações com a memória.

Então, os usuários pedem imutabilidade, mas a equipe principal encontra desculpas para não fazê-lo? : p
Vamos lá pessoal, essa mudança é muito mais importante do que reescrever o código em ES6 ^^ Em sua forma atual, a API é simplesmente ruim, um pouco como o JS Array onde alguns métodos são imutáveis ​​(filtro, concat, etc), mas alguns outros não são (reverso, classificação), exceto sua restrição para compatibilidade com versões anteriores é infinitamente maior do que para uma biblioteca.

+1

uma pequena armadilha que sempre me pega (e IMHO, este é um bom motivo para a imutabilidade):

var today = moment();
for (var i = 0; i < 7; i++) {
   week.push(today.subtract(i, 'days').format('dd').toUpperCase());
}

isso infelizmente não gera uma matriz com os nomes dos dias, mas algo estranho porque você realmente calcula a data assim:

i = 0 = today -0;
i = 1 = today -0 -1;
i = 2 = today -0 -1 -2;
etc

então você tem que refatorá-lo neste:

var today = moment();
for (var i = 0; i < 7; i++) {
            if (i == 0) {
                week.push(today.subtract(0, 'days').format('dd').toUpperCase());
            }
            else {
                week.push(today.subtract(1, 'days').format('dd').toUpperCase());
            }
        }

@faebser excelente exemplo

+1 para imutabilidade

+1

@faebser aconteceu comigo esta manhã. O vínculo bidirecional + mutabilidade do Angular dificulta a tarefa de manter as datas de clonagem para evitar a modificação das atuais.

1 para imutabilidade, isso me custou apenas algumas horas.

: +1:

+1 para imutabilidade

Estou um pouco indeciso sobre este assunto.

O purista em mim quer gritar "+1 para imutabilidade! Objetos de momento são claramente do tipo ValueObject ."

No entanto, não podemos ignorar que moment.js é o 13º repositório de javascript mais popular no GitHub (e 24º no geral), e que a pesquisa por "momento" no bower.io retorna 111 resultados correspondentes. Mesmo que possamos fornecer aos criadores de aplicativos uma maneira gradual de implementar uma versão imutável do momento, isso causará uma grande confusão entre suas dependências.

@ichernev Talvez uma sugestão mais humilde: seria possível dedicar uma pequena parte da página de documentação do momento para falar sobre mutabilidade vs imutabilidade? Você pode declarar brevemente sua posição oficial sobre o tópico e talvez adicionar um breve resumo dos argumentos, colocar um link para este tópico ou, se desejar uma entrada específica para uma discussão, pode funcionar como um CTA.

No momento, a página de documentação não menciona o termo "imutável". Pesquisar "momento imutável" no Google leva você a esta página, mas me levou duas horas lendo e ainda não tenho certeza sobre sua posição atual sobre o assunto. Seria ótimo se o maior sucesso do Google em "momento imutável" desse uma resposta rápida sobre o futuro da imutabilidade no momento :)

Para citar @ jehoshua02 :
"Compreendo que esta seja uma decisão difícil de tomar. Agradeço seu trabalho. Moment.js é incrível."

Aqui está minha proposta. Em vez de tornar o momento base imutável, adicione uma fábrica moment.immutable . Seria uma propriedade da função moment e incluiria a mesma assinatura de API exata de moment , mas imutável.

Poderia até ser apenas uma extensão de protótipo da fábrica mutável moment , usando as funções desse protótipo, mas clonando.

EDIT: Parece que WhoopInc / frozen-moment é exatamente o que estou procurando.

@thomasvanlankveld mudanças de quebra são o que os números de versão principais servem. Qualquer pessoa que usar o Bower e o npm terá a opção de manter o número da versão principal atual; não devemos nos preocupar com a compatibilidade com versões anteriores aqui - exceto, talvez, aquelas pessoas que estão apenas servindo isso a partir do CDN. Mas se eles estão usando momentjs do CDN, provavelmente não estão muito interessados ​​em atualizar a biblioteca de vez em quando.

Eu diria que ter imutabilidade na próxima versão principal - ou na versão principal depois dela - deveria estar no roteiro.

Parece que também encontrei esse problema.

http://stackoverflow.com/questions/33002430/moment-js-formatting-incorrect-date

Portanto, sou totalmente a favor da imutabilidade.

+1 para imutabilidade

Acabei de perder uma noite com este comportamento surpreendente e inesperado.
Outro +1 para imutabilidade com uma alteração de versão principal correspondente para torná-lo claro.

+1 para imutabilidade

+1 para total imutabilidade.
A quantidade coletiva de horas perdidas devido a "às vezes mutável, às vezes imutável" deve ser muito grande.

Sim, quero dizer sério. Quem se importa com o desempenho em uma biblioteca datetime? Tipo .. realmente? Estou supondo que 99,9% dos usuários não estão fazendo nada que, mesmo remotamente, requeira bom desempenho. Normalmente você lida com alguns encontros ou, na pior das hipóteses, com algumas centenas. Os poucos usuários que lidam com milhões de datas por segundo podem usar pontos de API mutáveis ​​otimizados.

A imutabilidade é a única escolha sensata de design. Existem vários estudos que mostram que a programação com tipos imutáveis ​​é muito menos sujeita a erros do que com tipos mutáveis.

1 para imutabilidade. Isso me custou algumas horas.

Parte do problema é que nomes de métodos como .startOf() não implicam em mutação do objeto subjacente.

Eu bati em gargalos de desempenho com o Moment, então posso garantir que isso às vezes pode acontecer.

No entanto, não estou convencido de que os momentos imutáveis ​​seriam inerentemente menos eficientes e posso imaginar alguns casos em que seriam mais eficientes.

Este debate foi resolvido há muito tempo no mundo Java. As datas imutáveis ​​ganharam e a implementação mais popular (JodaTime) acabou se tornando parte da biblioteca padrão em Java 8.

Trabalhar com LocalTime Java 8 tem sido um daqueles tapinhas na testa "Por que nós _sempre_ não fizemos isso?" momentos. Raramente evangelizo tecnologias, mas honestamente não consigo ver nenhuma vantagem em objetos de data mutáveis.

Então, sim .... Eu odeio que esses tópicos sejam inundados com + 1s, mas a verdade da questão é que outra pessoa vai criar uma biblioteca de data JS imutável se o Moment não o fizer.

Recentemente, deparei com um novo módulo npm que pretende portar grande parte da API JodaTime (ou seja, datas do Java 8) para JS.

Isso traria coisas como imutabilidade, LocalDate e LocalTime para o nó e o navegador.

Tendo trabalhado com esses conceitos em Java, todo o resto parece confuso e sujeito a erros.

Ligação?

Na sexta-feira, 11 de dezembro de 2015, às 16h30 Andrew Schmadel [email protected]
escreveu:

Recentemente me deparei com um novo módulo npm que pretende portar muito de
a API JodaTime (ou seja, datas Java 8) para JS.

Isso traria coisas como imutabilidade, LocalDate e LocalTime para
nó e o navegador.

Tendo trabalhado com esses conceitos em Java, todo o resto parece confuso
e propenso a insetos.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/moment/moment/issues/1754#issuecomment -163964349.

Wout.
(digitado no celular, desculpe concisão)

Como ainda não entrei na conversa, só direi que sou a favor da imutabilidade no momento 3.0. Principalmente porque venho da escola de pensamento DDD, onde objetos como moment seriam considerados _objetos de valor_ e, portanto, são melhor implementados como imutáveis.

Mesmo se houver um impacto significativo no desempenho, ainda é a coisa certa a fazer. O momento deve se encaixar naturalmente nos designs dos outros. A API intuitiva supera o perf e a mutação não é intuitiva em objetos de valor (IMHO).

Eu também acho que o momento 3.0 deve remover sua dependência do objeto Date , mas isso é uma discussão para um tópico diferente.

Eu concordo totalmente com @ mj1856 aqui.

Tenho usado Object.freeze em instâncias momentâneas e geralmente alcançou o que eu precisava; exceto que acabei de descobrir que o seguinte falha:

let now = Object.freeze(moment());
if (now.isSameOrBefore(anotherTime)) { // throws exception
}

A exceção:

TypeError: Can't add property _isValid, object is not extensible
 at valid__isValid (C:\git\quick-test\node_modules\moment\moment.js:93:24)
 at Moment.moment_valid__isValid [as isValid] (C:\git\quick-test\node_modules\moment\moment.js:2195:16)
 at Moment.isSame (C:\git\quick-test\node_modules\moment\moment.js:1945:44)
 at Moment.isSameOrBefore (C:\git\quick-test\node_modules\moment\moment.js:1962:21)

Isso pode ser corrigido para que Object.freeze possa ser usado quando desejado?

@wmertens , presumo que seja: https://github.com/pithu/js-joda

@ichernev , @ mj1856 , como não estou envolvido no desenvolvimento do núcleo do momento há algum tempo e a imutabilidade tem um interesse bastante significativo, estou retratando minha postura anterior.

Não tenho certeza se fui o único bloqueador nisso, mas estou confortável em avançar com a imutabilidade no 3.0.

@gabrielmaldi @wmertens Sim. Foi isso. Desculpas pelo meu comentário incoerente - claramente cliquei no botão 'Enviar' em uma postagem escrita pela metade.

Para reunir alguns dos meus pensamentos desconexos:

  • Há claramente algum interesse em objetos de data imutáveis ​​para JS. Existem bibliotecas de datas imutáveis ​​maduras em várias outras linguagens, e há muito ímpeto geral em direção a objetos imutáveis ​​em JS ( immutable.js tem 10.500 estrelas se isso for qualquer indicação). No mínimo, acho que isso merece uma prova de conceito.
  • Apesar desse interesse, muito pouco código parece ter sido escrito. js-joda parece ser a primeira tentativa séria de escrever uma biblioteca de datas imutável para JS.
  • Momentos imutáveis ​​seriam uma grande mudança de ruptura, o que levanta algumas questões filosóficas. Embora eu odiasse perder o apoio da enorme comunidade MomentJS, não seria necessariamente uma coisa horrível para aqueles de nós que estão interessados ​​em datas imutáveis ​​de JS fazer uma pausa limpa e contribuir para js-joda em vez de tentar para empurrar uma mudança bastante radical no Moment (uma biblioteca madura com uma grande e estabelecida base de usuários).
  • À parte: js-joda ainda é muito jovem e não está claro quais são os objetivos e intenções do autor para a biblioteca. Em particular, ele precisa escolher uma licença, e podemos considerar se as necessidades do desenvolvedor JS típico seriam atendidas por uma reimplementação fiel do Joda Time ou JSR-310.

+1 para uma imutabilidade e o código mais correto que resultará.

Será um grande esforço, portanto, um sincero agradecimento àqueles que estarão (e têm feito) que isso aconteça.

Moment é amplamente usado o suficiente para que eu ache que seria possível ir com algo próximo ao seguinte, presumindo que o seja implementado de forma semelhante ao https://github.com/WhoopInc/frozen-moment de @butterflyhug

3.x: imutável como uma opção, padronizado como falso e tem um sinalizador definido na exportação de momento global que seria definido como verdadeiro; console.warn no carregamento da biblioteca (no modo dev)
4.x: imutável como uma opção, padronizado como verdadeiro, sinalizador ainda disponível para ser definido como falso; console.warn sobre a programação para 5.x (no modo dev)
5.x: imutável como a única maneira

Tenha uma página inicial e no centro descrevendo a visão de imutabilidade de longo prazo - digamos, um grande lançamento por ano ao longo do esboço 3.x / 4.x / 5.x que estabeleci - e acho que daria uma ideia razoável quantidade para qualquer pessoa afetada para atualizar seu código.

Algumas observações:

  1. Eu construí WhoopInc / frozen-moment esperando que

Dito isso, ainda estou disposto a ajudar a consertar bugs que as pessoas encontram ao usar o momento congelado - independentemente de esses bugs serem meus ou se eles estão em outro plugin de momento que nunca considerou a possibilidade de que momentos podem se tornar imutáveis. Apenas registre os problemas no momento congelado e eu darei uma olhada. E ainda acho que um esforço comunitário em torno de algo como o momento congelado poderia nos ajudar a entender e aliviar a dor de uma transição para momentos imutáveis.

  1. Se o momento implementa a imutabilidade no 3.0, seria bastante simples para alguém escrever e manter um wrapper para implementar a API do momento mutável 2.x no topo da API 3.x imutável. Conceitualmente, isso se pareceria muito com o momento congelado: em todos os lugares que o momento congelado implicitamente clone() s, este invólucro de mutabilidade mudaria implicitamente sua referência interna para um novo valor de momento imutável. Isso também pode ajudar a facilitar a transição para as pessoas que usam o momento em grandes bases de código.
  2. Eu estaria disposto a ajudar a pensar sobre os problemas potenciais e implementar a imutabilidade no momento 3, se desejado.
  3. js-joda irá portar o JSR-310 diretamente para o JavaScript usando uma licença BSD .

@butterflyhug - Obrigado por construir o momento congelado! Fiquei animado quando descobri isso, mas preocupado em introduzir uma dependência do meu projeto para o momento congelado, visto que, se o suporte fosse interrompido, a mudança de um momento imutável para um mutável seria um grande trabalho no meu código. Se o seu objetivo era obter feedback e você está ativamente apoiando isso, então me sinto mais confortável fazendo isso. :-)

Não sei quantas outras pessoas podem ter tido os mesmos processos de pensamento.

Estou curioso para saber se as pessoas aqui pensam que a imutabilidade deve ser explorada em conjunto com a noção de quebrar a dependência do objeto Date (ou mesmo adicionar algum tipo de avaliação preguiçosa) por motivos de desempenho.

Eu sugeriria dar um passo de cada vez, @schmod. Esta já é uma (aparentemente) grande mudança

@RobertMcCarter Sim, estou planejando apoiar o momento congelado no futuro previsível, a menos / até que alguma opção de imutabilidade seja implementada na biblioteca central - em grande parte porque estou usando-a pessoalmente para algumas coisas que espero que sejam mantendo por um tempo. Dito isso, meus casos de uso não abrangem todo o ecossistema do Moment, então eu confio no feedback e no uso de outras pessoas para ajudar a identificar o que é importante.

+1 para imutabilidade, depois de meia hora tentando descobrir o que aconteceu com meu aplicativo depois de usar o endOf () pela primeira vez. Admitindo que não li os documentos com atenção, apenas assumi que um método com esse nome retornaria o final do mês, por exemplo, e não afetaria a instância do momento. Para ser honesto, é uma surpresa e acho ridículo que não aconteça assim ou talvez minha cabeça esteja muito acostumada com os - na minha opinião - enormes benefícios de ter uma API quase imutável

1 para imutabilidade :)

Eu não me importo com a imutabilidade, deixe esta excelente biblioteca de lado!

@ es6Test Com que base você discorda da imutabilidade? Você tem algum motivo concreto além da resistência à mudança?

+1
Acho que vai facilitar o uso da biblioteca se ela for imutável, meu código está cheio do método .clone () e às vezes a mutabilidade pode provocar bugs muito difíceis de encontrar.

+1 Por favor, mais imutabilidade ^ _ ^

@danpantry Depois de fazer mais alguns aplicativos, mudei de ideia. Eu preferiria a imutabilidade.

Mas eu gostaria de ainda ter alguns vars mutáveis, muitas vezes gosto de adicionar dias a momentos e não quero ter que criar mais vars para segurar o resultado.

@ es6Test Use let se você _realmente_ não gostar?

let date = moment()
// with immutability
date = date.add(5)

Também sou a favor da imutabilidade. Esse é o único recurso da biblioteca datetime do Python que realmente o faz brilhar. Você pode lançar objetos sem se preocupar em modificá-los, como acontece com as cadeias de caracteres.

No mundo React / Redux, a imutabilidade é suprema. Já me deparei com alguns problemas difíceis porque o momento não é intrinsecamente imutável. O desempenho é irrelevante aqui, pois pode ser mitigado. A biblioteca ImmutableJs do Facebook prova que imutável pode ser feito sem sacrificar o desempenho.

Também irei +1 na imutabilidade até o fim. Você não obtém nenhum benefício da imutabilidade até então, então não há por que fazer no meio do caminho.

Imutabilidade e programação funcional estão sendo usadas mais agora do que nunca (e eu adoro isso). Vou oferecer meu próprio tempo para contribuir com esta iniciativa. Colaboradores, por favor, entre em contato comigo e me digam como posso ajudar.

A equipe queria dar uma atualização sobre isso, já que tivemos muito interesse.

Neste momento, queremos que você saiba que ouvimos suas preocupações. Toda a equipe de mantenedores concorda que, se estivéssemos escrevendo a biblioteca do zero, escolheríamos torná-la imutável. No entanto, não é assim agora.

Do jeito que está, temos 4 milhões de downloads de NPM por mês, junto com um número incontável de usuários que dependem de conseguir o momento por meio de outros canais. Todos esses usuários têm um código que espera o momento de ser mutável como é hoje. Além disso, temos muitos plug-ins que dependem do momento de serem mutáveis.

O código é fácil de escrever, mas as necessidades de suporte desse tipo de mudança são difíceis de assumir como uma equipe pequena fazendo isso em nosso tempo livre. Dito isso, estamos dispostos a considerá-lo. Estamos nos perguntando:

  • Por que o plugin do momento congelado não atende às suas necessidades?
  • Você só precisa de uma API imutável (uma API que sempre retorna um clone) ou, por algum motivo, precisamos realmente não transformar os objetos internamente?
  • Adicionar uma segunda API imutável ao código atual atenderia às suas necessidades?

O problema com o plug-in de momento congelado é que ele é ativado, e não desativado. Cada
moment () precisa de um .freeze () para ser imutável.

O ponto principal da imutabilidade é que quando eu tenho o objeto X, eu sei que
a menos que eu o torne mutável explicitamente, ele precisa ser imune a mudanças.
Qualquer função pública que me permite alterar um objeto internamente sem
mutabilidade explícita é problemática.

Acho que uma solução alternativa é fazer várias coisas:

  1. Adicione uma segunda API imutável ao código atual
  2. Tenha uma configuração global moment () onde, se estiver definido para o modo imutável, tudo
    as instâncias moment () criadas são imutáveis, se uma chamada mutável for tentada,
    não sofrerá mutação e, em vez disso, apresentará um erro com a mensagem apropriada para usar imutável
    api chama.

Isso eu acho que vai satisfazer a todos. O que você acha?

Na segunda-feira, 23 de maio de 2016 às 12h11, Maggie Pint [email protected]
escreveu:

A equipe queria dar uma atualização sobre isso, já que recebemos tantos
interesse.

Neste momento, queremos que você saiba que ouvimos suas preocupações. o
toda a equipe de mantenedores concorda que estávamos escrevendo a biblioteca do
do zero, escolheríamos torná-lo imutável. No entanto, não é assim
é agora mesmo.

Do jeito que está, temos 4 milhões de downloads NPM por mês, junto com um
número incontável de usuários confiando em conseguir o momento por meio de outros
canais. Todos esses usuários têm código que espera o momento de ser mutável conforme
é hoje. Além disso, temos muitos plug-ins que dependem do momento sendo
mutável.

O código é fácil de escrever, mas o suporte precisa desse tipo de
mudanças são difíceis de assumir como uma equipe pequena fazendo isso em nosso sobressalente
Tempo. Dito isso, estamos dispostos a considerá-lo. Estamos nos perguntando:

  • Por que o plugin do momento congelado não atende às suas necessidades?
  • Você só precisa de uma API imutável (uma API que sempre retorna um
    clone) ou, por algum motivo, precisamos realmente não transformar internamente o
    objetos?
  • Adicionar uma segunda API imutável ao código atual atenderia ao seu
    precisa?

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/moment/moment/issues/1754#issuecomment -221062274

Eric Lau da conta do Gmail.

Obrigado por responder @maggiepint.

  1. Alguns problemas com o plugin de momento congelado: não é o padrão, requer trabalho extra para ser usado, há menos chance de que ele seja mantido ativamente, suponho que ele tenha um impacto de desempenho (provavelmente muito pequeno) em relação a algo que foi construído como imutável. Acho que o maior problema é esquecer de usá-lo, especialmente em projetos maiores com muitos engenheiros.
  2. A API deve ser livre de efeitos colaterais. Retornar um clone é bom, mas se você também modificar o objeto original, isso seria um efeito colateral. O código a seguir não deve modificar o início ao declarar o fim:
start = moment();
end = start.add(10, 'minutes');
  1. Você quer dizer ter funções como 'immutableAdd' além de 'add'? Em caso afirmativo, sim, tecnicamente seria, especialmente se você criar um wrapper para usar funções imutáveis ​​com os mesmos nomes:
import "moment/immutable";
start = moment();
end = start.add(10, 'minutes'); // immutable version of add

Em minha opinião, essa abordagem se presta a uma atualização elegante para aqueles que desejam usar a API imutável - o código existente ainda funcionará, ninguém é forçado a entrar e requer menos alterações para aqueles que desejam usar a API imutável.

Temos toda a intenção de tornar o efeito colateral do código gratuito. O padrão básico seria conectar-se às funções atuais, fazê-las chamar o clone e, em seguida, operar naquele clone.

Porém, tecnicamente, se você estiver criando um código verdadeiramente imutável, os objetos devem ser construídos com valores que não mudam. No entanto, isso aumentaria a dificuldade em fazer essa alteração. É muito mais fácil chamar o clone e fazer o que fazíamos antes.

Apoio a ideia de Drew:

importar "momento / imutável";
início = momento ();
end = start.add (10, 'minutos'); // versão imutável de add

Isso seria ótimo, já que é um opt-out imutável e nenhuma alteração para
nomes de funções.

Na segunda-feira, 23 de maio de 2016 às 12h53, Maggie Pint [email protected]
escreveu:

Temos toda a intenção de tornar o efeito colateral do código gratuito. O básico
padrão seria conectar-se às funções atuais, fazê-las chamar clone,
e operar nesse clone.

Porém, tecnicamente, se você estiver criando um código verdadeiramente imutável, os objetos
deve ser construído com valores que não mudam. Fazer isso seria
aumente a dificuldade em fazer essa mudança. É muito mais fácil
chame clone e faça o que estávamos fazendo antes.

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/moment/moment/issues/1754#issuecomment -221076796

Eric Lau da conta do Gmail.

@ ericlau-solid

  1. Tenha uma configuração global moment () onde, se estiver definido para o modo imutável, tudo
    as instâncias moment () criadas são imutáveis, se uma chamada mutável for tentada,
    não sofrerá mutação e, em vez disso, apresentará um erro com a mensagem apropriada para usar imutável
    api chama.

Isso será interrompido se 2 bibliotecas na página esperarem comportamentos diferentes no momento. Por exemplo, você usa datepicker, que espera um momento mutável, e seu próprio código espera um momento imutável - não funcionará.

Tendo api imutável (ala frozen-moment)

Isso também não é perfeito, porque nenhum plug-in funcionará com ele. Na verdade, não há como introduzir imutabilidade E manter todos os plug-ins existentes funcionais. Os plug-ins não funcionarão ou não funcionarão com momentos imutáveis, antes que alguém gaste tempo para fazê-los funcionar.

importar "momento / imutável";

Portanto, esta é basicamente a proposta de uma biblioteca diferente com uma interface semelhante. Claro, ele não quebrará o código, mas provavelmente causará confusão e fará com que alguns projetos tenham as 2 versões instaladas (por exemplo, o datepicker pegará a versão mutável e seu código ficará com a imutável).

A melhor opção é fazer uma API bem parecida com a atual, mas com objetos imutáveis. Um garfo pode estar em ordem. Afinal, é assim que o software livre funciona.

A opção "adicionar uma segunda API / publicar um submódulo" seria melhor para compatibilidade, porque os desenvolvedores seriam capazes de atualizar seu código de forma incremental. Se possível, o significado de moment() (via import moment; no módulo de terreno, ou o moment global na construção do navegador) não deve mudar, porque há um toneladas de código legado por aí.

IMO, uma solução que permitisse o seguinte seria o ideal:

import moment from 'moment';
import {immutable as immoment} from 'moment';

var a = moment(); // mutable moment
var b = moment().immutable(); // immutable moment
var c = immoment(); // also an immutable moment; shorthand

Não é uma biblioteca diferente, mas sim - tem dois tipos de momentos separados e distintos. Assumindo que os objetos de momento mutáveis ​​e imutáveis ​​compartilham uma quantidade significativa de código "nos bastidores", o tamanho da biblioteca não precisaria aumentar muito para desenvolvedores que precisam usar ambas as sintaxes. Se um aplicativo usa apenas uma sintaxe, a agitação de árvore pode ser usada para produzir uma construção otimizada.

A bifurcação da biblioteca potencialmente dobraria o tamanho do código que a maioria dos desenvolvedores precisará carregar, o que seria indesejável para a maioria dos aplicativos da web.


Não acho que seria uma boa ideia presumir que qualquer plug-in funcionará com momentos imutáveis ​​"fora da caixa" e não consideraria isso um requisito razoável.

Também não acho que seja um requisito / suposição razoável que as APIs mutáveis ​​e imutáveis ​​sejam idênticas. Devemos nos esforçar para tornar o caminho de atualização o mais suave possível, mas não devemos nos prender a nenhuma sintaxe estranha.


Eu também acho que há muito espaço para debate / discussão sobre como seria a API "imutável". Padrão do construtor? Instanciação do construtor? Objeto de valor? Implementar a API atual, mas algum método "setter" retornou um clone?

Minha única solicitação é que a nova API seja clara e inequívoca sobre o tipo de momento com o qual estamos trabalhando. IMO, freeze falha nesse teste e oferece pouca proteção além de chamar clone() toda vez que passo um momento.

Portanto, esta é basicamente a proposta de uma biblioteca diferente com uma interface semelhante. Claro, ele não quebrará o código, mas provavelmente causará confusão e fará com que alguns projetos tenham as 2 versões instaladas (por exemplo, o datepicker pegará a versão mutável e seu código ficará com a imutável).

Não é uma biblioteca separada, apenas um invólucro fino em torno da mesma biblioteca. Haveria apenas a necessidade de haver uma versão do Momento instalada. Você pode importar 'momento / imutável' e datepicker pode importar 'momento' no mesmo projeto sem problemas.

Pode haver problema na interface com plug-ins que demoram ou retornam um momento se eles não foram atualizados para lidar com momentos imutáveis.

Digamos que você passe um momento imutável para um plugin que, no momento, o trata como mutável. Até que o plug-in seja atualizado, deve haver uma maneira de converter para mutável antes de dar um momento para o plug-in. Idealmente, ele seria descontinuado após os mantenedores do projeto terem algum tempo para preparar o suporte à imutabilidade. Provavelmente também seria necessário haver uma maneira de detectar a imutabilidade (para autores de plug-ins).

Por outro lado, uma biblioteca que se atualiza para usar a interface imutável e retorna um momento imutável aos usuários, pode confundir aqueles que não usam a imutabilidade e não esperam um momento imutável. Eu acredito que isso também pode ser tratado por um método de conversão desativado. Os plug-ins devem retornar um momento do mesmo tipo que foi passado.

@maggiepint sim, entendo seu ponto, mas acho que pode ser um salto muito grande para se dar. Pessoalmente, eu estaria ok com uma abordagem que simplesmente clone esteja por trás da cortina. Especialmente enquanto as torções estão sendo resolvidas.

@tacomanator é o que eu também quero fazer. Refazer tudo para ser verdadeiramente imutável internamente não é terrivelmente sustentável.
Eu só não sabia se por algum motivo as pessoas QUERiam isso.

@schmod Você poderia freeze é uma API clara e inequívoca?

Se o nome da função for muito bonito, ficarei feliz em considerar um argumento para renomear os métodos do Frozen Moment como um problema nesse repo. Por outro lado, se você acha que não deve ser possível converter de mutável para imutável (e vice-versa), então eu suspeito que isso possa levar a alguma discussão aqui - embora observe que eu também estaria disposto a usar o Momento Congelado nessa direção, se chegarmos a um consenso aproximado de que essa seria uma API melhor.

@maggiepint Estou correto ao ler "adicionar uma segunda API imutável ao código atual" como basicamente agrupar parte ou todo o Frozen Moment com a biblioteca central? Se for útil, eu ficaria feliz em ajudar a migrar o Frozen Moment ou algumas de suas ideias para a organização do momento (seja como um plugin oficial ou como parte da biblioteca central) e ajudar com sua manutenção nesse novo contexto.

@butterflyhug Você está dizendo exatamente o que @ichernev estava pensando. Ele estava inclinado para o plugin oficial que veio com a biblioteca. Talvez possamos coordenar isso em Gitter em algum momento? Tenho que ficar ausente por três dias a negócios, então terei disponibilidade limitada. O resto dos caras deve estar por perto.

@butterflyhug

Eu acho que freeze é um bom nome, apenas é chato ter que lembrar de usá-lo após _cada única_ invocação de momento.

Também acho que import 'moment/immutable' tem os mesmos problemas, é fácil esquecê-los.

Honestamente, você está seguindo semver, acho que a abordagem correta é fazer tudo usar _por padrão_ imutável e lançar essa mudança como sua própria versão principal, com um plano de não oferecer mais suporte a versões mais antigas após um período de tempo (12 meses?). Novos recursos / correções podem ser mesclados em ambas as faixas, imutáveis ​​e mutáveis, com um plano de migração dado aos usuários que usam a versão mutável.

Após os 12 meses mencionados, as versões antigas _ainda_ funcionariam, mas não receberiam nenhum TLC.

Claro, isso é um monte de sobrecarga, mas acho que seria melhor fazer essa mudança direito do que tentar falsificá-la no interesse da compatibilidade com versões anteriores. Isso também torna a mudança muito mais complicada, o que pode dissuadir o interesse da equipe de desenvolvimento principal. Eu não sei.

Outra desvantagem potencial dessa abordagem é onde os usuários estão usando esse script de um CDN e não especificam uma versão explícita (por qualquer motivo), o que pode causar o rompimento de seus sites se uma API compatível com versões anteriores for lançada. Tudo o que posso dizer é "Eu avisei", mas entendo que esse pode não ser um risco aceitável por enquanto.

Ter duas versões da mesma biblioteca só seria um problema se você estiver contando com um objeto global e não há realmente uma maneira legal de contornar isso além de continuar a usar freeze() .


TLDR é que parece que o problema que você está tentando resolver foi resolvido pelo semver, que você já está usando. Por que não usá-lo como deve ser? Versão principal para mudanças significativas. A única ocasião em que isso quebra é quando você está contando com uma variável global moment e usando um CDN, mas qualquer alteração que fizermos aqui quebrará isso de qualquer maneira

Meu voto também é sobre o lançamento do semver e do imutável 3.0.

Não me oponho ao nome freeze , mas acho intrinsecamente problemático que seja difícil fazer suposições seguras sobre se um momento está ou não congelado. ( Object.freeze() tem um problema semelhante)

Um momento imutável não deve ser congelável, e nunca deve haver qualquer dúvida se ele está ou não congelado. Isso poderia ser realizado por meio de uma variante estrita do padrão do construtor (ou seja, o objeto _only_ tem setters até .build() ser chamado, após o qual _somente_ tem getters), ou tendo um momento ser "congelado" assim que é instanciado, com todos os setters retornando um clone.

Por exemplo:

/* BUILDER PATTERN */
var bldr = moment.immutable()
  .hours(5)
  .minutes(30)
  .seconds(25);

bldr.hours();  // throws exception.  builder has no getters

var time = bldr.build();

time.hours(); // 5
time.hours(6); // throws, OR returns a clone

/*  A more explicit variant:  */
var bldr = moment.immutable()
  .setHours(5);

bldr.getHours; // undefined

var time = bldr.build();
time.getHours(); // 5
time.setHours;   // undefined
/* VALUE OBJECT */
var time = moment.immutable()   // 00:00:00
  .hours(5)       // new object => 05:00:00
  .minutes(30)    // new object => 05:30:00
  .seconds(25);   // new object => 05:30:25

/*  Same thing, but more efficient:  */
var time2 = moment.immutable(5,30,25); // 05:30:25

time.hours();   // 5
time.hours(6);  // new object => 06:30:25

O primeiro exemplo é muito parecido com o java, mas também deixa pouca ambigüidade sobre como os momentos são construídos e o que você pode fazer com eles. Ele também fornece um caminho eficiente e intuitivo para a construção de novos momentos com pouca sobrecarga e segue de perto como a maioria das pessoas atualmente usa o momento.

Eu seria a favor de que os setters em momentos construídos lançassem exceções, pois esse comportamento reduziria ainda mais a ambigüidade (em detrimento do detalhamento) e forçaria os desenvolvedores a reconhecer sempre que estão criando novos momentos.

O segundo exemplo parece ter muito mais sobrecarga, porque estamos criando (e descartando) muitos objetos. Porém, há muito espaço para otimização. GC moderno é muito bom; a avaliação preguiçosa pode ajudar; poderíamos tornar os objetos Moment tão leves quanto possível (eliminando o Date subjacente), etc. (para alguma comparação, este padrão não é diferente da maneira como as strings são tratadas em JavaScript)


Eu sou um fã do semver, mas o caso de uso do navegador torna problemáticas as alterações significativas, porque será impossível ter duas versões do momento na mesma página sem um carregador de módulo.

Como mencionado anteriormente, existe um _muito_ de código legado por aí que depende do Moment. No mínimo, precisamos de uma versão que ofereça suporte a ambos os padrões, para permitir um período de transição suave.

+1 para métodos combináveis ​​que retornam novos momentos. Eu nem me importo se eles são imutáveis. Apenas me dê a composição, para que eu possa encadear métodos juntos ou atribuir o momento mutado em uma linha (em vez de 2).

@alexyuly por que a clonagem não funciona para você? Se quiser escrever inline, você pode fazer algo como:

var a = moment();
var b = a.clone().subtract(1, 'week').startOf('day');

Como queiras.

@maggiepint Bem, me sinto um idiota, parece que você poderia compor métodos o tempo todo. Obrigado pela dica. Talvez seja um pouco mais claro nos documentos? por exemplo, http://momentjs.com/docs/#/manipulating/start -of / <- nenhuma menção a qualquer valor de retorno.

Pequena atualização - esta postagem do blog é MINHA posição sobre o assunto no momento: https://maggiepint.com/2016/06/24/why-moment-js-isnt-immutable-yet/

Não falo pelo resto da equipe, mas eles viram isso, e geralmente diria que estamos todos em um lugar semelhante.

@maggiepint pontos excelentes e muito válidos

Obrigado por isso. Imutabilidade é rei em redux, então irei mudar para js-joda com certeza. Posso ainda guardar o momento para o tempo relativo.

Eric Lau - Gmail

Na sexta-feira, 24 de junho de 2016 às 11h12 -0700, "Maggie Pint" [email protected] escreveu:

Pequena atualização - esta postagem do blog é MINHA posição sobre o assunto no momento: https://maggiepint.com/2016/06/24/why-moment-js-isnt-immutable-yet/

Não falo pelo resto da equipe, mas eles viram isso, e geralmente diria que estamos todos em um lugar semelhante.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

Alguns bugs / confusão mais comuns causados ​​por mutação: http://stackoverflow.com/questions/26131003/moment-js-start-and-end-of-given-month

1 para isso, mas na verdade com Redux eu descobri que este é um problema surpreendentemente pequeno porque eu não coloco instâncias de Moment no objeto de estado Redux. Apenas as strings de data ou timestamps e eu uso Moment nos métodos de renderização apenas para converter as strings de data em outras strings.

Faço isso principalmente porque é fácil serializar e desserializar o estado sem nenhum trabalho extra, mas também esconde a mutação de React e Redux.

Estou fazendo o meu melhor para obter uma atualização sobre este neste fim de semana. Temos um plano, mas preciso ter certeza de que tudo vai dar certo antes de me comprometer com ele. Infelizmente, estou me mudando de Minneapolis para Seattle na próxima semana, então isso pode desacelerar por um tempo, mas quero avançar.

Pequena atualização em preparação para uma atualização maior, pois percebi que aquela postagem do blog ainda está recebendo algum tráfego. Atualmente estou retrabalhando a compilação do momento para usar o Babel. Isso nos prepara para trazer o plugin do @butterflyhug tem gentilmente nos ajudado muito com isso. Além disso, estou me reunindo com John-David Dalton do LoDash (ambos trabalhamos na Microsoft) para discutir a estratégia ao trazer um plugin oficial, como ele já fazia com o LoDash funcional. Longa postagem no blog e RFC em breve.

@maggiepint enquanto torna o frozen-moment oficialmente suportado, você está planejando abordar https://github.com/WhoopInc/frozen-moment/issues/20?

Eu acho que essa abordagem de imutabilidade é boa o suficiente, desde que cada chamada para moment() retorne um momento congelado por padrão, e os desenvolvedores não precisam se lembrar de chamar .freeze() todas as vezes.

@gabrielmaldi Boa pergunta. Estou escrevendo o RFC (deve ser feito a qualquer momento) e, sim, é meu objetivo explícito fornecer uma história melhor para uso apenas imutável. Minha proposta segue as linhas do meu comentário sobre WhoopInc / frozen-moment # 20, levando em consideração os métodos estáticos. Vou postar um link para meu RFC aqui e naquela edição quando abrir meu PR no repositório RFC, e certamente receberíamos comentários da comunidade sobre a proposta naquele momento.

Terminei de escrever o rascunho da RFC e abri um PR .

É um documento bastante longo, em parte porque ainda há algumas questões pendentes sobre como queremos entregar essa funcionalidade aos usuários e, portanto, estou tentando destacar os prós e os contras de várias abordagens lá. Mas acho que as ideias de implementação são bastante sólidas, então adoraria ouvir o pessoal aqui se você tiver reservas sobre a API voltada para o usuário proposta .

Resumo executivo da RFC com nossas principais perguntas a serem respondidas: https://maggiepint.com/2016/07/16/immutability-its-happening/

@maggiepint Eu tentei postar um comentário sobre aquele artigo, mas por algum motivo ele engoli em seco. Aqui está o que escrevi:


Minha maior preocupação com essas mudanças é que elas respondem a uma parte desproporcionalmente vocal e expressiva da comunidade - evitando o baluarte silencioso de desenvolvedores comuns que nem mesmo sabem que essa discussão está ocorrendo.

Os threads do GitHub não são um microcosmo da comunidade de desenvolvimento mais ampla. Este site sofre o mesmo viés de participação de muitos fóruns na web, e é voltado para um certo tipo de desenvolvedor: intelectualmente engajado com a teoria da computação; interessado em ideias em vez de aplicações; e atrevo-me a dizer socialmente inclinado a se mobilizar em torno de tendências populares. Esses desenvolvedores são naturalmente atraídos por causas célebres filosóficas, como imutabilidade e programação funcional, e têm acesso mais próximo a você do que qualquer outro grupo. Eles serão a voz mais alta na sala e clamarão por essa mudança - mas e quanto ao resto do mundo?

O resto do mundo quer coisas que funcionem. Ele quer saber se a biblioteca que usa atualmente continuará recebendo atualizações - correções de bugs pelo menos, mas idealmente pequenas melhorias incrementais que tornam suas vidas melhores. Mas não diz isso, porque não busca ativamente esses fóruns e porque é preciso muita paciência para falar contra a tendência.

Se você está decidido a fazer essa mudança, acho que precisará deixar bem claro para essas pessoas por que essa mudança tornará suas vidas melhores; por que eles devem atualizar; por que eles não precisam se preocupar porque seus projetos legados não receberão correções de bugs indiretas; e essencialmente - quais coisas eles serão capazes de fazer e que não podiam no momento.

Também acho que você também deve ter muito cuidado para validar a importância dessa mudança em termos reais. Eu me pergunto se você deve liberar essa mudança como um plugin ou wrapper e monitorar sua aceitação cuidadosamente por vários meses antes de mesclá-la no tronco. Se a imutabilidade foi exagerada como uma preocupação de nicho, você terá encontrado uma maneira de satisfazer esses usuários vocais sem alterar o curso da biblioteca como um todo.

Como um usuário iniciante, terminei aqui depois de algum tempo perdido com startOf endOf. Esses métodos estão sofrendo mutações surpreendentes!

+1 para imutabilidade total

Talvez outra solução seja tornar dolorosamente óbvio que os objetos momentâneos são mutáveis . A documentação menciona isso na seção de clonagem, mas NÃO é suficientemente saliente.

Outra solução, se você quiser mutabilidade, use conceitos Orientados a Objetos e crie a criação de objetos usando a palavra-chave NEW versus o padrão de fábrica moment ().

O resto do mundo quer coisas que funcionem.
... você precisará deixar bem claro para essas pessoas por que essa mudança tornará suas vidas melhores

Todas as pessoas que testemunhei serem novas no momento caem na armadilha dos "momentos" sofrerem mutações.
Mesmo depois de 3 anos de uso do momento eu ainda tenho que dizer a mim mesmo "oh merda, você está usando .startOf aqui .. é melhor verificar duas vezes se você precisa de uma cópia".

O comportamento atual não é intuitivo e está muito atrasado.
Tente fazer com que array.filter / map mude e veja como isso é divertido.

Em relação a...
Desempenho / Memória: Eu nunca encadei mais de 2 funções no momento e geralmente é .set().get()
Pseudo-Imutabilidade: Levará muitas e muitas gerações até que java-pass-by-ref-gen seja lançado.

Eu gosto da ideia de @AdamHess sobre escolher se você está procurando por OOP ou imutabilidade.

Meus dois centavos sobre por que ficamos confusos são estes: valores de retorno. Se moment.add('1', 'days') estivesse retornando indefinido, como as funções mutáveis ​​em JS geralmente fazem, a confusão iria embora. Devolver o mesmo objeto, pelo menos para mim, implica que tenho uma nova cópia. Claro, isso quebraria a capacidade de cadeia.

Acho que há uma baixa probabilidade de problemas de uso de memória para mais desenvolvedores (exceto para casos de uso especiais). A mutabilidade do Moment já me mordeu. As datas devem ser tratadas como valores, como uma string ou número.

+1 para imutável por padrão

A propósito, esse mesmo problema existe para o PHP. Você quer ser como o PHP ?! 😆

Em PHP, eles resolvem isso fornecendo DateTimeImmutable (além do DateTime normal).

Se não mudarmos o comportamento padrão para ser imutável, devemos pelo menos considerar uma API alternativa de primeira classe como imoment / momenti (ou qualquer outra coisa). Eu literalmente sempre usaria isso (em vez da API mutável) e espero que qualquer outra biblioteca que eu usasse também usasse a versão / API imutável.

Eu voto pela imutabilidade também, estou disposto a ajudar na implementação se esse for o plano. Já tive problemas de mutabilidade ao fazer adição e subtração, o que torna ainda mais confuso, é que esses métodos retornam a instância por causa do encadeamento.

A propósito, que tal durações de clonagem? Qual é a melhor maneira de fazer isso, não consegui encontrar nenhum que não parecesse hacky.

@ngerritsen Acredito que a melhor opção disponível é moment.duration(existingDuration) .

Re: implementação, # 3548 ainda é um PR ativo. Esperançosamente, não resta muito trabalho em nível de código, mas nunca é demais ter mais olhos para validar grandes mudanças. Também precisamos trabalhar na documentação e etc antes de podermos fazer um aumento na versão principal, que será necessário para lançar uma mudança como esta. Se você gostaria de ajudar com alguma coisa desta lista, tenho certeza que agradeceríamos. 😀

Passei uma hora tentando identificar um bug sutil causado por .startOf () alterando a data original ... Obrigado pelo trabalho árduo, momentjs fez um ótimo trabalho mostrando como construir uma excelente biblioteca de datas para JS, mas estou mudando até date-fns por causa da natureza muito sutil desse tipo de bug e porque depois da minha introdução a alguns conceitos gerais de FP (principalmente graças ao React, Redux e ELM) comecei a apreciar os benefícios gerais da imutabilidade.

Pelo que vale a pena, lodash já seguiu uma abordagem mais FP com lodash / fp. Eu sugiro que você dê uma olhada na forma como o lodash / fp foi implementado, porque eles agrupam suas funções existentes em vez de ter que reescrever tudo por completo. O pessoal do Lodash também está muito preocupado com o desempenho.

Eu também concordo com @mull , o verdadeiro problema é devido à API de encadeamento para mim, que IMO tem algumas grandes falhas de design não apenas neste caso, mas de forma mais geral (por exemplo, jQuery). Seria melhor para mim se o método de mutação de datas retornasse indefinido (pelo menos esta é a regra geral que aplico ao código que escrevo)

Enquanto o namespace moment.frozen está em andamento, eu recomendo --como o poster anterior sugeriu-- usar apenas

Acabei de consertar outro bug devido a momentos mutáveis ​​🎉

Relacionado tangencialmente, seria incrível se o 3.0 pudesse passar para as classes ES6:

let mom1 = new Moment();
let mom2 = Moment.parse('2019-03-01T14:55');
// etc

Tal movimento também pode guiar a discussão sobre imutabilidade. Eu diria que todos os métodos devem ser imutáveis, com uma exceção. Um método chamado .set('minute/hour/year/etc', 18) .

Acabei de começar a usar o Moment e estava _horrorizado_ que esta biblioteca não era totalmente imutável desde o início. Estou usando o momento imutável até que isso seja corrigido.

O momento

Confira seu novo projeto: luxon
É muito bom, moderno, imutável (!) E deve ter um desempenho muito melhor do que o imutável no momento, que envolve tudo em .clone() chamadas.

Para aqueles que gostariam de fazer a transição de momentjs para uma abordagem moderna, confira https://github.com/you-dont-need/You-Dont-Need-Momentjs

Muito surpreso por ser mutável!

Até que ponto o luxon é um substituto? Uma das razões pelas quais estou usando Moment.js é o suporte de fuso horário - é uma obrigação para o meu projeto.

@alamothe Essa pergunta está claramente respondida no site: https://moment.github.io/luxon/docs/manual/moment.html

Fechando isso. Como outros apontaram, use o Luxon se quiser uma API quase imutável. Obrigado.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

benhathaway picture benhathaway  ·  3Comentários

nikocraft picture nikocraft  ·  3Comentários

tanepiper picture tanepiper  ·  3Comentários

dogukankotan picture dogukankotan  ·  3Comentários

chitgoks picture chitgoks  ·  3Comentários