اشتباهات برنامهنویسها معمولاً بخشودنی هستند. آنهادر طول کار روزانه باگهای زیادی ایجاد میکنند یا در طراحی نرمافزار دچار خطا میشوند؛ خطاهایی که اغلب در بازبینی کد (Code Review) توسط افراد باتجربهتر شناسایی و برطرف میشوند. با این حال، برخی اشتباهات به دلیل پیامدهای جدی و هزینههای بالایی که به همراه دارند نابخشودنی هستند...
پس از استقبالات فراوان از سری اول رویداد #المپیکفناوری پردیس، دستاندرکاران مجموعه پارک علموفناوری پردیس به فکر بازگشایی یک فروشگاه جدید و مجهز برای برطرف کردن نیازهای زندگی برنامهنویسانهی اهالی این پارک فناوری و به ویژه شرکتکنندگان سری جدید مسابقات #المپیکفناوری پردیس افتادند. این فروشگاه که پس از راهاندازی، بعدها توسط پردیسیون (Pardision) به پردیس شاپ (Pardis Shop) معروف شد هرآنچه که یک برنامهنویس در زندگیاش به آن نیاز داشت، از انواع و اقسام تنقلات تا کیبوردهای مکانیکال به آنها ارائه میکرد.
پردیس شاپ، که به مرور زمان به یکی از معروفترین فروشگاههای ناحیه فناوری پردیس تبدیل شد، همواره از نبود یک فروشگاه آنلاین برای ارائه تجربهای بهتر و خدماتی بیشتر به مشتریانش رنج برده است. علی میو (Ali Meow) یکی از پردیسیونی است که به واسطه علاقهاش به گربهها (که محبوبترین حیوانات خانگی نزد برنامهنویسها هستند) طرفداران زیادی دارد، به عنوان مسئول طراحی وبسایت پردیس شاپ انتخاب شده و کارش را از مدتها قبل از برگزاری سری دوم المپیکفناوری پردیس شروع کرده است.

علی میو برای مدیریت کاربران پردیس شاپ سه مدل جداگانه طراحی کرده است: یکی برای مدیران، یکی برای مشتریان و دیگری برای فروشندگان. در ابتدا همهچیز برای علی و دستاندرکاران پردیس شاپ ساده و قابلمدیریت بهنظر میرسید، اما با رشد این فروشگاه و افزایش نیازها، کمکم مشکلات بزرگی نمایان شد. هر تغییری در سیستم این آنلاین شاپ به سه جای مختلف سرایت میکرد و نگهداری کدها به کابوسی واقعی تبدیل شده بود! اشتباه علی که دیگر تنها یک اشتباه ساده در طراحی نرمافزار نبود، حال به یک اشتباه بسیار بزرگ و نابخشودنی تبدیل شده است...
پروژهی اولیه
برای دانلود پروژهی اولیه روی این لینک کلیک کنید.
ساختار فایلها
pardis_shop
├── users_app
│   ├──  > migrations < 
│   │   ├── 0001_initial.py
│   │   └── utils
│   │       └── user_migration.py
│   ├── __init__.py
│   ├──  > models.py < 
│   └── ...
├── manage.py
└── ...
راهاندازی پروژه
برای اجرای پروژه، باید پایتون و ابزار pip را از قبل نصب کرده باشید.
- 
ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
 - 
در پوشهی اصلی پروژه، یک محیط مجازی پایتون (venv) ایجاد و فعال کنید:
 
python -m venv venv
source venv/bin/activate  # در ویندوز: venv\Scripts\activate
- دستور زیر را برای نصب نیازمندیها در پوشهی اصلی پروژه اجرا کنید:
 
pip install -r requirements.txt
- برای اجرای پروژه Django دستور زیر را در مسیر پوشهی اصلی پروژه اجرا کنید:
 
python manage.py runserver
در صورت اجرای موفق، یک لینک در خروجی نمایش داده میشود که میتوانید آن را در مرورگر باز کنید.
- برای اجرای مایگریشنها و ایجاد جداول پایگاه داده، دستور زیر را اجرا کنید:
 
python manage.py migrate
- برای بارگذاری دادههای نمونه از فایل fixture، دستور زیر را اجرا کنید:
 
python manage.py loaddata users_fixture.json
جزئیات پروژه
اکنون وقت بازطراحی مدلهای پردیس شاپ رسیده است. شما باید ساختار دادهای طراحی شده توسط علی میو که در قالب پروژه اولیه در دسترس شما قرار گرفته را اصلاح کنید و آنرا بهبود ببخشید. در طراحی اولیهی پروژه، اپلیکیشنی با نام users_app مسئولیت مدیریت انواع کاربران را بر عهده دارد. در این پیادهسازی، سه مدل مجزا برای کاربران با نقشهای متفاوت تعریف شده است:
- مدل 
AdminUser - مدل 
CustomerUser - مدل 
VendorUser 
طراحی دیاگرام (ER Diagram) این مدلها به صورت زیر است:

هر یک از این مدلها اطلاعات خاص خود را ذخیره میکنند. با وجود برطرف کردن نیازهای ابتدایی، اکنون مشخص شده که این ساختار از لحاظ طراحی پایگاهداده و اصول مهندسی نرمافزار با نقصهای جدی همراه است. وجود چندین مدل برای انواع کاربران منجر به افزونگی، دشواری در توسعه و مشکلات نگهداری شده است.
علی میو پس از مواجهه با مشکلات نگهداری و توسعه در ساختار قبلی، تصمیم به بازطراحی کامل سیستم کاربری گرفته است. شما در این پروژه قرار است بخشهای زیر از سیستم مدیریت کاربران را طراحی کنید.
پیادهسازی مدلهای جدید
شما باید با استفاده از تصویر زیر که نشان دهنده ساختار مدلهای جدید است، مدلهای جدید کاربران را پیادهسازی کنید:

مدلهایی که باید پیادهسازی کنید:
- مدل مشترک 
CustomUser. - سه مدل دیگر به نامهای 
AdminProfile،CustomerProfileوVendorProfile. 
رابطههای مدلها:
مدل CustomUser به عنوان مدل اصلی کاربر عمل میکند و شامل فیلدهای مشترک تمام کاربران است. هر یک از مدلهای پروفایل (AdminProfile، CustomerProfile، VendorProfile) با مدل CustomUser رابطه یکبهیک دارد، به این معنی که:
- 
هر کاربر فقط یک پروفایل از هر نوع میتواند داشته باشد.
 - 
هر پروفایل فقط به یک کاربر متصل است.
 - 
با حذف کاربر، پروفایل مرتبط نیز حذف میشود.
 - 
هر پروفایل دارای
related_nameمنحصر به فرد است تا بتوان به راحتی از کاربر به پروفایل دسترسی داشت. - 
شما باید این مدلها را در کنار مدلهای قبلی (
AdminUser،CustomerUser،VendorUser) و در همان فایلmodels.pyتعریف کنید. - 
به عنوان
usernameدر مدلCustomUserمیتوانید از ایمیل کاربران استفاده کنید. - 
برای کاربران ادمین در مدل
CustomUserباید ویژگیهایis_staffوis_superuserمقداردهی شوند. - 
توجه داشته باشید که مدلهای دیگر موجود در عکس بالا که ربطی هم به مدل یوزر ندارند را نیازی نیست در پیادهسازی درنظر بگیرید، برای این مدلها امتیازی درنظر گرفته نخواهد شد.
 
ایجاد فایل مایگریشن
پس از پیادهسازی مدلهای جدید، با استفاده از دستور زیر، فایل مایگریشن را بسازید:
python manage.py makemigrations
در نتیجه این عملیات، فایلی مشابه فایل زیر ساخته خواهد شد:
0002_user_adminprofile_..._.py
پیادهسازی تابع انتقال دادهها
در فایل users_app/migrations/utils/user_migration.py تابعی با نام migrate_users_forward وجود دارد. این تابع وظیفه دارد تا اطلاعات کاربران را از مدلهای قبلی (AdminUser, CustomerUser, VendorUser) به مدلهای جدید منتقل کند و دادهها را بهدرستی در User و پروفایلهای مرتبط ذخیره کند.
شما باید این تابع را تکمیل کرده و در فایل مایگریشنی که ساختهاید (0002_...) با استفاده از migrations.RunPython(...) این تابع را اجرا کنید. برای این کار، در بخش operations این فایل، دستور زیر را اضافه کنید:
from users_app.migrations.utils.user_migration import migrate_users_forward
...
migrations.RunPython(migrate_users_forward, reverse_code=migrations.RunPython.noop)
- توجه: نیازی به برگشتپذیر بودن این مایگریشن نیست.
 
آنچه باید آپلود کنید
- توجه: پس از پیادهسازی موارد خواسته شده، کل فایلهای پروژه بهجز پوشهی 
venvو فایلdb.sqlite3را زیپ کرده و ارسال کنید. - توجه: شما مجاز به افزودن فایل جدید به جز فایل مایگرشن خواسته شده در این ساختار نیستید و تنها باید تغییرات را در فایلهای موجود اعمال کنید.
 - توجه: که نام فایل Zip اهمیتی ندارد.
 - توجه: در پایان فراموش نکنید که مدل 
CustomUserرا در فایلsettings.pyباAUTH_USER_MODEL = 'users_app.CustomUser'اضافه کنید. 
ارسال پاسخ برای این سؤال