Freecodecamp: [beta] Controle de qualidade da seção de programação orientada a objetos

Criado em 30 jan. 2017  ·  44Comentários  ·  Fonte: freeCodeCamp/freeCodeCamp

Isso foi originalmente aberto para um desafio específico, mas observando algumas outras coisas ao longo do caminho nesta seção, portanto, apenas consolidarei nesta edição (um comentário para cada). @HKuz , se talvez já exista outro problema para isso, acho que você é quem deve saber, fiz uma busca rápida mas não consegui encontrar nada.

No geral - acho que esses desafios são ótimos! _ Definitivamente _ uma melhoria _maior_ em relação à seção OOP existente !!!! Parabéns a quem os criou !!

Comentários / problemas gerais:

  • Parece que nesta seção, depois de resolver um desafio, você pode alterar ou até mesmo apagar o código, e o desafio ainda passará. Eu criei um problema separado para isso: # 13021
  • Seria bom obter o registro das saídas no console de desafio integrado para que as pessoas pudessem ver os resultados de seu código. Frequentemente chamamos métodos que registram coisas no console nesses desafios, mas eles não foram projetados para fazer logon no console in-page.

Comentários muito úteis

Use a herança para não se repetir :

Acho que esse desafio é um pouco confuso. O título refere-se a Herança, no entanto, herança nunca é mencionada no desafio - eu percebo que está ligada ao próximo desafio, então os campistas irão descobrir rapidamente, mas a forma como é apresentada ainda é um pouco desanimadora. Além disso, no final do desafio, criamos um supertipo Animal , mas ficamos um pouco confusos, porque Animal , neste ponto, não está vinculado a Cat e Dog . Para acabar com a confusão um pouco, acho que podemos fazer uma pequena mudança:

Esta frase vem do próximo desafio:

Este e o próximo desafio cobrirão como reutilizar os métodos do Animal dentro do Bird e Dog sem defini-los novamente. Ele usa uma técnica chamada herança.

Talvez, para amarrar as coisas, uma visão geral de nível superior semelhante a esta possa ser dada neste desafio que une todos os 3, de forma que seja entendido que eles são uma sequência e realmente introduz o conceito de que o desafio é intitulado depois e o torna claro que no final deste desafio ainda não terminamos.

Todos 44 comentários

Use a notação de pontos para acessar as propriedades de um objeto

(RESOLVIDO PELA ENCENAÇÃO) ✅

Este desafio só aceita o seguinte como solução:

console.log(dog.name);
console.log(dog.numLegs);

No entanto, não declaramos explicitamente que 2 instruções separadas devem ser usadas e o seguinte não é aprovado:

console.log(dog.name, dog.numLegs);

Estou pensando que devemos especificar que 2 instruções separadas console.log() precisam ser feitas ou refatorar o teste para aceitar as duas soluções - acho que preferiria a última opção. Pensamentos?

Verifique o construtor de um objeto com instanceof :

(RESOLVIDO PELA ENCENAÇÃO) ✅

  • Por alguma razão, o linter lança o aviso Expected an assignment of function call and instead saw an expression quando a solução correta myHouse instanceof House; é escrita. O desafio passa embora.
  • Além disso, o próprio código de semente tem um aviso de linter no carregamento para um ponto e vírgula ausente.
  • Por último, não tenho certeza se é intencional, mas pode ser um pouco confuso - nos desafios anteriores desta seção, os construtores são definidos assim:
function House(numBedrooms) {
  this.numBedrooms = numBedrooms;
}

mas neste desafio eles mudam para esta sintaxe:

let House = function(numBedrooms) {
  this.numBedrooms = numBedrooms;
}

Isso não é tanto um problema quanto uma possível fonte de confusão. Se usarmos as duas maneiras, acho que devemos observar especificamente a diferença, caso contrário, apenas mantenha a sintaxe consistente em toda a seção. Provavelmente, apresentar os dois é uma boa ideia, embora eu acho.

Compreendendo as próprias propriedades :

Apenas uma observação sobre este, e curioso para ver quais são as outras opiniões - mas este desafio parece girar um pouco mais em torno de for...in vez de hasOwnProperty , e for...in não é adequadamente explicado nesta seção até o momento.

