PDA

View Full Version : Class auto-loader فوق پیشرفته!



freeman99
یک شنبه 24 اسفند 1393, 12:38 عصر
برای پروژم یه auto-loader درست کردم.
اما نکات برجسته اون در مقایسه با بقیهء auto-loader ها اینه که شما میتونید در هر فایل هر تعدادی کلاس با هر نامی تعریف کنید، و حتی اسم فایل هم کاملا آزاده و مهم نیست چی بذارید؛ یعنی فقط کافیه هر کلاسی میخواید تعریف کنید وبعد فایلش رو بندازید توی پوشهء کلاسهای برنامه! به این میگن آخر انعطاف و آزادی عمل. نه محدودیتی در تعداد کلاسهای یک فایل داره و نه محدودیتی در نامگذاری، هیچ اینکلودی هم نیاز نیست. فقط بنداز توی فولدر و آمادهء استفاده! از تولید به مصرف :لبخند:

اینجا میتونید کدش رو بررسی کنید: https://github.com/ferchang/reg8log/blob/c23553d91f6c5b5b5981081bacb3ad38632b258d/include/class/class_class_loader.php

البته این کد الان برای استفاده دیگران نیست دقیقا، بلکه جزیی از پروژهء خودمه و با یک جزییاتی که به پروژهء خودم مربوط میشه نوشتم. ولی بهرحال کلیت الگوریتم و روشش باید کاملا روشن باشه و تغییر اون جزییات هم کار ساده ایه!

طرز کار این سیستم به این شکله که وقتی کلاسی توی PHP استفاده میشه که تعریف نشده خب PHP میاد متد load این کلاس autoloader رو فراخوانی میکنه و اسم کلاس هم به عنوان آرگومان بهش پاس میشه. بعد این جریانات در این سیستم اتفاق میفته:
سیستم یک ایندکس داره که توش اسامی تمام کلاسهای پیدا شده رو همراه با نام فایلی که اون کلاس توشه ذخیره کرده. این ایندکس بصورت یک آرایه، یا اگر دقیقتر بخوایم بگیم، یک associative array است.
سیستم اول میاد نگاه میکنه آیا آرایهء ایندکس در سشن ذخیره شده یا نه، اگر ذخیره بود میاد و اسم فایل مربوط رو پیدا میکنه و فایل تعریف کلاس مورد نظر رو اینکلود میکنه. اگر اسم کلاس مورد نظر در آرایهء ایندکس پیدا نشد، سیستم تمام فایلهای کلاس رو مجددا اسکن میکنه تا ببینه فایل جدیدی اضافه شده یا کلاس جدیدی در فایل های موجود قبلی اضافه شده، و آرایهء ایندکس آپدیت میشه.
آرایهء ایندکس در یک فایل هم ذخیره میشه، علاوه بر سشن، چون اگر سشن از بین رفته باشه به این شکل نیازی نیست که دوباره این عمل اسکن و جستجوی تمام فایلها برای پیدا کردن کلاسهای تعریف شده در اونا صورت بگیره، و فقط کافیه ایندکس رو از توی اون فایل مجددا لود کنه و در سشن بریزه. البته ممکنه به علت عواملی مثل مشکل در پرمیشن نوشتن در این فایل، فایل برای ذخیرهء ایندکس برنامه قابل استفاده نباشه، اما حتی در این حالت برنامه باز بدون مشکل کار میکنه و فقط بهینگی اون مقداری پایین میاد (چون برای هر سشن جدیدی که ایجاد میشه یک اسکن و جستجو بین تمام فایلهای کلاس باید صورت بگیره). البته برنامه در این ارتباط هشداری رو نمایش میده و لاگ میکنه که برنامه نویس یا وبمستر متوجه این مسئله بشه و اگر خواست درستش کنه.
موقعی که اسم فایل تعریف مورد نظر از آرایهء ایندکس موجود در سشن خونده شده، اون فایل اینکلود میشه، بعد برنامه دوباره چک میکنه که حالا آیا اون کلاس تعریف شده یا نه، یعنی توی اون فایل واقعا چنان کلاسی وجود داشته یا نه، اگر وجود نداشته باشه نشون میده که کلاس مورد نظر از اون فایل حذف شده و شاید به فایل دیگری منتقل شده یا حتی به فایل جدیدی، و شاید هم اصلا اسم فایلی که اون کلاس توش بوده رو برنامه نویس عوض کرده، بنابراین سیستم در صورت تعریف نشدن کلاس میاد و دوباره تمام فایلها رو اسکن و ایندکس رو آپدیت میکنه و این بار اگر کلاس مورد نظر پیدا نشد دیگه معلومه که اون کلاس واقعا وجود نداره و برنامه با خطا متوقف میشه.

