「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > 演習 - 端末を使用した銀行口座のシミュレーション

演習 - 端末を使用した銀行口座のシミュレーション

2024 年 8 月 26 日に公開
ブラウズ:564

Para sair um pouco da teoria, o próximo passo no bootcamp é um exercício (que eles chamam de desafio de projeto). Achei interessante colocar uma parte prática para sedimentar o conteúdo abordado até aqui.

O que foi pedido foi para criar um projeto que simule uma única conta em um banco, contendo número da agência, número da conta, nome do cliente e saldo. Esses dados devem vir do terminal e ao final, deve ser exibida uma mensagem informando que a conta foi criada com sucesso e mostrando quais foram os dados inseridos. A descrição original pode ser vista aqui.

Bom, parece bem simples. Mas uma coisa que eu gosto muito de fazer em qualquer tarefa que eu recebo é quebrar em passos bem curtinhos, pra que eu tenha um caminho claro de onde seguir. Eu faço isso também porque enquanto estou desenhando o fluxo na minha cabeça, consigo entender se ele faz sentido com o que foi pedido e posso rapidamente mudar o curso de ação se achar que não está batendo.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Sendo assim, os passos a seguir são os seguintes:

  1. Criar uma classe para "abrigar" os dados recebidos no terminal e o método criador de conta;
  2. Pedir ao usuário os dados, ler as informações inseridas no terminal e armazená-las em variáveis;
  3. Exibir ao usuário a mensagem de confirmação, organizando as variáveis em uma string legível.

Não parece algo exatamente complexo. Começando pelo passo 1, temos o seguinte:

TerminalAccount.java

public class TerminalAccount { // eu sei, sou muito criativo
    private int branch;
    private String account;
    private String clientName;
    private double balance;

    public void createAccount(){
        // aqui a mágica acontece
    }
}

Apesar de modificadores de acesso não terem sido abordados com muita profundidade até agora no curso eu optei por deixar todos os campos privados, imaginando que em um sistema bancário, os dados de agência, conta, titular e saldo devem ser bem protegidos e só a própria classe deve ter acesso a eles.

Além disso, o método createAccount não deve retornar nada, apenas exibir uma mensagem no console, por isso seu retorno é void.
É nesse método que começa algumas das coisas que me irritam no Java. Em vez de ter um método genérico que captura qualquer tipo de informação que o usuário inserir, a classe Scanner, que é usada para isso, tem métodos específicos para cada tipo primitivo. Ou seja, tem um Scanner.nextLine() para Strings, Scanner.nextInt() para números, Scanner.nextBoolean para booleanos...

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Em comparação, no C# temos um método de entrada padrão que sempre retorna uma String, que ter seu tipo alterado em seguida:

String input = Console.ReadLine();
int.TryParse(input, out number)
Console.WriteLine(number) //completamente válido

Tem que escrever um pouco mais? Tem. Mas pelo menos eu não preciso lembrar da sintaxe de todos os métodos, basta apenas um e converter para o tipo que eu quero em seguida. Muito mais intuitivo.
Mas sigamos, que ainda tem muito chão pela frente para resolver esse problema. O próximo passo, então, é pedir para o usuário inserir os dados do cliente para o registro.

TerminalAccount.java

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  
        System.out.print("Por favor, insira o número da agência: ");  
        this.branch = sc.nextInt();  

        System.out.print("Por favor, insira o número da conta: ");  
        this.account = sc.nextLine();  

        System.out.print("Por favor, insira o nome do cliente: ");  
        this.clientName = sc.nextLine();  

        System.out.print("Por favor, insira o saldo inicial: ");  
        this.balance = sc.nextDouble();  

        System.out.println("Olá "   this.clientName   ", obrigado por criar uma conta em nosso banco. sua agência é "   this.branch   ", conta "   this.account   " e seu saldo "   this.balance   " já está disponível para saque.");  
    }  
}

Bom, aparentemente está tudo certo. Vamos instanciar essa classe no nosso método main e ver o que dá.

Main.java

public class Main {  
    public static void main(String[] args) {  
        TerminalAccount account = new TerminalAccount();  
        account.createAccount();  
    }  
}

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Oxe? Porque o input do número da conta foi ignorado e o algoritmo já pediu o nome do cliente?
Lendo a documentação da classe Scanner, é explicado que ela quebra o input em tokens usando algum tipo de caractere como delimitador, para saber onde parar. No caso dos métodos .next() e .hasNext() (e suas variantes, como o .nextInt() e o .hasNextInt()), o delimitador é um whitespace global (\s ) como espaços, tabulações e quebras de linha.

