Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

[Reclamação] Trilha de estudos mais elaborada (Formação Dart)

Olá. Atualmente estou fazendo a trilha Dart: cursos para aprender a linguagem utilizada no Flutter. Estou em uma etapa em que o novo instrutor está falando sobre dominar assicronismo e criando comunicação com API. Eu já havia visto um pouco disso em outra linguagem, o conceito em minha mente ficou claro mas quando se tratou de codar eu tive diversas dúvidas.

Estou seguindo fielmente a trilha de estudos desse curso, então concluí todos os projetos, li todos os artigos e realizei todas as atividades dos cursos anteriores desse para chegar nele e não compreender muito sobre o que estava sendo ensinado. Não sei se esse post se encaixaria devidamente em uma reclamação mas como estou no meio do curso... Eu também gostaria de sugerir que talvez as trilhas fossem menores e mais detalhadas, ainda mais para quem está vendo pela primeira vez.

Me recordo que quando finalizei as atividades de POO em Dart eu consegui fazer quase toda a lista de exercicíos sozinha e quando vejo os vídeos dessa de API eu não consigo entender nada que o instrutor diz. Exemplo:

Em POO aprendemos sobre como podemos utilizar List< String > listExemplo e suas outras variações de como os sinais de maior e menor são usados e isso foi devidamente explicado. "Essa primeira palavra você faz isso, você usa o sinal de mais para aquilo, o segundo é o nome..." e por ai vai.

Nesse novo curso em específico o instrutor apenas fala "aperta esse botão, ele vai criar para você o formato (um bloco de código que eu nunca tinha visto, uma função diferente, usou arrow, abriu chave, não usou ponto e virgula e sim somente virgula). Eu sei que é uma dynamic e está feito, conseguimos!". Espera, conseguimos? Tipo, eu sei que no geral coisas prontas ajudam mas eu gostaria de fato de entender o que é cada coisa. Entendo que muitas vezes temos que procurar por fora, estou lendo artigos e procurando outros vídeos e outros sites para entender melhor. Todos fazemos o curso para melhorar, entender e até mesmo conseguir um emprego e eu não acho justo assistir um vídeo que me diz que é só estalar os dedos que tá tudo pronto sem me explicar. Até me questionei se era algo que eu havia deixado passar nos cursos anteriores mas tem coisas que realmente não cheguei a ver e nem nos desafios apareceram. É um pouco frustrante eu confesso, mas nada que impeça que eu aprenda. Só gostaria de deixar minha observação para ter vídeos ou que os instrutores tenham mais cuidado, calma e paciência na hora de ensinar.

5 respostas

Oie, Evellyn! Tudo bom?

Muito obrigado por compartilhar sua experiência com a gente. Entendemos completamente a sua frustração e ficamos felizes que você esteja se dedicando tanto à trilha, concluindo os projetos, lendo os artigos e realizando todas as atividades. Isso mostra o quanto você está comprometida com o seu aprendizado!

Sobre a sua dificuldade com a parte de API e assincronismo, queremos muito te ajudar a entender melhor esses conceitos e melhorar a sua experiência no curso. Você poderia nos contar um pouco mais sobre quais partes específicas te deixaram com dúvidas? Por exemplo, tem algum trecho de código ou conceito que você tentou aplicar e não conseguiu? Ou algum ponto específico de algum vídeo que passou rápido demais e precisava de mais explicação?

Seu feedback sobre o formato das trilhas também é super válido. A gente sempre busca equilibrar profundidade e progressão do conteúdo, mas entendemos que, dependendo do conhecimento prévio de cada pessoa, algumas partes podem precisar de mais explicação. Por isso, saber exatamente onde você sentiu essa dificuldade nos ajuda a pensar em melhorias para os cursos e também a encontrar formas de te apoiar agora.

Conta pra gente um pouco mais sobre essas dificuldades e vamos juntos encontrar uma solução!

Olá!

Primeiro queria pedir desculpas pela demora na resposta. Em segundo agradecer pela atenção e a disponibilidade de tirar minhas dúvidas.

