Prática: aulas e coleções

1. Antes de começar

Neste módulo, você aprendeu sobre generalizações, diferentes tipos de classes, coleções e funções de ordem superior. Para praticar o que aprendeu, você vai ajudar sua equipe a melhorar o novo app de acompanhamento de eventos. As instruções para cada etapa descrevem o estado atual do app e a tarefa que você precisa concluir.

É recomendável usar o Playground Kotlin para resolver esses exercícios.

Pré-requisitos

  • Conclua a Unidade 3, Módulo 1 do curso Noções básicas do Android com o Compose e os módulos anteriores.
  • Conhecer a linguagem de programação Kotlin, incluindo classes, objetos, coleções e funções de ordem superior.

Pré-requisitos

2. Visão geral do app

Você começou a trabalhar na engenharia de software da equipe que criou o app de acompanhamento de eventos. O objetivo desse app é permitir que os usuários acompanhem os próprios eventos. Sua equipe vai atribuir tarefas para ajudar você a aprimorar a funcionalidade do app.

No final de cada tarefa, compare sua solução com a fornecida. Há diferentes maneiras de alcançar a funcionalidade desejada, então não se preocupe caso seu código não seja exatamente igual ao código da solução fornecido.

Use o código da solução fornecido na tarefa anterior como o código inicial da tarefa seguinte para que haja um ponto de partida comum.

3. Tarefa 1

Outro engenheiro de software já concluiu algumas tarefas de alto nível no app e você é responsável por implementar os detalhes.

É necessário implementar a classe Event. Ela é usada para armazenar os detalhes do evento inserido pelo usuário. Dica: essa classe não precisa definir métodos nem executar ações.

Para essa tarefa, você precisa criar uma classe de dados chamada Event.

Uma instância dessa classe precisa armazenar o seguinte:

  • Título do evento como uma string.
  • Descrição do evento como uma string (pode ser nula).
  • Período do dia como uma string. Só precisamos monitorar se o evento começa de manhã, à tarde ou à noite.
  • Duração do evento em minutos como um número inteiro.

Antes de continuar, tente escrever o código por conta própria.

Usando seu código, crie uma instância com as seguintes informações:

  • Título: estudar Kotlin
  • Descrição: comprometer-se a estudar Kotlin pelo menos 15 minutos por dia.
  • Período do dia: noite
  • Duração: 15

Imprima o objeto para confirmar se apareceu o seguinte resultado:

Event(title=Study Kotlin, description=Commit to studying Kotlin at least 15 minutes per day., daypart=Evening, durationInMinutes=15)

Depois de concluir a tarefa ou fazer o melhor possível, clique em Avançar para ver como a codificamos.

4. Solução da tarefa 1

Sua solução será parecida com esta:

data class Event(
    val title: String,
    val description: String? = null,
    val daypart: String,
    val durationInMinutes: Int,
)

5. Tarefa 2

Para manter o projeto no caminho certo, o gerente decide usar o código fornecido para a classe de dados.

Depois da classe Event ser usada por algum tempo, o colega de trabalho sênior percebe que usar uma string para o período do dia não é o ideal.

Alguns desenvolvedores armazenaram o valor de "Morning", alguns usaram "morning" e outros usaram "MORNING".

Isso causou muitos problemas.

Sua tarefa é corrigir o problema com uma refatoração. A refatoração é o processo de melhorar o código sem mudar a função dele. Alguns exemplos são simplificar a lógica ou mover código repetido para funções separadas.

Que tipo de classe pode ser usada para modelar um conjunto limitado de valores distintos para ajudar a corrigir esse problema?

Sua equipe quer que você mude o código do período do dia e passe a usar uma classe de enumeração. Ao usar uma classe desse tipo, seus colegas de equipe são obrigados a escolher um dos valores fornecidos de período do dia, o que evita esse tipo de problema.

O nome da classe de enumeração deve ser Daypart. Ela precisa ter três valores:

  • MORNING
  • AFTERNOON
  • EVENING

Como você criaria essa classe de enumeração?

Como faria a refatoração da classe Event para usá-la?

Tente codificar a solução agora antes de continuar.

Clique em Avançar para ver como a codificamos.

6. Solução da tarefa 2

enum class Daypart {
    MORNING,
    AFTERNOON,
    EVENING,
}

A classe de dados Event refatorada agora usa a classe de enumeração:

data class Event(
    val title: String,
    val description: String? = null,
    val daypart: Daypart,
    val durationInMinutes: Int,
)

7. Tarefa 3

Seus colegas gostam de usar o Daypart refatorado, mas eles têm outros problemas.

O código a seguir mostra como eles criam e armazenam os eventos do usuário.