O que o método faz é pegar o token precedido pelo delimitador, converter para o tipo especificado e retornar esse valor. O resto continua no buffer do input.
Beleza, até aí ok. O problema é que o método .nextLine(), usado para capturar Strings consome o caractere de quebra de linha (\n), em vez de descartar. Aí, quando usado na sequência de outro que faz o descarte, ele lê o que ficou pra trás e imediatamente encerra sua atuação, passando para a próxima linha do código.

Parece confuso, e é mesmo. Fiz um diagrama para ajudar a compreender a loucura que é esse fluxo:

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Tá, e como consertamos essa lambança? Simples: adicionando um novo Scanner.nextLine() logo depois do .nextInt() para "limpar" o que sobrou. É bonito? Não, mas resolve.
Dá pra mudar o delimitador para aceitar a quebra de linha (\n ) em vez de um whitespace comum (\s ), mas isso poderia quebrar a forma com que as informações são quebradas em tokens, então é melhor deixar pra lá.

TerminalAccount.java

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  
        System.out.print("Por favor, insira o número da agência: ");  
        this.branch = sc.nextInt();  
        sc.nextLine();

        //...
    } 
}

Mais feio que bater na mãe.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Beleza, funcionou. Poderíamos dizer que o exercício está completo, mas vamos por um segundo imaginar que o usuário, sem querer, digitou uma letra na hora de colocar o número da agência:

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Eita lasqueira.

Isso acontece porque, como já sabemos, a tipagem do Java é estática e o Scanner está esperando um número mas quando colocamos uma letra junto com um número, essa cadeia se torna uma String. O input que estava esperando um int recebeu uma String e ficou confuso tal qual uma criança que recebe meias de presente de natal.
Exercício - Simulando Uma Conta Bancária Através Do Terminal

Para remediar essa situação, podemos criar um loop simples, que informe para o usuário que a informação que ele inseriu está incorreta de acordo com as especificações do sistema e pedir que ele insira os dados novamente (de maneira correta, dessa vez). Como não sabemos quantas tentativas o usuário vai levar para inserir os dados corretamente, um while parece adequado.

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  

        boolean isBranchNumberInputCorrect = false;  
        do {  
            try {  
                System.out.print("Por favor, insira o número da agência: ");  
                this.branch = sc.nextInt();  
                sc.nextLine();  
                isBranchNumberInputCorrect = true;  
            } catch (InputMismatchException e) {  
                System.out.println("Por favor, insira apenas números inteiros para o número da agência."); 
                sc.nextLine(); 
            }  
        } while (!isBranchNumberInputCorrect);

        //...
    }
}

Aqui criamos uma variável de controle chamada IsBranchNumberInputCorrect (porque, novamente, sou muito criativo quando se trata de nomes), inicializada em false. Em seguida, começamos o bloco do, uma vez que queremos que o código faça uma ação antes de verificar se o dado inserido é valido ou não e jogamos nosso input lá pra dentro.
Caso dê tudo certo, o dado inserido será armazenado no campo branch, qualquer caractere sobrando será consumido pelo Scanner.nextLine() e a nossa variável de controle será atualizada para true. Aí a condição do while vai checar se isBranchNumberInputCorrect é false. Se for, reinicia o loop no caso de sucesso, o laço é encerrado.

Agora, caso o usuário insira algo não esperado (como uma String), o método Scanner.nextInt() vai emitir um evento de erro InputMismatchException, que será capturado pelo nosso bloco catch. Uma vez lá dentro, o código vai exibir uma mensagem de erro alertando que o tipo de dado está errado e consumido qualquer caractere que tenha ficado pra trás.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

A gente pode fazer a mesma coisa com o input de saldo, para garantir que o valor inserido sempre será numérico e não permitir que a aplicação quebre caso seja inserido algo como 12,56f:

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in); 

        //...

        boolean isBalanceInputCorrect = false;  
        do {  
            try {  
                System.out.print("Por favor, insira o saldo inicial: ");  
                this.balance = sc.nextDouble();  
                sc.nextLine();  
                isBalanceInputCorrect = true;  
            } catch (InputMismatchException e) {  
                System.out.println("Por favor, insira apenas valores decimais.");  
                sc.nextLine();  
            }  
        } while (!isBalanceInputCorrect);  

        //...
    }  
}

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Poderíamos parar por aqui e dar esse exercício como encerrado, mas ainda tem um bug que requer um pouco de atenção. O que aconteceria se, em vez de delimitarmos nosso saldo com uma vírgula (,) usássemos um ponto (por exemplo, 10.56)?

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Isso acontece devido ao locale, a adaptação do input à cultura do local. Aqui no Brasil, o decimal é delimitado pela vírgula, então o método não entende que essa separação com ponto é válida.
A documentação da classe Scanner nos mostra que é possível alterar a cultura para uma que atenda ou um ou outro padrão, mas não os dois ao mesmo tempo. Também é possível alterar especificamente o delimitador, para um símbolo ou para outro, mas não os dois ao mesmo tempo.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Um dos métodos para solucionar esse problema não é muito elegante, mas resolve: em vez de capturar o dado diretamente como double, vamos usar o método Scanner.nextLine() para pegar o input como uma String, trocar os pontos por vírgula e tentar trocar o tipo para double.

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  

        //...
        boolean isBalanceInputCorrect = false;  
        do {  
            try {  
                System.out.print("Por favor, insira o saldo inicial: ");  
                String balanceString = sc.nextLine().replace(",", ".");  
                this.balance = Double.parseDouble(balanceString);  
                isBalanceInputCorrect = true;  
            } catch (NumberFormatException e) {  
                System.out.println("Por favor, insira apenas valores decimais.");  
            }  
        } while (!isBalanceInputCorrect);  

        //...

    }  
}