Se presumirmos que as pessoas trabalharam no restante do currículo, acho que está tudo bem, porque isso é pelo menos abordado na seção Estruturas de dados básicas, mas se pretendemos que as seções sejam independentes umas das outras e não exijam pré-requisitos do que podemos querer revisitar isso?

Compreenda a propriedade do construtor :

(RESOLVIDO PELA ENCENAÇÃO) ✅

Este desafio passará com qualquer solução:

function joinDogFraternity(candidate) {
  if (candidate instanceof Dog) {
    return true;
  }
  return false;
}

// OR:

function joinDogFraternity(candidate) {
  if (candidate.constructor === Dog) {
    return true;
  }
  return false;
}

Não vejo isso como um grande problema, pois o instinto dita que as pessoas tentem a solução sugerida primeiro, no entanto, também posso ver isso sendo um problema que está sendo aberto no futuro quando um campista experiente tenta os dois caminhos e quer apontar isso.

Poderíamos apenas adicionar um caso de teste que diz "message: 'your solution should use the constructor property'" e verificar com um regex.

Use a herança para não se repetir :

Acho que esse desafio é um pouco confuso. O título refere-se a Herança, no entanto, herança nunca é mencionada no desafio - eu percebo que está ligada ao próximo desafio, então os campistas irão descobrir rapidamente, mas a forma como é apresentada ainda é um pouco desanimadora. Além disso, no final do desafio, criamos um supertipo Animal , mas ficamos um pouco confusos, porque Animal , neste ponto, não está vinculado a Cat e Dog . Para acabar com a confusão um pouco, acho que podemos fazer uma pequena mudança:

Esta frase vem do próximo desafio:

Este e o próximo desafio cobrirão como reutilizar os métodos do Animal dentro do Bird e Dog sem defini-los novamente. Ele usa uma técnica chamada herança.

Talvez, para amarrar as coisas, uma visão geral de nível superior semelhante a esta possa ser dada neste desafio que une todos os 3, de forma que seja entendido que eles são uma sequência e realmente introduz o conceito de que o desafio é intitulado depois e o torna claro que no final deste desafio ainda não terminamos.

Herdar comportamentos de um supertipo :

(RESOLVIDO PELA ENCENAÇÃO) ✅

Problema super menor aqui - parte da semente para isso é o seguinte:

// Add your code below this line

let duck
let beagle

duck.eat(); // Should print "nom nom nom"
beagle.eat(); // Should print "nom nom nom"

Isso gera um erro de linter. Eu proporia o seguinte:

Problema super menor aqui - parte da semente para isso é o seguinte:


let duck; // change this line
let beagle; // change this line

duck.eat(); // Should print "nom nom nom"
beagle.eat(); // Should print "nom nom nom"