val event1 = Event(title = "Wake up", description = "Time to get up", daypart = Daypart.MORNING, durationInMinutes = 0)
val event2 = Event(title = "Eat breakfast", daypart = Daypart.MORNING, durationInMinutes = 15)
val event3 = Event(title = "Learn about Kotlin", daypart = Daypart.AFTERNOON, durationInMinutes = 30)
val event4 = Event(title = "Practice Compose", daypart = Daypart.AFTERNOON, durationInMinutes = 60)
val event5 = Event(title = "Watch latest DevBytes video", daypart = Daypart.AFTERNOON, durationInMinutes = 10)
val event6 = Event(title = "Check out latest Android Jetpack library", daypart = Daypart.EVENING, durationInMinutes = 45)

A equipe criou muitos eventos e cada um deles exige a própria variável. Conforme mais eventos são criados, fica mais difícil acompanhar todos eles. Com essa abordagem, seria difícil determinar quantos eventos o usuário programou?

Você consegue pensar em uma forma melhor de organizar o armazenamento desses eventos?

Como armazenar todos os eventos em uma variável? Observação: ela precisa ser flexível, porque é possível que mais eventos sejam adicionados. Ela também precisa retornar com eficiência a contagem do número de eventos armazenados na variável.

Qual classe ou tipo de dados você usaria? Como adicionaria mais eventos?

Agora é sua vez de implementar esse recurso. Escreva o código antes de clicar em Avançar para ver nossa solução.

8. Solução da tarefa 3

val events = mutableListOf<Event>(event1, event2, event3, event4, event5, event6)

9. Tarefa 4

Seu gerente gosta do uso do app, mas decide que o usuário precisa acessar um resumo dos eventos curtos dele, com base na duração. Por exemplo, "Você tem cinco eventos curtos".

Um evento "curto" tem menos de 60 minutos.

Usando o código da variável events da solução da tarefa anterior, como você conseguiria esse resultado?

Clique em Avançar para acessar nossa solução.

10. Solução da tarefa 4

Há várias maneiras de fazer isso, e optamos pela seguinte:

val shortEvents = events.filter { it.durationInMinutes < 60 }
println("You have ${shortEvents.size} short events.")

11. Tarefa 5

Seus colegas de equipe gostam do app, mas querem que os usuários consigam acessar um resumo de todos os eventos e o período do dia deles.

A resposta precisa ser semelhante a esta:

Morning: 3 events
Afternoon: 4 events
Evening: 2 events

Usando o código da variável events da etapa anterior, como você pode atingir esse resultado?

Clique em Avançar para conferir o código da solução.

12. Solução da tarefa 5

Nossa solução é apresentada a seguir, mas outras variações são aceitáveis.

val groupedEvents = events.groupBy { it.daypart }
groupedEvents.forEach { (daypart, events) ->
    println("$daypart: ${events.size} events")
}

13. Tarefa 6

Atualmente, seu colega encontra e imprime o último item usando o índice dele. O código usado é: println("Last event of the day: ${events[events.size - 1].title}").

O gerente sugere consultar a documentação do Kotlin para encontrar uma função que possa simplificar esse código.

Qual função você encontrou?

Use-a para confirmar que você recebe os mesmos resultados.

Clique em Avançar para ver a solução.

14. Solução da tarefa 6

println("Last event of the day: ${events.last().title}")

15. Tarefa 7

Sua equipe gosta da classe de dados que você criou, mas acha repetitivo programar o código sempre que precisa da duração de um evento como uma string:

val durationOfEvent = if (events[0].durationInMinutes < 60) {
        "short"
    } else {
        "long"
    }
println("Duration of first event of the day: $durationOfEvent")

É possível corrigir essa repetição adicionando um método diretamente à classe. Mas isso não é o ideal a fazer, porque outras equipes começaram a usar a classe de eventos nos apps delas. Se a classe mudar, elas precisarão testar o código inteiro novamente para garantir que não haja falhas.

Sem mudar diretamente a classe de dados, como você pode escrever uma propriedade de extensão que retorne os mesmos valores do código acima?

Quando implementado corretamente, você vai poder usar o código a seguir. Ele vai imprimir a mesma mensagem que o código mostrado no início desta tarefa.

println("Duration of first event of the day: ${events[0].durationOfEvent}")

Clique em Avançar para exibir a solução.

16. Solução da tarefa 7

val Event.durationOfEvent: String
    get() = if (this.durationInMinutes < 60) {
        "short"
    } else {
        "long"
    }

17. Mais exercícios

Para praticar mais sobre a linguagem Kotlin, confira a faixa principal de Kotlin da JetBrains Academy. Para ir a um tópico específico, acesse o mapa de conhecimento (links em inglês) e confira a lista de temas abordados na faixa.