Bom, em específico na aula 2, no primeiro vídeo "Tratando resposta recebida" no minuto 5:47 é onde a parte de uma criação de lista de dinâmicos é criada. Eu cheguei a pesquisar para entender melhor mas mesmo assim não consegui compreender muito. No caso seria se eu tenho um arquivo em JSON que me da informações diferentes que podem conter strings e outros valores como double o tipo de lista deve ser como dinâmico?

Logo mais a frente, no minuto 6:52, por que usar o arrow ( => ) em vez de chaves ( {} )? Após a questão de pegar o elemento e especificar a sua chave eu compreendi, muito bem explicado por sinal. Seguindo nesse mesmo minuto eu não compreendi um pouco sobre map. Só de analisar a estrutura do JSON eu consigo identificar isso ou por ser um JSON ele já caracteriza a estrutura como map?

E então dentro desse map ele também se torna um tipo de lista? Nesse ponto acredito que eu não compreendi a sintaxe mesmo. Me recordo de ter visto no curso de introdução ao Dart mas ele foi mostrado somente como texto então não entendi muito bem a aplicabilidade dele (Map<String, dynamic>... ). Nesse caso, se é dynamic, por que incluir String também?

Agradeço desde já!

Oie, Evellyn! Não se preocupa, estamos aqui para isso! Vamos por partes tá?

Bom, em específico na aula 2, no primeiro vídeo "Tratando resposta recebida" no minuto 5:47 é onde a parte de uma criação de lista de dinâmicos é criada. Eu cheguei a pesquisar para entender melhor mas mesmo assim não consegui compreender muito. No caso seria se eu tenho um arquivo em JSON que me da informações diferentes que podem conter strings e outros valores como double o tipo de lista deve ser como dinâmico?

Isso! Toda a questão de usar dynamic está na forma que nossa biblioteca dart:convert lida com JSONs.

Primeiro vamos recapitular: um JSON é um arquivo de texto com uma formatação BEM específica: são chaves e valores. As chaves sempre serão String, porém os valores podem variar bastante, como sendo string, int, double, bool ou até estruturas como list ou map. E aí por isso, voltando ao dart:convert, a biblioteca pode até sempre saber o que é uma chave (tipo String), mas ela nunca pode ter certeza do valor, e por isso escolhe usar dynamic.

No Dart, o dynamic é uma sintaxe que permite declarar variáveis que podem mudar de valor durante a execução do programa. Isso significa que as variáveis dinâmicas podem armazenar valores de qualquer tipo de dado.

Por fim, analisando o que chegou do http.get que vimos lá no comecinho desse vídeo, conseguimos notar que se trata de uma lista, afinal, começa e termina com colchetes. Veja que essa lista é um valor, pois não contém uma chave do tipo String. Isso é tudo que podemos inferir por enquanto, já que dentro dessa lista poderiam haver maps de diferentes estruturas.

Por isso, usamos o List<dynamic> para obter o resultado convertido da resposta do servidor! :D

E depois, com a lista em mãos, conseguimos usar o firstWhere para fazer uma verificação elemento a elemento procurando qual tem a chave (tipo String) name, como valor sendo "Carla".

Logo mais a frente, no minuto 6:52, por que usar o arrow ( => ) em vez de chaves ( {} )? Após a questão de pegar o elemento e especificar a sua chave eu compreendi, muito bem explicado por sinal.

Sobre o uso da função arrow ao invés da expressão comum, admito que isso realmente passou rápido e poderia ser melhor explicado. Não há um motivo específico para termos usado a arrow nesse caso, foi uma escolha estética, além de que o autocomplete do VSCode já sugeriu direto a arrow. Mas é importante entender quando podemos usar a arrow, que se trata de quando nossa função cumpre as seguintes condições:

  • Não preciso de mais do que uma linha de código nessa função para garantir o retorno;
  • Posso usar "retorno implícito" sem prejudicar a lógica do programa;

Então por exemplo, se eu tenho a seguinte função normal:

String getMyName() {
    return "Ricarth Lima";
}

Ela atende as duas condições, possui apenas uma linha, e eu não perco nenhuma parte da lógica ao ocultar o return, então, posso simplesmente expressar essa função como:

String getMyName() => "Ricarth Lima";

Porém, analisando o caso a seguir para uma função que recebe duas listas e juntas elas em um único map, mostrando os resultados no console:

Map<String, dynamic> getAndShowPersons(List<String> listNames, List<int> listIdades){
    Map<String, dynamic> mapResult = {};
    for (int i = 0; i < listNames.length; i++){
        String name = listNames[i];
        String idade = listIdades[i];
        mapResult[name] = {"name": name, "idade": idade}
    }
    return mapResult;
}

Percebes que não teria como eu fazer isso em uma linha, e ocultar nosso return seria muito prejudicial para o entendimento da lógica da nossa função. Essa função não pode ser arrow.

Por fim, no caso do vídeo, a função firstWhere precisa encontrar o primeiro elemento da lista listAccounts que atenda a uma condição. Para isso, passamos uma função anônima (callback) como argumento, que recebe cada item da lista (element) e verifica se o campo "name" desse item é "Carla". O motivo de passarmos uma função é porque firstWhere precisa testar cada elemento da lista um por um, e a melhor forma de definir o critério de busca é com uma função. O parâmetro element representa cada item da lista conforme a função percorre os dados, permitindo que a condição seja verificada de forma dinâmica.

solução!

Seguindo nesse mesmo minuto eu não compreendi um pouco sobre map. Só de analisar a estrutura do JSON eu consigo identificar isso ou por ser um JSON ele já caracteriza a estrutura como map? E então dentro desse map ele também se torna um tipo de lista? Nesse ponto acredito que eu não compreendi a sintaxe mesmo. Me recordo de ter visto no curso de introdução ao Dart mas ele foi mostrado somente como texto então não entendi muito bem a aplicabilidade dele (Map<String, dynamic>... ). Nesse caso, se é dynamic, por que incluir String também?

Sim, exatamente! Você precisa analisar a estrutura do JSON que chega antes de começar a extrair dados em qualquer caso de uso de API durante sua vida como pessoa programadora.

Trabalhando em uma empresa, em geral, haverá uma documentação interna que já garante a estrutura das respostas do servidor, criada pelo time de back-end. Mas lidando com requisições para APIs públicas, por exemplo, precisamos ler com muito carinho com que estrutura esses dados chegam.

Para o nosso caso, a estrutura era: uma lista, contendo mapas, contendo as informações de cada pessoa usuária. Mas em outras APIs, poderia ser um map com chave "users", que aí sim conteria uma lista, algo como:

{
    "users" : [
        {
            "name": "Ricarth Lima",
            "balance": 0
        }
    ]
}

Note que, se fosse o caso, nosso código deverá mudar para atender a estrutura recebida do servidor.

No nosso caso, o nosso código primeiro converte todo esse texto (lembra que o JSON nada mais é que uma String formatada), em uma List<dynamic>, e dessa lista podemos acessar os maps. Só que, ao invés de acessar via index, como por exemplo listAccounts[0] para pegar o primeiro, já usamos um firstWhere para pegar o primeiro (e único) mapa cujo a chave "name", continha o valor "Carla". E daí, com esse mapa em mãos, poderíamos pegar qualquer outra informação de Carla e, no caso, pegamos o "balance".

No final das contas, o JSON nos garante bastante coisa, mas não tudo. Ele garante a estrutura chave-valor, ele garante a representação de lista usando colchetes, e maps usando chaves, e garante que toda chave será uma String. Mas mesmo com essas condições, a estrutura pode mudar de acordo com como o back-end nos enviou as informações, por isso, precisamos sempre estudar a resposta caso a caso antes de montar nosso código.

Espero que tenha ajudado com as dúvidas, e qualquer coisa estamos aí! :D

Ajudou muito! Agradeço pela explicação. Vou conseguir evoluir melhor daqui para a frente.