Después de años de llenar formularios y esperar, por fin conseguiste tu licencia bancaria. Esto significa que ahora ya puedes abrir oficialmente tu propio banco, ¡hurra!
Tu primera prioridad es poner en marcha los sistemas informáticos. Después de un día de duro trabajo, ya puedes abrir y cerrar cuentas, además de manejar retiros y depósitos.
Como no tenías ganas de escribir pruebas, invitas a unos amigos para que te ayuden a probar el sistema. Sin embargo, apenas cinco minutos después, ¡uno de tus amigos dice que perdió dinero! Aunque confías en que tu código no tiene errores, empiezas a revisar los registros para investigar.
Ah, claro, tal como sospechabas, ¡la culpa es de tu amigo! Compartió sus credenciales de prueba con otro amigo y juntos conspiraron para hacer depósitos y retiros de la misma cuenta en paralelo. ¿A quién se le ocurriría hacer algo así?
Mientras argumentas que es físicamente imposible que alguien acceda a su cuenta en paralelo, tu amigo te informa con aire de superioridad que las reglas bancarias exigen que lo soportes. Así que, si no hay soporte para banca en paralelo, no hay luz verde para el lanzamiento. Suspiras y te haces una nota mental para trabajar en esto mañana. Esto retrasará tu fecha de lanzamiento al menos un día más, pero bueno...
Tu tarea es implementar cuentas bancarias que permitan abrir y cerrar cuentas, hacer retiros y depositar dinero.
Como se puede acceder a las cuentas bancarias de muchas maneras distintas (internet, teléfonos móviles, cargos automáticos), tu software bancario debe permitir que se acceda a las cuentas de forma segura desde varios hilos o procesos en paralelo (la terminología depende de tu lenguaje de programación). Por ejemplo, puede haber muchos depósitos y retiros ocurriendo en paralelo; debes asegurarte de que no haya condiciones de carrera entre el momento en que lees el saldo de la cuenta y el momento en que estableces el nuevo saldo.
Debe ser posible cerrar una cuenta; las operaciones sobre una cuenta cerrada deben fallar.
Python no soporta la concurrencia «real» debido al Global Interpreter Lock. Aunque se está trabajando para crear soporte para el free-threading en Python, todavía es experimental. Las soluciones actuales de la biblioteca estándar, como multiprocessing y threading, son difíciles de implementar con las herramientas actuales del track.
Como resultado, el requisito de concurrencia se dejó de lado para este ejercicio. Las operaciones de la cuenta son secuenciales en un solo hilo, y no se ejecutan pruebas de concurrencia ni de «condiciones de carrera».
Si quieres experimentar con free-threading o con pruebas de concurrencia, te pedimos que lo hagas de forma local. Si necesitas ayuda para descargar y trabajar en los ejercicios de forma local, te recomendamos la Exercism CLI.
A veces es necesario lanzar una excepción. Cuando lo hagas, siempre debes incluir un mensaje de error significativo que indique cuál es el origen del error. Esto hace que tu código sea más legible y ayuda mucho a la hora de depurar. En los casos en los que sepas que el origen del error será de cierto tipo, puedes optar por lanzar uno de los tipos de error incorporados, pero aun así debes incluir un mensaje significativo.
Este ejercicio en particular requiere que uses la sentencia raise para «lanzar» un ValueError cuando una cuenta está abierta o no lo está, o cuando los montos de retiro o depósito son incorrectos. Las pruebas solo pasarán si tanto haces raise de la exception como incluyes un mensaje con ella.
Para lanzar un ValueError con un mensaje, escribe el mensaje como argumento del 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')
Regístrate en Exercism para aprender y dominar Python con 17 conceptos146 ejercicios y mentoría humana real, todo gratis.