@ no-stack-dub-sack - esses são todos ótimos pontos, e não vi nenhum problema para esta seção, embora eu tenha estado off-line ontem. Obrigado por percorrer esta seção com tantos detalhes 👍 Aqui estão meus pensamentos (tl; dr - concordo com tudo que você mencionou):

  • Use Dot Notation to Access the Properties of an Object : os testes devem passar se alguém usar uma instrução console.log .
  • Verify an Object's Constructor with instanceof : devemos corrigir o ponto e vírgula ausente e ser consistentes sobre a forma House é definido. Embora existam várias maneiras de fazer as coisas em JS, não há necessidade de confundir as pessoas que estão aprendendo isso pela primeira vez.
  • Understanding Own Properties : Em sua opinião sobre for...in - geralmente achamos que não há problema em usar conceitos já abordados no currículo. Os campistas podem pular quando quiserem, mas há um fluxo para os tópicos. (Caso contrário, os desafios podem se tornar longos / repetitivos se eles tiverem que cobrir as coisas antes de chegar ao ponto). Dito isso, acho que pode ser útil colocar uma nota logo abaixo do exemplo que explica resumidamente a sintaxe ("Lembre-se de que for...in faz ...)
  • Understand the Constructor Property : concorde com seu ponto de adicionar usando o construtor nas instruções
  • Use Inheritance So You Don't Repeat Yourself : sim, bons pontos para unir melhor os desafios
  • Inherit Behaviors from a Supertype : devemos definitivamente adicionar o ponto e vírgula, e os comentários também são úteis

Deixe-me saber se você quiser trabalhar neles - estou pulando para outra seção (posso trabalhar nisso em um ou dois dias), ou podemos abrir isso se precisarmos de ajuda 😄

@HKuz Legal, obrigado! Vou terminar a seção, adicionar mais alguns comentários, se houver algum, e então podemos decidir a essa altura, mas acho que abrir o item Procura-se ajuda será provavelmente o melhor. Manterá você informado.

Adicionar métodos após a herança :

Este desafio é um pouco confuso por causa do seguinte caso de teste:

Dog should have the bark() method as an own property.

A solução para esta parte é procurar isto:

Dog.prototype.bark = function() {
    console.log('Woof!');
};

e embora Dog.prototype.hasOwnProperty('bark') retorne true (então isso é, é claro, correto), a fonte da confusão vem daqui (que é de Iterar sobre todas as propriedades ):
image

Com as informações que os campistas recebem até este ponto, eles provavelmente presumem que, para passar no teste, eles teriam que definir o método bark , diretamente na instância do objeto de Dog vez de no protótipo.

A diferença é que para instâncias de Dog , bark _não_ seria uma propriedade own , mas _é_ uma propriedade own de Dog.prototype . Então, isso é um pouco confuso para quem está começando a conhecer esses conceitos.

A solução mais simples seria mudar o caso de teste para dizer:

Dog.prototype should have the bark() method as an own property.

Embora, talvez, uma explicação rápida seja para que os campistas saibam que uma propriedade prototype de um protótipo é na verdade uma own propriedade desse protótipo? Uau, isso é um trava-língua, então sim, é um pouco confuso, e não tenho certeza qual é a melhor maneira de dissipar essa confusão ...

Use o fechamento para proteger as propriedades de um objeto de serem modificadas externamente :

(RESOLVIDO PELA ENCENAÇÃO) ✅

Pequeno erro de digitação:

image

Acho que deveria estar "... fora da definição de bird ." ?

Compreender a expressão da função invocada imediatamente (IIFE) :

Sem maiores problemas com este desafio - apenas uma sugestão - embora eu saiba que IIFE anônimos são o padrão mais comum (e o padrão que será usado no próximo desafio), talvez aqui seja um bom lugar para mencionar que IIFE 's também podem ser nomeados, e isso pode até ser considerado uma prática melhor (embora menos comumente visto) porque pode tornar a depuração mais fácil, pois os erros serão mais difíceis de rastrear se houver muitos IIFE anônimos

Pensamentos?

Use um IIFE para criar um módulo :

Eu gostaria de ter algumas idéias sobre este ... talvez @dhcodes ou @Greenheart?
Meu problema é que não acho que o desafio seja adequado para explicar por que IIFE faz sentido neste cenário.

A solução exige:

let funModule = (function() {
  return {
    isCuteMixin: function(obj) {
      obj.isCute = function() {
        return true;
      };
    },  
    singMixin: function(obj) {
      obj.sing = function() {
        console.log("Singing to an awesome tune");
      };
    }
  };
})();

então você pode fazer algo como:

function Bird () { }
let duck = new Bird();
funModule.singMixin(duck);
duck.sing();

entretanto, você poderia obter a mesma coisa de uma forma menos detalhada e sem invocar nenhuma função, simplesmente definindo apenas o objeto que IIFE retorna.

O desafio diz o seguinte:

A vantagem do padrão de módulo é que todos os comportamentos de movimento podem ser empacotados em um único objeto que pode então ser usado por outras partes do seu código.

Mas, uma vez que isso não requer um IIFE, acho que questionaria a ideia de introduzir o conceito aqui, ou de encontrar uma maneira mais forte de vinculá-lo. Isso pode ser confuso / enganoso porque os campistas podem pensar que PRECISAM fazer isso para atingir esse padrão quando não for o caso.

Alguma ideia?

@ no-stack-dub-sack Concordo que este não é o melhor exemplo de um IIFE. Seria melhor se fornecermos module como exemplo?

Acho que o valor central do IIFE é que você pode criar propriedades e métodos privados de seus objetos. É realmente útil para diminuir as maneiras pelas quais outras pessoas podem (mal) usar seu software na esperança de torná-lo mais confiável.

Por exemplo, você pode ter um pequeno módulo de utilitário para seu aplicativo vanilla js onde deseja expor apenas alguns métodos públicos, já que o resto está prestes a ser alterado / removido e causaria problemas se fossem usados ​​em outras partes da base de código.

Este site tem muitos bons exemplos: https://toddmotto.com/mastering-the-module-pattern/

@Greenheart Bem, no último dos 2 desafios do IIFE aqui, ele é apresentado como um padrão de módulo e não tenho nenhum problema com isso, só acho que poderia ser mais claramente explicado _por que_ usar um IIFE e que um IIFE não precisa necessariamente estar presente para obter a mesma funcionalidade. Acho que isso diz tudo:

O valor central do IIFE é que você pode criar propriedades e métodos privados para seus objetos. É realmente útil para diminuir as maneiras pelas quais outras pessoas podem (mal) usar seu software na esperança de torná-lo mais confiável.

Se pudermos apenas explicar isso e informar ao usuário "você pode obter a mesma funcionalidade sem um IIFE, mas com um IIFE é a melhor maneira, e aqui está o porquê ...".

As instruções atuais dizem:

Uma expressão de função imediatamente chamada (IIFE) é freqüentemente usada para agrupar funcionalidades relacionadas em um único objeto ou módulo.

A isso vamos apenas adicionar: "Embora a mesma funcionalidade possa ser alcançada sem um IIFE, o valor central do IIFE, neste contexto, é que você pode criar propriedades e métodos privados de seus objetos. Isso pode ser muito útil para diminuir o maneiras que outras pessoas podem (mal) usar seu software e tornar as coisas muito mais confiáveis. "

@ no-stack-dub-sack Isso! :aponte para cima:

Tomei a liberdade de compilá-lo e fazer algumas pequenas alterações. Precisamos de algo assim: blush:
An <dfn>immediately invoked function expression</dfn> (IIFE) is often used to group related functionality into a single object or module. While the same functionality can be achieved without an IIFE, its core value in this context is that you can create private properties and methods for your objects. This can be very useful for decreasing the ways others can (mis)use your software, and make things much more reliable.

Possivelmente, use <dfn> se o termo não tiver sido usado nos desafios anteriores.

Seguirei em frente e atualizarei os testes de Usar notação de pontos para acessar as propriedades de um objeto !

Continuando com https://github.com/freeCodeCamp/freeCodeCamp/issues/12966#issuecomment -275974706.

O primeiro problema é porque o linter não quer que escrevamos uma expressão que seja essencialmente um código morto (já que não chamamos uma função nem criamos uma variável). Para corrigir isso, sugiro que atribuamos o resultado a uma variável.

O segundo e o terceiro problema podem ser corrigidos alterando a semente para usar o código que você propôs. A atribuição de objetos de função a variáveis ​​pode ser ensinada em outro lugar ou pela experiência. Acho que devemos ser consistentes com function X () {}

Vou consertar isso: sorria:

Percebi que nenhum desafio tem soluções, então estou trabalhando em um PR.

Compreendendo as próprias propriedades :

(RESOLVIDO PELA ENCENAÇÃO) ✅

Os testes atualmente permitem o uso do método embutido Object.keys() , mas acho que os campistas obtêm uma prática melhor usando for...in combinado com Object.hasOwnProperty() .

Programação orientada a objetos: iterar em todas as propriedades :

(RESOLVIDO PELA ENCENAÇÃO) ✅

Acabei de descobrir que este desafio tem o mesmo problema - permite o uso de Object.keys() Como ainda não acho que isso deveria ser permitido nesses desafios, vou criar um PR adicionando o caso de teste a partir desta linha

function Dog(name) {
  this.name = name;
}

Dog.prototype.numLegs = 4;

let beagle = new Dog("Snoopy");

let ownProps = Object.keys(beagle);
let prototypeProps = Object.keys(Dog.prototype);

Corrigindo isso imediatamente: sorria:

Programação orientada a objetos: mudar o protótipo para um novo objeto

Instruções e testes insuficientes. describe e eat deveriam existir apenas no prototype , ou deveriam ser funções?

Acho que devemos adicionar testes para verificar se são funções.

Programação orientada a objetos: lembre-se de definir a propriedade do construtor ao alterar o protótipo

PR enviado: white_check_mark:

Este desafio provavelmente deve formatar a "propriedade do construtor" como <code>constructor</code> property para aumentar a legibilidade e a consistência. O que você acha?

Por exemplo, a mensagem de teste usa este formato.

Uma sugestão geral é substituir as instruções let por const para mostrar as práticas recomendadas. Este vídeo de @mpj explica bem!

Programação orientada a objetos: redefinir uma propriedade de construtor herdada :

PR enviado: white_check_mark:

Pequeno erro de digitação: supertype's provavelmente deve ser supertype 's

Programação orientada a objetos: use um IIFE para criar um módulo :

PR enviado: white_check_mark:

Pequeno erro de digitação: "Aqui está um exemplo de uso:" deve ser alterado para "Aqui está um exemplo de uso:"

Outra sugestão geral: acho que precisamos mudar os exemplos para que os participantes não possam simplesmente copiar o exemplo e mudar uma ou duas coisas para completar o desafio.

Os exemplos devem mostrar o conceito, mas não usar propriedades ou métodos que são usados ​​pelo próprio desafio. Dessa forma, acho que as pessoas aprenderão mais com cada desafio.

Ditch Custom CSS para Bootstrap

No sábado, 4 de fevereiro de 2017 às 21h11, Samuel Plumppu [email protected]
escrevi:

Outra sugestão geral: acho que precisamos mudar os exemplos para
os campistas não podem simplesmente copiar o exemplo e alterar 1-2 coisas para completar o
desafio.

Os exemplos devem mostrar o conceito, mas não usar propriedades ou métodos
que são usados ​​pelo próprio desafio. Assim, acho que as pessoas vão aprender
mais de cada desafio.

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/freeCodeCamp/freeCodeCamp/issues/12966#issuecomment-277463832 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AX9USApjW3rwocbHWe2yoFLV0RegbkCCks5rZL9SgaJpZM4LxApU
.

@iansibindi Parece que você está inscrito em todas as mensagens deste repositório. Para desativá-lo, visite https://github.com/freecodecamp/freecodecamp e clique em "Cancelar a observação" no canto superior direito.

Desculpe pela inconveniência!

@Greenheart Estou achando um pouco difícil seguir cada um deles mesmo com os links - acho que talvez devesse ter aberto um exemplar adicional para cada um! Eu pretendia adicionar uma lista de verificação aos comentários originais também.

Vou começar fazendo uma revisão inicial dos PRs, mas você acha que poderia adicionar um comentário a cada um dos comentários originais se eles tiverem um PR aberto para que possamos rastrear quais questões foram abordadas?

@ no-stack-dub-sack Haha, tenho que admitir que também não consigo acompanhar, apenas continuei postando! :sorriso:

Adicionarei um grande "PR aberto" (com um link para ele) no início de cada comentário WIP / corrigido.

@Greenheart Perfect! Obrigado! Eu revisei os primeiros vários PRs

@ no-stack-dub-sack Tudo bem, ainda há algumas coisas a fazer aqui, mas resolvi algumas delas hoje!

Opa, fechou de novo: rindo:

@Greenheart Uau! Um retrocesso - ainda há algo a fazer neste? Algumas melhorias importantes foram feitas!

@ no-stack-dub-sack Eu não sei - ainda há algumas coisas a serem feitas de acordo com os comentários acima, mas elas podem ter sido resolvidas em outros lugares?

Acho que ainda não foi corrigido. Deixe-me saber se você pensa o contrário

Bom trabalho a todos. Estou encerrando este problema e podemos reabrir questões mais específicas à medida que surgirem.

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

Questões relacionadas

MichaelLeeHobbs picture MichaelLeeHobbs  ·  3Comentários

imhuyqn picture imhuyqn  ·  3Comentários

ar5had picture ar5had  ·  3Comentários

robwelan picture robwelan  ·  3Comentários

vaibsharma picture vaibsharma  ·  3Comentários