خلاصه من سعی کردم تمام حالات ممکن رو در نظر بگیرم تا برنامه نویس درصورتی که هر تغییری در کلاسها و فایلهای اونها داد نیازی به انجام هیچ عمل دیگری نداشته باشه و سیستم خودش بصورت خودکار این تغییرات رو متوجه بشه و کار خودش رو به درستی انجام بده. هر فایلی رو دوست دارید rename کنید، کلاسی رو به فایل دیگری منتقل کنید (چه به فایلهای موجود و چه فایلهای جدیدی)، فایل و کلاس جدیدی ایجاد کنید، نیازی به هیچ عملی نیست و سیستم به درستی کار میکنه.

البته میدونم الان خیلی ها روی پرفورمنس این سیستم میخوان گیر بدن، ولی خواهشا بحث بیخود راجع به پرفورمنس نکنید چون بنظر من حکایت «وسواس در بهینه سازی» و بیخودی بستن دست برنامه نویس است و محروم شدن بیهوده از کدنویسی راحتتر و سریعتر. البته من بهینه سازیهای درشتی رو که بنظرم برای این سیستم میتونست موثر باشه درش گذاشتم. مثلا این عمل اسکن و جستجو در فایلها و آپدیت ایندکس درسته بنظر سنگین میاد (هرچند روی سیستم خانگی و قدیمی من که کاملا سریع انجام میشه)، ولی باید در نظر داشت که این کار به ندرت در عمل صورت میگیره و فقط در اولین اجرای برنامه یک باره و دفعات بعد در یک نشست کاری و درخواستهای بعدی کاربر ایندکس از سشن لود میشه و سشن هم از بین رفته بود ایندکس میتونه از فایل ایندکس لود بشه (درصورتیکه پرمیشن های ایجاد و خواندن فایل مشکلی نداشته باشن). در غیر این صورت عمل اسکن و جستجوی مجدد در فایلها فقط وقتی تکرار میشه که تغییری در کلاسها و فایلهای محتوی اونا بوجود بیاد که این فقط موقع توسعه و تست توسط خود برنامه نویسه که ممکنه چندین بار رخ بده که در اون مواقع پرفورمنس مطرح نیست و این راحتی و سرعت کدنویسی و کمتر شدن حجم جزییات و کدها و وظایف برنامه نویس است که خیلی مهمتر و مفیدتره برای برنامه نویسی، و این سیستم دقیقا هدفش همینه که این بار رو از دوش برنامه نویس برداره و کدهاش رو کم حجم تر و خواناتر کنه و باگهایی رو که بر اثر دخالت و طبیعتا خطای انسانی بوجود میان به حداقل ممکن برسونه.
از سوی دیگر من این کلاس رو برای پروژه و هدف خودم نوشتم و در نظر نداشتم از نظر پرفورمنس خیلی وسواسی باشه تا بتونه در هر برنامه و هر مقیاسی با هر ترافیک و تعداد کلاس استفاده بشه. لزومی هم نمیبینم که آدم همیشه با این ذهنیت و هدف محدودکننده و دشوار کننده کد بنویسه و چیزی رو درست بکنه. اصولا سیستم رجیستر و لاگین خودم رو برای برنامه ها و کارها و سایت های معمولی با مقیاس کوچک تا شاید متوسط در ذهن طراحی کردم و کلاسهای زیادی هم نداره. ضمنا هر وقت نیاز شد میشه این سیستم رو تغییر داد یا اصلا با یه چیز دیگه مناسب برای شرایط و مقیاس مورد نظر خودش تعویض کرد.

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

یه نکتهء دیگه اینکه با اینکه گفتم نام فایلهای کلاس کاملا آزاده و میتونه هرچیزی که برنامه نویس میذاره باشه و لزومی به تبعیت از الگوی خاصی نیست، ولی در کد خودم اگر نگاه کنید الگویی که فایلهای کلاس رو پیدا میکنه رو class_*.php تعیین کردم، ولی فقط چون فایلهای کلاس برنامهء من از قبل از این الگو پیروی میکردن و اینطوری بنظر خواناتر اومد، ولی درواقع هیچ نیازی به این محدودیت نیست و میشه اون رو با ‎*.php یا حتی یک الگوی عمومی تر براحتی عوض کرد.

MMSHFE
دوشنبه 25 اسفند 1393, 09:49 صبح
بجای ROOT.class_loader::$index_file میتونین از self::$index_file استفاده کنین. کلاً داخل کلاس برای دسترسی به عناصر استاتیک همون کلاس از self استفاده کنید بهتره چون اگه اسم کلاس عوض شد، لازم نیست کدها رو عوض کنید. همچنین برای دسترسی به اسم کلاس داخل خود کلاس از __CLASS__ و در بیرون از کلاس برای دسترسی به اسم کلاس اشیاء از (get_class($obj استفاده کنید.