2
respostas

[Projeto] Refatorando a organização de livros

// Refatorando a organização de livros (sistema de catalogação)

// catálogo
var catalogo = new Dictionary<string, Dictionary<string, string>>
{
    { "Ficção Científica", new Dictionary<string, string>
        {
            { "10", "Duna" }
        }
    },
    { "Literatura Clássica", new Dictionary<string, string>
        {
            { "20", "Dom Quixote" }
        }
    },
    { "Fantasia", new Dictionary<string, string>
        {
            { "30", "O Senhor dos Anéis" }
        }   
    },
    { "Romance", new Dictionary<string, string>
        {
            { "40", "Orgulho e Preconceito" }
        }
    },
    { "Suspense/Mistério", new Dictionary<string, string>
        {
            { "50", "O Assassinato de Roger Ackroyd" }
        }
    },
    { "Não ficção", new Dictionary<string, string>
        {
            { "60", "Sapiens: Uma Breve História da Humanidade" }
        }
    },
    { "Biografias/Memórias", new Dictionary<string, string>
        {
            { "70", "O Diário de Anne Frank" }
        }
    },
    { "Distopia", new Dictionary<string, string>
        {
            { "80", "1984” – George Orwell" }
        }
    },
    { "Infantojuvenil", new Dictionary<string, string>
        {
            { "90", "Harry Potter e a Pedra Filosofal" }
        }
    },
};
// função que exibe as opções sistema de catalogação
void ExibirMenu()
{
    Console.Clear();
    Console.WriteLine("Bem vindo ao Catálogo Biblioteca Universitária.\n");
    Console.WriteLine("Exibir todos os livros registrados - 1");
    Console.WriteLine("Registrar um novo livro - 2");
    Console.WriteLine("Pesquisar um livro - 3");
    Console.WriteLine("Sair - 4");
    Console.Write("\nInforme a opção desejada: ");
    byte opcao = ValidacaoNumerica();
    AcoesDoMenu(opcao);
}

// função que controla o fluxo do menu
void AcoesDoMenu(byte opcaoEscolhida)
{
    switch (opcaoEscolhida)
    {
        case 1: ExibirCatalogo(); break;
        case 2: RegistrarLivro(); break;
        case 3: FiltrarLivro(); break;
        case 4: EncerrarSistema(); break;
        default: throw new InvalidOperationException("Valor inesperado recebido.");
    }
}
2 respostas
//funções das ações do menu
void ExibirCatalogo ()
{
    Console.Clear();
    Console.WriteLine("Catálo de livros atualizado.");

    foreach (var categoria in catalogo)
    {
        Console.WriteLine($"\nCategoria - {categoria.Key}\n");

        foreach (var livro in categoria.Value)
        {
            Console.WriteLine($"Código: {livro.Key} | Título: {livro.Value}");
        }
    }

    Console.Write("\nAperter qualquer tecla para voltar ao menu: ");
    Console.ReadKey();
    ExibirMenu();
}

void RegistrarLivro ()
{
    Console.Clear();
    byte contador = 0;
    Console.WriteLine("Categorias (1 - 9):  \n");

    foreach (var categoria in catalogo)
    {
        Console.WriteLine($"{++contador} - {categoria.Key}");
    }

    Console.Write("\nInfome o código: ");
    char codigoInformado = char.Parse(ValidarString());
    Console.Write("Informe o título do livro: ");
    string tituloDoLivro = ValidarString();
    string categoriaSelecionada = VerificarCategoria(codigoInformado);

    if (catalogo[categoriaSelecionada].ContainsValue(tituloDoLivro))
    {
        Console.WriteLine("Esta livro já esta registrado.");
        Thread.Sleep(1500);
        ExibirMenu();
    }
    else
    {
        catalogo[categoriaSelecionada].Add($"{codigoInformado}{catalogo[categoriaSelecionada].Count}", tituloDoLivro);
        Console.WriteLine("O novo livro foi cadastrado com sucesso!");
        Thread.Sleep(2000);
        ExibirMenu();
    }  
}

void FiltrarLivro ()
{
    Console.Clear();
    Console.WriteLine("Informe o código do livro:");
    string codigoDoLivro = ValidarString();
    string categoria = VerificarCategoria(codigoDoLivro[0]);

    if (catalogo[categoria].ContainsKey(codigoDoLivro))
    {
        Console.WriteLine($"\n{catalogo[categoria][codigoDoLivro]} - {categoria}");
        Console.Write("\nPrecione qualquer tecla para voltar ao menu.");
        Console.ReadKey();
        ExibirMenu();
    }
    else
    {
        Console.WriteLine("O código informado não corresponde a nennhum livro do catálogo.");
        Thread.Sleep(2000);
        ExibirMenu();
    }
}

string VerificarCategoria (char codigo)
{
    string categoria = codigo switch
    {
        '1' => "Ficção Científica",
        '2' => "Literatura Clássica",
        '3' => "Fantasia",
        '4' => "Romance",
        '5' => "Suspense/Mistério",
        '6' => "Não ficção",
        '7' => "Biografias/Memórias",
        '8' => "Distopia",
        '9' => "Infantojuvenil",
        _ => throw new InvalidOperationException("Valor inesperado recebido.")
    };

    return categoria;
}

void EncerrarSistema ()
{
    Console.WriteLine("Encerrando sistema...");
    Thread.Sleep(2000);
    Environment.Exit(0);
} 

// funções para validar dados
string ValidarString ()
{
    while(true)
    {
        string entrada = Console.ReadLine()!;

        if (!string.IsNullOrWhiteSpace(entrada))
        {
            return entrada;
        }

        Console.WriteLine("Informação inválida, tente novamente.");
    }

}

byte ValidacaoNumerica()
{
    while (true)
    {
        bool valido = byte.TryParse(Console.ReadLine(), out byte opcao);

        if (valido && (opcao >= 1 && opcao <= 4))
        {
            return opcao;
        }
        else
        {
            Console.WriteLine("Entrada invalida");
        }
    }
}

ExibirMenu();

Olá, José!

Parabéns pela construção do seu sistema de catalogação de livros.

Sua solução demonstra um excelente nível de maturidade técnica. O uso do switch expression no método VerificarCategoria é um ótimo exemplo de como aplicar os recursos modernos do C# para deixar a leitura do código limpa. E, a preocupação em criar métodos específicos para validação de dados, como ValidarString e ValidacaoNumerica, eleva a segurança da aplicação, impedindo que entradas vazias ou tipos incorretos quebrem a execução.

Uma observação interessante sobre o fluxo do programa: ao chamar ExibirMenu() no final de funções como ExibirCatalogo ou RegistrarLivro, o sistema realiza chamadas recursivas indiretas. Em aplicações de terminal muito longas, isso pode preencher a pilha de memória. Uma alternativa comum para gerenciar esse ciclo de telas é utilizar um laço de repetição tradicional no método principal.

Na sua visão, trabalhar com essa estrutura de dicionário aninhado trouxe vantagens na hora de buscar o livro pelo código em comparação com o uso de uma lista única de objetos?

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!