جنگولرن
3.82K subscribers
287 photos
74 videos
31 files
557 links
آموزش Django و بستگان
Download Telegram
درمورد Descriptor چی می دونیم؟

چطوری می‌توان رفتارهای ویژگی‌های مرتبط به یک کلاس را مدیریت کرد؟ چطوری می‌توانیم کاری کنیم که ویژگی‌های متفاوت کلاس‌های مختلف به شکلی یکسان مدیریت شوند؟

ما در حالت ساده هیچ کنترلی روی ویژگی (Attribute) هایی که یک کلاس دارد نداریم.
وقتی شما کلاسی دارید که یک ویژگی به نام x دارد، هنگام کار با نمونه‌های ساخته‌شده از این کلاس می‌توان هر مقداری را به این ویژگی نسبت داد.
مثلاً فرض‌کنید که ما یک کلاس به نام Person داریم که مقدار سن شخص در آن نگهداری می‌شود:
class Person:
def __init__(self, age):
self.age = age

حالا ما موقع ساخت یک نمونه از این کلاس می‌توانیم «هرچیزی» را به آن نسبت بدهیم:
person1 = Person(10000)
person2 = Person(-10)
person3 = Person("I am not even an integer!")

در حالت ساده ما هیچ کنترلی روی ویژگی‌ها نداریم. پس تمام نمونه‌های بالا از نظر زبان پایتون درست هستند. امّا این مقادیر منطق برنامه‌ی ما را خراب می‌کنند.

شما می‌توانید برای اعتبارسنجی (Validation) مقادیر کدهای اضافی‌ای را درون init قرار بدهید. امّا آن کدها دیگر تغییرات مقادیر را پس از ساخت شئ کنترل نمی‌کنند.

حتّی می‌توانید متدهایی برای اعتبارسنجی درون کلاس‌تان بگذارید. امّا این کار تنها استفاده از کدتان را برای دیگران سخت‌تر می‌کند و همواره این احتمال وجود دارد که برنامه‌نویس فراموش کند که پس از هرتغییری در هر جای کد، آن متدها را فراخوانی کند.

از این مورد بگذریم.

فرض‌کنید که شما می‌خواهید یک ویژگی درون کلاس A همیشه عدد مثبت باشد. حالا در جای دیگر برنامه نیازدارید که چند ویژگی کلاس B هم درست همین خاصیّت را داشته باشند.
کلاس‌های A و B هم هیچ ربط منطقی‌ای ندارند و نمی‌توان به مواردی مثل ارث‌بری حتّی فکر کرد.
عالی نبود اگر می‌شد کاری کرد که ویژگی‌های کلاس های مختلف، بدون اینکه به هم ربطی پیدا کنند، به یک شکل مدیریت شوند؟

خب Descriptor پروتکلی است که همه‌ی این کارها را برای ما می‌کند.
پروتکل Descriptor خیلی ساده است. هر کلاسی که حداقل یکی از متدهای: set، get یا delete را پیاده‌سازی کند یک Descriptor حساب می‌شود.

کاربردها و مثال های Descriptor رو خودتون بخونید.
از سایت علی حسینی کپی کردم. این لینک

میخوام یه قابلیت ساده که توی جنگو هست رو توضیح بدم.
اما قبلش اگه بدونیم Descriptor چیه، یادگرفتنش باحال تر میشه.
پس اگه عمری بود، بقیه در پست های بعدی...


اسپانسر این قسمت 👈 لینک
👏62👍2
جنگولرن
وات ایز F() expressions در جنگو 😁 جنگو در مورد تابع F توی داکیومنت میگه: An F() object represents the value of a model field, transformed value of a model field, or annotated column. It makes it possible to refer to model field values and perform database…
نکته ای از عثمان در مورد پست F

ی مورد دیگه که خود جنگو داره از F object استفاده میکنه زمانیه که شما سعی میکنی ی رکورد جدید توی تیبل ایجاد کنی که اگه همون موقع بدون کال کردن refresh_from_db بیای یکی از فیلدهای رکورد جدید رو تو ی کوئری یا ایجاد رکورد تو ی جدول دیگه استفاده کنی توی کوئری یا ترنزکشنت ORM میاد دقیقا به اسم همون فیلد ترجمه میکنه، مثال:

شما فکر کنید ی تیبل به اسم Stock دارید و ی تیبل دیگه به اسم StockLog
فیلدهای استاک:
quantity
quantity_allocated

فیلدهای استاک لاگ:
initial_quantity
final_quantity

حالا شما ی رکورد جدید تو تیبل استاک می سازید:
stock = Stock.objects.create(quantity=10, quantity_allocated=0)

و میای بعدش میگی:
StockLog.objects.create(initial_quantity=0, final_quantity=stock.quantity)

Orm -> insert into stocklog(initial_quantity, quantity) values(0, 10)

اینجا حتما باید حواست به رفرش قبل اساین باشه
5🤔31
چرا ذهن ما عاشق Abstraction زودهنگام است؟

خیلی وقت‌ها در تیم‌های نرم‌افزاری می‌بینیم که مهندسان خیلی زود به سراغ abstraction و generalization می‌روند. یعنی قبل از اینکه حتی نیاز واقعی شکل بگیرد، یک لایه انتزاعی طراحی می‌کنند تا برای آینده آماده باشند.

این رفتار بی‌دلیل نیست. ذهن ما از نظر تکاملی عادت دارد الگوها را سریع تشخیص دهد و تعمیم دهد. همین باعث شده است که حتی وقتی دو سناریوی مشابه می‌بینیم، ناخودآگاه به فکر ساختن یک راه‌حل عمومی می‌افتیم. در زندگی روزمره این توانایی به بقای ما کمک کرده، اما در دنیای نرم‌افزار همیشه مفید نیست.

مشکل اصلی اینجاست که وقتی زود abstraction بسازیم، سطح اشتباه را انتخاب می‌کنیم. نه آنقدر بالا که به درد بخورد، نه آنقدر دقیق که واقعاً نیاز را برطرف کند. نتیجه این می‌شود که کدی می‌نویسیم که پیچیده‌تر از چیزی است که لازم داریم، و سرعت یادگیری و تغییر را پایین می‌آورد.

در عین حال، فرهنگ و فضای آموزشی هم این عادت را تقویت می‌کند. همه جا به ما گفته‌اند تکرار بد است یا باید برای reuse طراحی کنی. در حالی‌ که در بسیاری از موقعیت‌ها بهترین کار این است که ابتدا با ساده‌ترین راه‌حل شروع کنیم و بعد، وقتی چند بار نیاز تکرار شد و الگو روشن شد، سراغ abstraction برویم.

به جای پیش‌بینی آینده، باید برای تغییر آماده باشیم. به جای اینکه یک معماری عمومی از روز اول طراحی کنیم، بهتر است ساختار را طوری بچینیم که refactor راحت باشد. یعنی اول مسأله را حل کنیم، بعد اگر دیدیم الگو دارد تکرار می‌شود، abstraction را بسازیم.

آیا ما واقعاً می‌خواهیم برای آینده‌ای که هنوز نیامده هزینه بدهیم؟ یا می‌خواهیم امروز ساده شروع کنیم و اجازه بدهیم کد و معماری با واقعیت رشد کند؟

✍🏻 Kayvan Alimohammadi
55👍2