Small-Note

‫معماری نرم‌افزار‬
‫با یک خاطره‌ی کوچک بگذارید شروع کنم‪ .‬سال پیش برای کار به مرکز فناوری ــــــــــ«نمی‌گم کجا !»ـــــــ رفتم‪.‬‬
‫آن دوستان سیستم گمرک را داشتند می‌نوشتند‪ .‬اول از همه تعجب کردم پروژه‌ی به این مهمی را چرا داده‌اند دست‬
‫چند دانشجو ولی خوب ‪ ...‬بگذریم !‬
‫درست است که سیستم گمرک تا یک‌سال دیگر از کار می‌افتد و دوباره آن را از اول می‌نویسند ! ولی حداقل این‬
‫برای من و شما یک فایده دارد‪ ،‬اینکه از اشتباه این بچه‌ها درس بگیریم !‬
‫خوب حاال مشکل چی بود ؟ نداشتن معماری‪ .‬آن هم نه معماری خفن و پیچیده ! بلکه همان چیزی که االن نقل و‬
‫نبات دهان هر جوجه مهندسی شده‪ ،‬یعنی معماری ‪.MVC‬‬
‫این بچه‌ها برای درست کردن صورت وب‌سایتشون (‪ )Web-UI‬از یک کتابخانه‌ی جاوا به اسم ‪ Wicket‬استفاده‬
‫کرده بودند‪.‬‬
‫اولین ایراد این بچه‌ها تا اینجا این بود که نمی‌دانستند برای یک پروژه‌ی بزرگ باید ‪Front-‬‬
‫‪ End‬و ‪ Back-End‬از هم جدا شود‪.‬‬
‫اگر این اشتباه‌شان را زیر سبیلی رد کنیم‪ ،‬اشتباه دوم‌شان را از زیر سبیل که هیچ‪ ،‬از زیر تونل رسالت هم نمی‌شود‬
‫رد کرد‪ .‬این بچه‌ها داخل ‪ Event-Handler‬اجزای صفحه (به قول خودمان همان ‪onClick‬های دکمه‌ها) منطق‬
‫برنامه را کُد نویسی کرده بودند !‬
‫فردا اگر می‌دیدند پروژه بزرگ شده و دیگر ‪ Wicket‬بدرد کار نمی‌خورد چی؟ اگر به چشم ندیده باشید شاید باور‬
‫نکنید تغییر در چنین کُدی چقدر هزینه‌بر و خطرناک است‪ .‬تاجایی که خیلی وقت‌ها اصال به زحمتش نمی‌ارزد و در‬
‫چنین مواقعی سیستم را کال دور می‌ریزند و از اول می‌نویسند‪ .‬حاال بماند که چنین سیستم یکپارچه‌ای نه تست‬
‫می‌شود‪ ،‬نه به این راحتی‌ها درش تغییر می‌شود ایجاد کرد و هزار مشکل جدی دیگر‪.‬‬
‫به عبارت دیگه باید ‪ BusinessLogic‬رو از ‪ UI‬جداکنید‪.‬‬
‫خوب اصال برای چی این جداسازی‌ها رو داریم می‌کنیم ؟ جواب ساده‌ست ! اگر به دنیای واقعی هم نگاه کنید یک‬
‫برج رو به ‪ ۰۱۱‬طبقه تقسیم کردند‪ ،‬هر طبقه مثال ‪ ۸‬واحد دارد‪ ،‬هر واحد ‪ ۲‬تا اتاق و پذیرایی و توالت و حموم و‬
‫آشپزخونه داره‪( .‬پس سیستمی که به بخش‌های معنی‌دار تقسیم‌بندی شده‪ ،‬قابلیت‌درک راحت‌تری دارد)‬
‫خوب االن مثال اگر آقای جوادی اگه با آشپزخونه خون‌شون راحت نبود و مشکل داشت‪ ،‬می‌تونه همون یه تیکه رو‬
‫تغییر بده‪( .‬امکان تغییر راحت‌تر هر بخش) کارشناس بهداشت اگه بیاد مجبور نیست کل واحد رو چک کنه و‬
‫فقط می‌تونه بخش مربوط به خودش رو چک کنه‪( .‬تست آسان‌تر)‬
‫معماری نرم‌افزار به طور رُک و پوست‌کنده‬
‫این «معماری نرم‌افزار» که می‌گویند‪ ،‬در یک کلمه یعنی یک نرم‌افزار بزرگ را بگیر ید و تقسیمش کنید به‬
‫بخش‌هایی که هر بخش واسه‌ی خودش تقریبا معنی مستقلی می‌ده و رابطه‌ی این جزا رو هم با هم مشخص کنید‪.‬‬
‫مثال بخش «ارتباط با پایگاه‌داده»‪« ،‬بخش رابطه‌کاربری»‪« ،‬بخش سرویس‌ها» و غیره درست کنید و بگویید‬
‫هرکدام چطور با بقیه‌ی بخش‌ها در ارتباط است‪.‬‬
‫می‌شود نرم‌افزار را خرد کرد به یک‌سری کامپوننت (مثال کامپوننت‌های سیستم‌عامل ویندوز که شامل‬
‫‪ Kernel32.dll, User32.dll, Advapi32.dll‬و غیره هستند)‪ ،‬می‌شود الیه‌ای کرد که هر الیه فقط از الیه‌ی‬
‫پایینی‌اش سرویس می‌گیرد و به الیه‌ی باالیی‌اش سرویس می‌دهد (مدل ‪ OSI‬شبکه که احتماال یادتان هست) و‬
‫غیره‪ .‬انواع و اقسام تقسیم‌بندی‌های معروف در قالب الگو برای معماری‌ها داده شده است (‪.)Best Practices‬‬
‫یا خودتون هم می‌تونید به صالح‌دید‪ ،‬سیستم‌خودتون رو تقسیم بندی کنید‪.‬‬
‫نحوه‌ی پیاده‌سازی مفاهیم این معماری‌ها (الیه‪/‬کامپوننت‪/‬ماژول‪ ).../‬به زبان‌برنامه‌نویسی‪ ،‬تکنولوژی و چارچوبی‬
‫که در اون کُد می‌زنید و سلیقه‌ی خودتون بستگی داره‪ .‬اگه دوست دارید حتی می‌شود یه ‪ Folder‬درست کرد و یک‬
‫سری ‪ Class‬داخل اون گذاشت‪ .‬بعد اون ‪ Folder‬رو یک کامپوننت فرض کرد یا یک الیه یا یک ماژول‪.‬‬
‫معماری که می‌خواهیم تمرین کنیم‬
‫به این شکل که براتون کشیدم خوب نگاه کنید ‪:‬‬
‫‪SYSTEM‬‬
‫‪VIEW‬‬
‫‪CONTROLLER‬‬
‫‪MODEL‬‬
‫‪DATA LAYER‬‬
‫‪Entity3‬‬
‫‪Model‬‬
‫‪Entity2‬‬
‫‪Model‬‬
‫‪LOGIC LAYER‬‬
‫‪Entity1‬‬
‫‪Model‬‬
‫‪VIEW‬‬
‫‪CONTROLLER‬‬
‫‪DATA LAYER‬‬
‫‪DB‬‬
‫‪MODEL‬‬
‫‪VIEW MODEL‬‬
‫‪VIEW‬‬
‫‪FRONT END‬‬
‫‪REST‬‬
‫‪SERVICE‬‬
‫‪LOGIC LAYER‬‬
‫‪DATA LAYER‬‬
‫‪BACK END‬‬
‫ببینید که چطور یک سیستم درشت را خرد کردم به بخش‌های کوچکتر ‪...‬‬
‫فرض کنید قرار بوده است یک سایت طراحی شود‪ .‬اگه معماری برایش طراحی نمی‌شد‪ ،‬در آن صورت می‌شد‬
‫همان شکل اول که سیستم یک‌پارچه و صُلب است‪ .‬تا دلتون بخواد قدیم‌ها وبسایت‌ها اینطوری درست می‌شدند‪،‬‬
‫هنوز هم اگر سواد مهندسی نباشد همین کار را می‌کنند‪ .‬برنامه‌نویس یه فایل ‪ PHP‬باز می‌کند و یاعلی از تو مدد !‬
‫از اول تا آخرش را همچون یه فایل ‪ batch‬قراضه کُد می‌زد‪.‬‬
‫یک‌ماه پس از تمام شدن پروژه به زور رمالی و دعا‪ ،‬وقتی ارباب رجوع زنگ می‌زد و می‌گفت که ‪ :‬آقا می‌شه‬
‫یکاری کنید نام‌خانوادگی ‪ ۰۱‬حرفی هم بشه وارد کرد ؟ برنامه‌نویس می‌گفت یک هفته بهم وقت بدید ببینم می‌شه‬
‫یا نه ! اگه شد هم هزینه‌ش می‌شه ‪ ۲۱۱‬هزار تومن ! یعنی کافی بود تا یه تغییر کوچک در کُد ایجاد شود تا کل‬
‫سایت دیگر از کار بیفتد‪.‬‬
‫تقسیمبندی کل سیستم‬
‫ما که حسابی مار گزیده هستیم دیگر فهمیده‌ایم که از این کارها نباید بکنیم ! پس سریع ‪ BackEnd‬و ‪FrontEnd‬‬
‫رو از هم جدا می‌کنیم‪ .‬در مورد سایت ما‪ ،‬ما پردازش‌های سمت ‪ Server‬را با ‪ NodeJs‬می‌خواهیم انجام دهیم‪ .‬و‬
‫نمایش اطالعات را در سمت ‪( Client‬که همون مرورگر کاربر است) میگذاریم به عهده‌ی ‪ Html‬و ‪.JavaScript‬‬
‫تقسیم‌بندی ‪Back-End‬‬
‫مجددا سمت ‪ Server‬حواسمان هست که امور مربوط به ‪ Database‬را در الیه‌ی ‪ DATA-LAYER‬انجام‬
‫دهیم آن هم بدون اینکه منطق ‪ Business‬را در آن دخیل کنیم‪ .‬منطق ‪ Business‬هم در الیه‌ی مربوط به خودش‬
‫یعنی ‪ LOGIC-LAYER‬باید برود‪.‬‬
‫جدیدا با گسترش مفهوم سرویس‌گرا یک الیه‌ی ‪ SERVICE-LAYER‬هم می‌گذارند روی ‪DATA-LAYER‬‬
‫و سرویس‌های کوچک و معنی دار را روی آن تعریف می‌کنند‪ ،‬این سرویس‌ها وظیفه‌مندی‌های معنی‌دار سیستم‬
‫هستند‪ .‬و ‪ LOGIC-LAYER‬دیگر با آن کار می‌کند‪ .‬اما در این تمرین به علت سادگی کار‪ ،‬دیگر چنین الیه‌ای‬
‫تعریف نکردیم‪.‬‬
‫برای ارتباط با ‪ Server ،Front-End‬نتایج را در قالب ‪( Json‬اشیاء ‪ )Javascript‬برای ‪ Client‬می‌فرستد‪.‬‬
‫(به این معماری ‪ RESTful‬می‌گویند)‬
‫تقسیم‌بندی ‪Front-End‬‬
‫در سمت ‪ Client‬معماری ‪ MVVM‬مُد روز است و خیلی هم کار را آسان می‌کند ! یک ‪ Framework‬شرکت‬
‫گوگل به اسم ‪ AngularJs‬ساخته است که معماری ‪ MVVM‬را روی ‪ HTML‬و ‪ JavaScript‬سوار می‌کند‪ .‬به‬
‫کمک این چارچوب براحتی می‌شود نتایجی را که در قالب ‪ Json‬از طریق ‪ Server‬برای ‪ Client‬ارسال می‌شود را‬
‫با ‪ JavaScript‬گرفته و روی ‪ HTML‬تغییرات را اعمال کنیم‪.‬‬
‫قدیم‌ها که این معماری نبود اگر می‌خواستیم با ‪ JavaScript‬داده از ‪ Server‬بگیریم و روی عناصر ‪ HTML‬در‬
‫صفحه نتیجه را بنویسیم کار دشوار و پیچیده بود‪ .‬کلی دستور برای گرفتن داده باید می‌گرفتید‪ ،‬بعد با کلی دستور‬
‫عناصر ‪ HTML‬را می‌گرفتید و بعد روی آنها تغییر را اعمال می‌کردید‪ .‬تازه برای هر ‪ Browser‬می‌دیدید یک‬
‫سری مشکل ایجاد می‌شه‪.‬‬
‫حتما یک نگاهی به چند آموزش ساده‌ی ‪ angularJs‬در سایت رسمی‌اش بندازید ‪:‬‬
‫‪https://docs.angularjs.org/tutorial/step_00‬‬
‫من ‪ Javascript‬و ‪ NodeJs‬و ‪ AngularJs‬بلد نیستم‪ ،‬چیکار کنم !‬
‫اشکالی نداره عزیزم نگران نباش ! تمرین‌تون خیلی آسونه‪ .‬من پروژه رو کامل براتون نوشتم‪ .‬شما باید فقط یکم‬
‫تغییر درش ایجاد کنید و تقسیم‌بندی معماریش رو درست کنید‪.‬‬
‫چند چیز رو در جاوا اسکریپ و مخصوصا ‪Framework‬های ‪Async‬اش باید قبل از انجام تمرین بدانید ‪:‬‬
‫تعریف یک تابع در جاوا اسکریپت‬
‫{ )‪var myFunction = function(a‬‬
‫;‪return a+10‬‬
‫}‬
‫;)‪myFunction(10‬‬
‫نحوه‌ی کار با سیستم‌های ‪Async‬‬
‫در زبان‌های برنامه‌نویسی رایج مکانیزم ‪ IO‬به صورت ‪ Sync‬کار می‌کنند‪ ،‬شما مثال اگر یک دستور برای خواندن‬
‫داده از پایگاه داده بخواهید اجرا کنید و بعد آن را پردازش کنید‪ .‬خیلی راحت دو دستور را در دو خط زیر هم‬
‫می‌نویسید‪ .‬و در هنگام اجرا برنامه‌ی شما آنقدر در خط اول معطل می‌شود تا جواب از پایگاه داده برسد و بعد‬
‫خط دوم اجرا می‌شود‪:‬‬
‫{ )‪function getGPAPlusOne(student_id‬‬
‫;)‪var result = db.read(“students.gpa”, student_id‬‬
‫;‪var added = result+1‬‬
‫;‪return added‬‬
‫}‬
‫ولی در برنامه‌ی ‪ Async‬دیگر ساختار طوری نیست که برنامه در خط خواندن از ‪ db‬معطل بماند‪ .‬معموال توابع‬
‫‪ IO‬خروجی مستقیم ‪ return‬نمی‌کنند ! یعنی معطل جواب نمی‌شوند و سریع دستور بعدی شما را اجرا می‌کنند‪.‬‬
‫حتما سوال می‌کنید پس چطوری جواب‪/‬نتیجه‪/‬خروجی را به ما می‌دهند ؟ مکانیزم اینطور هست که یک پارامتر‬
‫اضافی ‪ Callback‬می‌گیرند و وقتی نتیجه‌ی از پایگاه‌داده رسید به کمک ‪ Callback‬نتیجه را به شما خبر‬
‫می‌دهند‪ .‬یعنی اینطوری باید با آنها کار کنید ‪:‬‬
‫{ )‪function getGPAPlusOne(student_id, callback‬‬
‫{ )‪db.read(“students.gpa”, student_id, function (result‬‬
‫;‪var added = result+1‬‬
‫;)‪callback(added‬‬
‫;)}‬
‫}‬
‫کمی پیچیده شد نه ؟ اگر اولین باری است که چنین چیزی می‌بینید‪ ،‬درک‌تان می‌کنم‪.‬‬
‫ببینید در این سیستم ‪ Async‬پایگاه‌داده نتیجه‌اش را به شما از طریق تابع ‪ Callback‬که به عنوان پارامتر بهش‬
‫دادید رد کرده است‪ .‬یعنی در اینجا یک پارامتر سومی من به ‪ db.read‬رد کردم که این پارامتر یک تابع ‪callback‬‬
‫بود که نتیجه را در قالب پارامتر ‪result‬اش می‌گرفت‪ .‬وقتی ‪ db.read‬کارش تمام شود‪ ،‬تابع ‪ callback‬من را‬
‫فراخوانی (با رد کردن نتیجه در قالب پارامتر ‪ )result‬می‌کند‪.‬‬
‫از آنجایی در یک سیستم ‪ Async‬دارم کار می‌کنم من هم ‪ Async‬مجبور شدم عمل کنم و تابعم را ‪Async‬‬
‫بازنویسی کردم‪ .‬یعنی نتیجه را دیگر نمی‌توانستم ‪ return‬کنم‪ ،‬بلکه در قالب تابع ‪ callback‬به مشتری‌ام می‌دهم‪.‬‬
‫(درست همانطور که ‪ db.read‬به من رد کرد)‬
‫پس هر زمان وقتی نتیجه را ‪ db.read‬به من اعالم کرد‪ ،‬من هم ‪ callback‬که مشتری به من داده بود صدا میزنم‬
‫و نتیجه را به آن رد می‌کنم‪.‬‬
‫آماده‌سازی ‪ Back-End‬پروژه‬
‫نصب و اجرای ‪MongoDB‬‬
‫اول از همه ‪ MongoDB‬رو بگیرید و نصب کنید‪ .‬برای باال آوردن ‪ MongoDB‬به صورت ‪ Server‬روی‬
‫سیستم‌تون فایل ‪ mongod.exe‬رو باید اجرا کنید‪.‬‬
‫یعنی ‪ Command‬رو باز کنید‪ .‬با دستور >‪ cd /d <mongodb-bin-path‬به فولدر مورد نظر برید و ‪mongod‬‬
‫بزنید تا اجرا بشه‪ .‬معموال یه پیام خطا بهتون می‌ده که فایل‌های پایگاه داده رو نمی‌تونه ایجاد کنه و مسیر رو باید‬
‫دستی بهش بدید‪.‬‬
‫مثل من می‌تونید یه فولدر ‪ data‬همونطور که تو شکل می‌بینید درست کنید و بعد بزنید‬
‫”‪Mongod.exe --dbpath=”.\data‬‬
‫بدین‌ترتیب پایگاه‌داده‌مون باال اومد‪ .‬دیگه این رو نبندینش !‬
‫نصب و اجرای ‪NodeJs‬‬
‫بریم سروقت نصب ‪ ،Nodejs‬فایلش رو از سایت مربوطش دانلود و نصب کنید‪( .‬نسخه‌ی کامل که نصبی هست‬
‫رو بگیرید چون به غیر از ‪ node.exe‬به ‪ npm.exe‬برای مدیریت پکیج‌هاش احتیاج داریم)‬
‫ما در این پروژه به ‪ ۳‬پکیج نیاز داریم اینها رو هم به کمک دستورات زیر نصب کنید ‪:‬‬
‫‪npm install mongoose –g‬‬
‫‪npm install express –g‬‬
‫‪npm install body-parser –g‬‬
‫‪npm install sqlite3 –g‬‬
‫نصب و اجرای ‪AngularJs‬‬
‫این ‪ Framework‬سمت ‪ Client‬نصب ندارد و فقط یک فایل ‪ angular.js‬را باید در ‪ html‬معرفی کنید تا کار‬
‫کند‪.‬‬
‫>‪<script type="text/javascript" src="./js/angular.js"></script‬‬
‫اجرای پروژه‌ی که براتون آماده کردم‬
‫‪ mongodb‬را اجرا کنید‪ .‬سپس به مسیری که پروژه در آنجاست بروید و به کمک دستور ‪ Server‬خودتان را باال‬
‫بیاورید ‪:‬‬
‫‪node app.js‬‬
‫اگه همه‌چیز طبق برنامه پیش رفته باشد‪ ،‬باید چنین چیزی مشاهده کنید ‪:‬‬
‫اکنون مرورگر خود را اجرا کنید و به آدرس ‪ localhost:1333‬بروید تا نتیجه را مشاهده کنید ‪:‬‬
‫فایل‌های ‪ app.js‬و ‪ public/index.html‬را خوب برانداز کنید‪ .‬دلیل هرخط کدی که نوشتم را بررسی کنید‪ .‬تا در‬
‫روز آزمایش با این‌ها قرار است کار کنیم‪.‬‬
‫نصب یک ‪ IDE‬برای تسهیل کار‬
‫اگر از ‪ Eclipse‬استفاده می‌کنید با نصب ‪ Nodeclipse‬می‌توانید کار خود را برای کُد نویسی آسان‌تر کنید‪.‬‬
‫همچنین قابلیت ‪ Debug‬هم خودش کمک شایانی به شما می‌کند‪.‬‬
‫‪ Visual Studio‬و ‪ IntelliJ‬هم ویرایشگر و دیباگرهای خوبی هستند‪.‬‬