معماری اصلاح شده MVC برای وب اپلیکیشن های بزرگ

امشب داشتم معماری یه نرم افزار جدید رو انجام میدادم و داشتم به این فکر میکردم که چطوری یک وب اپلیکیشن رو بنویسم به طوری که برای کاربرد های وسیع و کاربران زیاد و همچنین منطق و لاجیک های پیشرفته کارا باشه٬ در عین حال برنامه نویس های مبتدی هم بتونن با یک پترن خوب کد بزنن و از اینکه از برنامه نویس های تازه کار و جونیور تو پروژه استفاده بشه ترسی نباشه.معماری وب اپلیکیشن های بزرگاول مقالم دوست دارم بگم که این یک معماری هست که من پیشنهادش میدم و فکر میکنم کار کنه ولی هنوز پیادش نکردم. اما وظیفه من هم هست بگم ایده این معماری از کجا به ذهن من رسید.از وقتی که تو یکی از شرکت های ممتاز آی تی وارد کار شدم٬ ساختار جدیدی که برای MVC می‌دیدم نظر من رو جلب کرد. برای همین سعی کردم خیلی منطقی و مو شکافانه اونو بررسی کنم. خیلی از مفاهیم معماری جدیدی که برای خودم طراحی کردم و اینجا توضیح میدم از اون شرکت اقتباس شده.در خصوص کارایی٬ یا پیشنهاداتی که به ذهنتون میرسه وقتی که این مقاله رو مطالعه میکنید٬ خدمتتون عرض کنم که خوشحال میشم ایرادات و پیشنهادات رو به من بگید. میتونید منو تو اینستا گرام یا تلگرام از طریق لینک های زیر پیدا کنید:تو تلگرام به من پیام بدید | تو اینستاگرام دنبالم کنید :)طرح مسئلهیکی از مشکلاتی که تو پیاده سازی پروژه های بزرگ و پیچیده به چشم میخوره (بنا بر تجربه شخصی اینجانب)٬ تبدیل شدن کد های سورس پروژه از کد های تمیز و شسته رفته اولیه به کد های پیچیده٬ اسپاگتی٬ کثیف٬ ناکارا و در یک کلام آشغال هست.چیزی که باعث میشه شرکت های بزرگی مثل اسنپ و دیجی‌کالا در ایران مجبور بشوند تا زیر ساخت خودشون رو بازنویسی کنند.اینکه به دلیل فشار های بیزینس گاهاً کد ها بدون تحلیل درست زده بشه٬ اجتناب ناپذیره اما بعضی معماری ها و روش ها٬ ریفکتور کردن و اصلاح این کد ها رو در آینده راحت تر میکنه.تو این مقاله قصد دارم به تفصیل با بیان مشکل چند راه حلی که خودم تجربه کردم و جواب داده رو برای شما بنویسم.معماری اولیهمعماری اولیه پروژه خیلی میتونه راه گشا باشه. متاسفانه این منطق که سریع یه چی بالا بیاریم٬ ممکنه مشکلات و باگ های زیادی رو در آینده در کد شما ایجاد کنه. همیشه به عنوان یه مهندس نرم افزار٬ و نه برنامه نویس باید هزینه و صرفه اینکه شما سریعتر کد بزنید یا درست تر رو حساب کنید.همیشه شرایط و اجبار هایی در پروژه به وجود میاد که شما مجبور به سریع کد زدن و ایجاد بدهی فنی میشید. پس در ابتدای پروژه که دست شما باز هست و معمولا هم زمان بیشتری برای دولوپ دارید٬ زیر ساخت قرص و محکمی فراهم کنید.برنامه قابل توسعهاز نظر شخص بنده برنامه قابل توسعه برنامه ای هست که شما بتونید هر وقت لازم شد با کمترین هزینه و بالاترین درصد اطمینان اون رو ریفکتور کنید. چون حتی اگر خدا هم باشید بعضی جاها سوتی میدید و بعدا متوجه این مسائل میشید.حتما همه شما دوستان با این مسئله مواجه شدید که کد به قدری کثیف و درهم تنیده شده باشه که از دست زدن بهش بترسید و ترجیح بدید بذارید همینطوری که الان داره کار میکنه به کارش ادامه بده. این یعنی شروع مرگ نرم افزار شما.تست نرم افزار را جدی بگیریدتست نرم افزار مهم ترین اصلی هست که به شما اجازه ریفکتور های گسترده و سریع رو میده. اگر تست ننویسید عملا صحبت در خصوص ریفکتور بی معنی میشه.تست نوشتن برخلاف تفکر عموم برنامه نویس ها سرعت توسعه شما رو کند نمیکنه. حتی به توسعه صحیح و هدفمند شما کمک هم میکنه. پترن خود من تو تست نوشتن این طوری هست که قبل از اینکه کد یه قسمت رو بنویسم اول تست هاشو مینویسم بعد سعی میکنم کدم رو انقد عوض کنم تا تست ها رو پاس کنه نه این که کد رو بنویستم و تست رو جوری بنویسم که پاس بشه :)))شما وقتی تست مینویسید حتی میتونید پروسه های پیچیده رو سریع تر تست کنید.فرض کنید در شرایطی شما باید سه Entity رو ذخیره کنید و بعد یه باگ اتفاق میوفته٬ چقدر دیباگ کردن اعصاب خورد کن و زمان بر میشه. اینجاس که تست ها میتونن سریع شرایط رو برای شما روشن کنند.معماری MVC بهبود یافتههمه ما در خصوص معماری MVC شنیدیم. من نمیخوام در خصوص MVC حرف بزنم. به جاش شما رو به مقاله یکی از دوستان ارجاع میدم. https://virgool.io/@taha/mvc-i06wbpjwatco بعد از اینکه این مقاله رو مطالعه کردید٬ البته اگر در خصوص MVC اطلاعی نداشتید٬ و بعد از چند باری کد زدن با این معماری٬ متوجه منظور من میشید که چی میخوام بگم.قانون ۱ : فقط API بنویس. قالب اچ تی ام ال رو فراموش کندر اصول مهندسی نرم افزار همیشه شنیدیم که یک بار کد بزنید و بارها استفاده کنید. با همین مقدمه میگم که اصلا فکر پیاده سازی سایت رو با روش های مرسوم گذشته از ذهنتون خالی کنید و فقط به API فکر کنید. من خودم بیشتر REST API رو هدف قرار میدم.چرا که شما با یک بار پیاده سازی اینترفیس های سرورتون دگه نیازی به نوشتن API برای اپ و دیگر سرویس هایی که قراره از سایتتون استفاده کنند ندارید. با تکنولوژی های جدید فرانت امروز هم مثل٬ VUEJS و REACTJS و ... کار براتون خیلی ساده تر میشه.با حذف لایه View در معماری مرسوم MVC یک V جدید ظاهر میشه که در ادامه توضیح میدم.قانون ۲: متد بیشتر از ۱۰ خط یعنی اشتباه کردیاین چیزی هست که همیشه روش تاکید میشه. اگر کد شما طولانی شده حتما اون رو میتونید به قطعات کوچکتر و قابل استفاده خورد کنید تا هم کد تمیز تر و خوانا تر داشته باشید و هم اینکه از زدن کد تکراری جلو گیری کنید.با این قانون و فرض پس دیگه تو کنترلر هاتون جای کد زدن نیست.قانون ۳: کنترلر فقط باید بفهمه کدوم مدل رو صدا کنه و چطوری خروجی رو برگردونهپس شما اگر دارید از معماری MVC استفاده میکنید٬ الان درگیر مدل میشید. یعنی کنترلر باید فقط با ورودی کاربر مدل درست رو صدا کنه و مقدار خروجیش رو برگدونه.تو فریم ورک هایی مثل Yii, Laravel, Symfony و ... شما یک مدل دارید که هم براتون دیتا رو از دیتابیس میخونه٬ هم داره بیزینس رو هندل میکنه٬ پس مدل هاتون خواه و ناخواه به اصطلاح چاق میشن و همه کد های پروژه تو اون لایه متمرکز میشه ولی همین موضوع باعث پیچیده شدن مدل ها میشه.نظریه من : اعتبارسنجی فرم ها و ورودی کاربر٬ کار مدل ها هست نه کنترلر. چون این موضوع هم به عبارتی نوعی لاجیک بیزینس حساب میشه. هر مدل ممکنه یه فرم رو به شکل متفاوتی اعتبار سنجی کنه. این موضوع تو Yii به خوبی هندل شده.قانون ۴: مدل های دیتابیسی یا Entity ها رو فقط با لاجیک دیتابیس پر کنیدیعنی چی؟ یعنی اینکه وقتی مثلا یه مدل الکونت تو لاراول یا اکتیو رکورد تو YII میسازید. مدل هایی که داره دیتا رو مستقیم با دیتابیس رد و بدل میکنه٬ اینا رو تمیز نگه دارید و فقط لاجیک های مربوط به دیتابیس توش بریزید. مثلا یکتایی دیتا٬ تبدیل به جیسون و از این قرتی بازیا. لاجیک بیزینس رو تا حد امکان وارد این مدل ها نکنید.پس جای لاجیک کجاس؟قانون ۵: از فرم مدل ها برای گرفتن ورودی کاربر استفاده کنیدیه چیزی که فریم ورک Yii داره و خیلی دل منو برده٬ منطق فرم مدل ها هست. تو این منطق شما یه مدل پایه که به دیتابیس وصل نیست میسازید٬ وقتی کاربر ورودی هاشو برای کنترلر میفرسته٬ کنترلر این مدل ها رو پر میکنه و متد مورد نظر اون اکشن مثلا create رو صدا میزنه. اگر هم ارور داشت ارور از مدل برمیگرده به کنترلر و اون خروجی رو به کاربر میده.مزیتش چیه؟ اینطوری شما دستتون به شدت بازه و کدتون خیلی تمیز تر میشه. میتونید اعتبارسنجی های پیشرفته تری داشته باشید. میتونید از فرم های پیچیده استفاده کنید و حتی چندین Entity رو هم زمان ذخیره کنید و خلاصه اینکه هر جنگولک بازی تو ذخیره Entity ها و دیتای کاربر میتونید در بیارید.زیبا نیست؟ به نظر شما تمیز تر و درست تر نیست؟قانون ۶: از View Model ها برای برگردوندن اطلاعات به کاربر استفاده کنیداین دقیقا همون V جدید مدل MVC هست که اینجا میگم. به قول محمد نظری عزیز٬ هد تیم فنی گروه مالی دیجی‌کالا٬ این کلاس ها چشم ما به دیتابیس هست.فرض کنید در یک لاجیک پیچیده بیزینسی٬ شما مجبورید از چندین Entity بخونید و دیتا رو به کاربر نشون بدید. اون موقع هست که این لایه بسیار راه گشا هست و دست شما رو تو تغییرات باز میذاره.شما میتونید بدون تغییر تو Entity یا FormModel ها مقادیر خروجی رو تغییر بدید و یا اصلاح کنید.وقتی ما لایه ای که خروجی رو به کاربر با HTML نشون میداد حذف میکنیم این لایه میتونه استفاده بشه تا آرایه هایی رو آماده کنه تا به کاربر برگدونیم.تو این لایه شما میتونید منطق های Cache های پیچیده٬ سرچ های پیچیده و هر چیزی که لازمه تا دیتا رو برگردونید استفاده کنید.مدل MVC بهبود یافته برای اپلیکیشن های بزرگاستفاده از FormModel ها و ViewModel ها شما رو توی نوشتن Unit Test های کارا تر و پیچیده تر قوی تر میکنه. همونی که گفتم. بدون تست ریفکتور معنا نداره.قانون ۷: هیچ وقت گول این حرف رو نخورید٬ کد تمیز مینویسم و داکیومنت لازم نیستکد تمیز الزامی هست. از متد های استاندارد کد استایل استفاده کنید. مثل PSR ها برای PHP.ولی الان همه زبان ها تقریبا از Inline Document پشتیبانی میکنند. PHP Doc رو برای مثال یاد بگیرید. نماد هاشو بفهمید و در همه کد ها٬ هر متد جدید استفاده کنید.کد شما هر چقدر هم تمیز باشه با این داکیومنت ها٬ کار برنامه نویس بعدی که قراره کد شما رو بهبود بده راحت تر میشه. این موضوع تو نوشتن برنامه های بزرگ اساسی هست.بعدا از همین PHP DOC یا هر چیز دگه میتونید استفاده کنید تا داکیومنت کامل پروژه رو بسازید و به وسیله اون برنامه نویس های جدید رو سریعتر آن برد کنید.ممنون وقت گذاشتید و این مقاله رو خوندید.اگر دوست داشتید اونو منتشر کنید.در خصوص اشتباهاتم به من پیام بدید و نظر بدید ولی ناموسا نگید چرا یک رو مینویسم ی و فلان چیز چرا خلاصه شده :)))). سبکمه و این مورد رو درست نمیکنم.