Além da alteração do método de captura do dado, tivemos mais algumas modificações: retiramos as chamadas para o método Scanner.nextLine() que serviam apenas para consumir os caracteres remanescentes, porque nosso input já faz isso pra gente. Além disso, o tipo do erro mudou: agora não se trata de um erro de incompatibilidade de tipo (InputMismatchException), mas sim um de erro no formato do número (NumberFormatException).
Com essas alterações feitas, bora ver se tudo deu certo:

Exercício - Simulando Uma Conta Bancária Através Do Terminal
Exercício - Simulando Uma Conta Bancária Através Do Terminal

Exercício - Simulando Uma Conta Bancária Através Do Terminal
Deu tudo certo! Com isso, conseguimos dizer que o exercício está concluído (finalmente)!
O repositório desse exercício está disponível aqui caso tenha interesse de ver.

E é isso. Até o próximo módulo!

リリースステートメント この記事は次の場所に転載されています: https://dev.to/lnabesima/exercicio-simulando-uma-conta-bancaria-atraves-do-terminal-23e4?1 侵害がある場合は、削除するために[email protected]に連絡してください。それ
最新のチュートリアル もっと>
  • Spring AOP の内部動作を明らかにする
    Spring AOP の内部動作を明らかにする
    この投稿では、Spring のアスペクト指向プログラミング (AOP) の内部メカニズムをわかりやすく説明します。多くの場合「魔法」の一種と考えられるロギングなどの機能を AOP がどのように実現するかを理解することに焦点を当てます。コア Java 実装を実際に見てみると、本当に魔法のようなものでは...
    プログラミング 2024 年 11 月 6 日に公開
  • JavaScript Eリリースノート: 最新の JavaScript の力を解き放つ
    JavaScript Eリリースノート: 最新の JavaScript の力を解き放つ
    正式には ECMAScript 2015 として知られる JavaScript ES6 には、開発者が JavaScript を記述する方法を変革する重要な機能強化と新機能が導入されました。ここでは、ES6 を定義し、JavaScript でのプログラミングをより効率的で楽しいものにした上位 20 ...
    プログラミング 2024 年 11 月 6 日に公開
  • Javascript の POST リクエストを理解する
    Javascript の POST リクエストを理解する
    function newPlayer(newForm) { fetch("http://localhost:3000/Players", { method: "POST", headers: { 'Content-Type': 'application...
    プログラミング 2024 年 11 月 6 日に公開
  • Savitzky-Golay フィルタリングを使用してノイズの多い曲線を滑らかにする方法
    Savitzky-Golay フィルタリングを使用してノイズの多い曲線を滑らかにする方法
    ノイズの多いデータの曲線の平滑化: Savitzky-Golay フィルタリングの探索データセットの分析を追求する中で、ノイズの多い曲線を平滑化するという課題が生じます。明瞭さを高め、根底にあるパターンを明らかにします。このタスクに特に効果的な方法の 1 つは、Savitzky-Golay フィルタ...
    プログラミング 2024 年 11 月 6 日に公開
  • 可変引数メソッドのオーバーロード
    可変引数メソッドのオーバーロード
    可変引数メソッドのオーバーロード 可変長の引数を取るメソッドをオーバーロードできます。 このプログラムは、可変引数メソッドをオーバーロードする 2 つの方法を示しています: 1 さまざまな varargs パラメーター タイプ: vaTest(int...) や vaTest(boolean...)...
    プログラミング 2024 年 11 月 6 日に公開
  • クラシック クラス コンポーネント内で React フックを活用するにはどうすればよいですか?
    クラシック クラス コンポーネント内で React フックを活用するにはどうすればよいですか?
    React フックとクラシック クラス コンポーネントの統合React フックはクラスベースのコンポーネント設計の代替手段を提供しますが、既存のクラスに組み込むことで徐々に採用することができます。コンポーネント。これは、高次コンポーネント (HOC) を使用して実現できます。次のクラス コンポーネン...
    プログラミング 2024 年 11 月 6 日に公開
  • Vite と React を使用して高速なシングル ページ アプリケーション (SPA) を構築する方法
    Vite と React を使用して高速なシングル ページ アプリケーション (SPA) を構築する方法
    現代の Web 開発の世界では、シングル ページ アプリケーション (SPA) が、動的で読み込みの速い Web サイトを作成するための一般的な選択肢となっています。 React は、ユーザー インターフェイスを構築するために最も広く使用されている JavaScript ライブラリの 1 つであり、...
    プログラミング 2024 年 11 月 6 日に公開
  • JavaScript での文字列連結のステップバイステップ ガイド
    JavaScript での文字列連結のステップバイステップ ガイド
    JavaScript における文字列の連結 は、2 つ以上の文字列を結合して 1 つの文字列を形成するプロセスです。このガイドでは、演算子、= 演算子、concat() メソッド、テンプレート リテラルの使用など、これを実現するためのさまざまな方法を説明します。 各メソッドはシンプルかつ効果的で...
    プログラミング 2024 年 11 月 6 日に公開
  • Web UX: ユーザーに意味のあるエラーを表示する
    Web UX: ユーザーに意味のあるエラーを表示する
    ユーザー主導でユーザーフレンドリーな Web サイトを作成することは、開発チーム全体が機能やコア ビジネスに価値を付加しないことに多くの時間を費やすことになるため、場合によっては難しい場合があります。しかし、短期的にはユーザーを助け、長期的には価値を付加することができます。納期に厳格なプロジェクト ...
    プログラミング 2024 年 11 月 6 日に公開
  • 小規模クラスのマニピュレーター
    小規模クラスのマニピュレーター
    Small Class マニピュレータの新しいメジャー リリース コードは完全にリファクタリングされ、属性操作の新しいサポートがコーディングされました これは操作の例です: $classFile = \Small\ClassManipulator\ClassManipulator::from...
    プログラミング 2024 年 11 月 6 日に公開
  • 機械学習プロジェクトにおける効果的なモデルのバージョン管理
    機械学習プロジェクトにおける効果的なモデルのバージョン管理
    機械学習 (ML) プロジェクトにおいて、最も重要なコンポーネントの 1 つはバージョン管理です。従来のソフトウェア開発とは異なり、ML プロジェクトの管理にはソース コードだけでなく、時間の経過とともに進化するデータとモデルも関係します。そのため、実験を管理し、最適なモデルを選択し、最終的に実稼働...
    プログラミング 2024 年 11 月 6 日に公開
  • PHPでキーを保持しながら列の値で連想配列をグループ化するにはどうすればよいですか?
    PHPでキーを保持しながら列の値で連想配列をグループ化するにはどうすればよいですか?
    キーを保持しながら列の値で連想配列をグループ化するそれぞれが「id」などの属性を持つエンティティを表す連想配列の配列を考えます。そして「名前」。課題は、元のキーを維持しながら、特定の列 'id' に基づいてこれらの配列をグループ化することです。これを実現するには、PHP の fore...
    プログラミング 2024 年 11 月 6 日に公開
  • Gradle で特定の推移的な依存関係を除外する方法は?
    Gradle で特定の推移的な依存関係を除外する方法は?
    Gradle での推移的な依存関係の除外Gradle では、アプリケーション プラグインを使用して jar ファイルを生成するときに、次のような推移的な依存関係が発生する可能性があります。除外したい場合があります。これを実現するには、exclude メソッドを使用できます。Exclude のデフォル...
    プログラミング 2024 年 11 月 6 日に公開
  • ミニマリスト生活の芸術
    ミニマリスト生活の芸術
    ミニマリストの暮らしとは何ですか? ミニマリスト生活とは、意図的に所有物の数や生活の中の物を減らすライフスタイルです。それは単に空間を整理整頓することではなく、生活をシンプルにし、本当に重要なことに集中し、気を散らすものを減らすことでもあります。 なぜミニマリズムを...
    プログラミング 2024 年 11 月 6 日に公開
  • Java 難読化パズル
    Java 難読化パズル
    Come play with our Java Obfuscator & try to deobfuscate this output. The price is the free activation code! Obfuscated Java code Your goal...
    プログラミング 2024 年 11 月 6 日に公開

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3