Depois de anos preenchendo formulários e esperando, você finalmente conseguiu sua licença bancária. Isso significa que agora você está oficialmente apto a abrir seu próprio banco, ebaaa!
Sua primeira prioridade é pôr os sistemas de TI para funcionar. Depois de um dia de trabalho puxado, você já consegue abrir e fechar contas, além de lidar com saques e depósitos.
Como você não quis se dar ao trabalho de escrever testes, você convida alguns amigos para ajudar a testar o sistema. Mas, depois de apenas cinco minutos, um dos seus amigos afirma que perdeu dinheiro! Embora você tenha certeza de que seu código não tem bugs, você começa a examinar os logs para investigar.
Ah, sim, exatamente como você suspeitava: a culpa é do seu amigo! Ele compartilhou as credenciais de teste com outro amigo, e juntos eles conspiraram para fazer depósitos e saques na mesma conta em paralelo. Quem faria uma coisa dessas?
Enquanto você argumenta que é fisicamente impossível alguém acessar a própria conta em paralelo, seu amigo avisa, com um ar de superioridade, que as regras bancárias exigem que você dê esse suporte. Ou seja: sem suporte a operações bancárias em paralelo, sem sinal verde para entrar em funcionamento. Suspirando, você faz uma nota mental para trabalhar nisso amanhã. Isso vai adiar sua data de lançamento em pelo menos mais um dia, mas, bem...
Sua tarefa é implementar contas bancárias com suporte a abertura e fechamento, saques e depósitos de dinheiro.
Como as contas bancárias podem ser acessadas de muitas formas diferentes (internet, celulares, cobranças automáticas), o software do seu banco precisa permitir que as contas sejam acessadas com segurança a partir de várias threads/processos (a terminologia depende da sua linguagem de programação) em paralelo. Por exemplo, pode haver muitos depósitos e saques acontecendo em paralelo; você precisa garantir que não haja condições de corrida entre o momento em que você lê o saldo da conta e o momento em que define o novo saldo.
Deve ser possível fechar uma conta; operações em uma conta fechada devem falhar.
O Python não oferece suporte a concorrência "verdadeira" por causa do Global Interpreter Lock. Embora haja trabalho em andamento para criar suporte a free-threading no Python, isso ainda é experimental. As soluções atuais da biblioteca padrão, como multiprocessing e threading, são difíceis de implementar com as ferramentas atuais da trilha.
Por isso, o requisito de concorrência foi deixado de lado neste exercício. As operações de conta são sequenciais, em uma única thread, e não são executados testes de concorrência nem de "condição de corrida".
Se você quiser experimentar free-threading ou testes de concorrência, pedimos que faça isso localmente. Para ajuda com o download e o trabalho nos exercícios localmente, recomendamos a Exercism CLI.
Às vezes é necessário lançar uma exceção. Quando você faz isso, deve sempre incluir uma mensagem de erro significativa para indicar qual é a origem do erro. Isso deixa seu código mais legível e ajuda bastante na depuração. Em situações nas quais você sabe que a origem do erro será de um determinado tipo, você pode optar por lançar um dos tipos de erro embutidos, mas ainda assim deve incluir uma mensagem significativa.
Este exercício em particular exige que você use a instrução raise para "lançar" um ValueError quando uma conta estiver aberta ou não estiver, ou quando os valores de saque/depósito estiverem incorretos. Os testes só passarão se você raise a exception e incluir uma mensagem junto.
Para lançar um ValueError com uma mensagem, escreva a mensagem como argumento do tipo exception:
# account is not open
raise ValueError('account not open')
# account is already open
raise ValueError('account already open')
# incorrect withdrawal/deposit amount
raise ValueError('amount must be greater than 0')
# withdrawal is too big
raise ValueError('amount must be less than balance')
Crie sua conta no Exercism para aprender e dominar Python com 17 conceitos146 exercícios e mentoria humana de verdade, tudo de graça.