پس از سالها پر کردن فرم و انتظار کشیدن، بالاخره مجوز بانکی خود را گرفتهاید. یعنی حالا رسماً میتوانید بانک خودتان را باز کنید، هورا!
اولین اولویتتان راهاندازی سیستمهای فناوری اطلاعات است. پس از یک روز کار سخت، هماکنون میتوانید حساب باز کنید و ببندید و همچنین برداشتها و واریزها را انجام دهید.
چون حوصلهی نوشتن Test را نداشتید، از چند دوست میخواهید که در آزمایش سیستم کمکتان کنند. اما فقط پنج دقیقه بعد، یکی از دوستانتان ادعا میکند که پول از دست داده است! هرچند مطمئنید که کدتان بدون Bug است، شروع میکنید لاگها را بررسی کنید تا بفهمید چه شده است.
آهان، دقیقاً همانطور که حدس میزدید، مقصر خود دوستتان است! او اطلاعات ورود آزمایشیاش را با دوست دیگری به اشتراک گذاشت و با هم توطئه کردند تا بهصورت موازی از همان حساب واریز و برداشت انجام دهند. چه کسی چنین کاری میکند؟
در حالی که شما بحث میکنید که از نظر فیزیکی غیرممکن است کسی بهصورت موازی به حساب خود دسترسی پیدا کند، دوستتان با خودپسندی به شما اطلاع میدهد که قوانین بانکی ملزمتان میکند که از این پشتیبانی کنید. بنابراین، بدون پشتیبانی از بانکداری موازی، سیگنالی برای راهاندازی در کار نیست. آهی میکشید و در ذهن خود یادداشت میکنید که فردا به این موضوع رسیدگی کنید. این کار تاریخ راهاندازی شما را حداقل یک روز دیگر عقب میاندازد، اما خب...
وظیفهی شما پیادهسازی حسابهای بانکیای است که از باز کردن و بستن، برداشت و واریز پول پشتیبانی میکنند.
از آنجا که میتوان از راههای گوناگون به حسابهای بانکی دسترسی داشت (اینترنت، تلفن همراه، کسرهای خودکار)، نرمافزار بانکی شما باید طوری باشد که بتوان بهطور موازی و ایمن از چند ریسمان/فرایند (اصطلاح آن بسته به زبان برنامهنویسی شما متفاوت است) به حسابها دسترسی داشت. برای نمونه، ممکن است واریزها و برداشتهای زیادی بهطور موازی رخ دهند؛ باید مطمئن شوید که میان خواندن موجودی حساب و تنظیم موجودی جدید، «شرایط رقابتی» رخ نمیدهد.
بستن حساب باید ممکن باشد؛ عملیاتی که روی حساب بسته انجام میشود باید با شکست مواجه شود.
Python به دلیل Global Interpreter Lock از «همزمانیِ واقعی» پشتیبانی نمیکند. هرچند کار برای پشتیبانی از free-threading در Python در جریان است، این قابلیت هنوز آزمایشی است. پیادهسازی راهحلهای کنونی کتابخانهی استاندارد، مانند multiprocessing و threading، با ابزارهای فعلی این track دشوار است.
در نتیجه، الزام همزمانی برای این تمرین کنار گذاشته شده است. عملیات حساب بهصورت ترتیبی و روی یک thread واحد انجام میشود و هیچ test همزمانی یا «شرایط رقابتی» اجرا نمیشود.
اگر میخواهید free-threading یا testهای همزمانی را آزمایش کنید، از شما میخواهیم این کار را بهصورت محلی انجام دهید. برای کمک در دانلود و کار کردن روی تمرینها بهصورت محلی، Exercism CLI را توصیه میکنیم.
گاهی لازم است استثنا ایجاد کنید. وقتی این کار را میکنید، همیشه باید یک پیام خطای معنادار بگنجانید تا نشان دهید منبع خطا چیست. این کار code شما را خواناتر میکند و کمک زیادی به debugging میکند. در موقعیتهایی که میدانید منبع خطا نوع مشخصی دارد، میتوانید یکی از انواع خطای توکار را ایجاد کنید، اما باز هم باید پیامی معنادار بگنجانید.
این تمرین بهطور خاص میخواهد که از دستور raise برای «پرتاب» یک ValueError استفاده کنید، آن هم وقتی که حساب باز است یا باز نیست، یا مقدار برداشت یا واریز نادرست است. tests تنها در صورتی پاس میشوند که هم exception را raise کنید و هم پیامی همراه آن بگنجانید.
برای اینکه یک ValueError را همراه با پیام ایجاد کنید، پیام را بهعنوان آرگومان به نوع 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')