<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مجتبی پاکزاد</title>
        <link>https://virgool.io/feed/@pakzad</link>
        <description>تکنیکال تیم لید شرکت داده پردازان آبشار هستم. برای خوندن بیشتر تجربیات و مطالعاتم من رو در باورژن baversion.com دنبال کنید.</description>
        <language>fa</language>
        <pubDate>2026-04-14 09:03:15</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/5646/avatar/wCWkyX.jpg?height=120&amp;width=120</url>
            <title>مجتبی پاکزاد</title>
            <link>https://virgool.io/@pakzad</link>
        </image>

                    <item>
                <title>راهنمای جامع محصول و اجایل برای دولوپرها و مدیران محصول</title>
                <link>https://virgool.io/@pakzad/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%D8%AC%D8%A7%D9%85%D8%B9-%D9%85%D8%AD%D8%B5%D9%88%D9%84-%D9%88-%D8%A7%D8%AC%D8%A7%DB%8C%D9%84-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%AF%D9%88%D9%84%D9%88%D9%BE%D8%B1%D9%87%D8%A7-%D9%88-%D9%85%D8%AF%DB%8C%D8%B1%D8%A7%D9%86-%D9%85%D8%AD%D8%B5%D9%88%D9%84-fyzgqgnyoyn7</link>
                <description>برنامه‌نویس باشی یا مدیر محصول، احتمالا تو جلسه‌ها اصطلاح‌هایی شنیدی که اولش برات یه ذره عجیب و غریب بودن:این اِپیک رو بیار تو اِسپرینت بعدیاستوری پوینت این تسک اشتباه تخمین زده شدهبذار تو بک لاگ بمونه تا نسخه‌ی بعد...اگه راستش رو بخوام بگم، اوایل منم فکر می‌کردم نصف این اصطلاحا بیشتر برای شاخ شدن تو جلسه‌ستولی وقتی واقعا فهمیدم هرکدوم‌شون چه معنی‌ای داره و چطوری با هم کار می‌کنن، تازه دیدم دنیای محصول چقدر منظم‌تر و جذاب‌تر از چیزیه که فکر می‌کردم.این مقاله، دقیقا برای همینه:یه راهنمای کامل از تمام اصطلاحات مهم دنیای محصول و اجایل، با مثال‌های ساده و کاربردی.نه فقط برای مدیرای محصول، بلکه برای هرکسی که توی تیم یه استارتاپ کار می‌کنه، از دولوپر و طراح گرفته تا CTO و فاندر.مثال‌های ما توی این مقاله از پروژه‌ی فرضی‌ای به اسم Lernado میان — یه پلتفرم آموزشی با ویدیوهای کوتاه و شخصی‌سازی‌شده برای یادگیری مهارت‌های جدید.تو مسیر ساخت لِرنادو، تک‌تک این اصطلاحات رو با هم یاد می‌گیریم و می‌بینیم چطور از جلسه‌ی برنامه‌ریزی تا انتشار فیچر، همه‌چی با این مفاهیم جلو می‌ره.فصل اول: مفاهیم پایه در مدیریت محصولقبل از اینکه بریم سراغ اصطلاحات پیچیده‌تر مثل اِپیک (Epic) و اِسپرینت (Sprint)، باید چند تا واژه‌ی بنیادی رو بشناسیم.اینا همون چیزایی‌ان که پایه‌ی همه‌ی حرف‌های بعدی‌ان.هرچی اینا رو بهتر بفهمی، بقیه‌ش راحت‌تر جا می‌افته.۱. Product (محصول)محصول یعنی چیزی که برای کاربرت ارزش تولید می‌کنه.ممکنه یه اَپ باشه، یه سایت، یه ابزار، یا حتی یه API.مهم‌ترین ویژگی محصول اینه که یه مشکل واقعی رو حل کنه.مثال لرنادو:محصول لرنادو یه اپه که کمک می‌کنه کاربرها مهارت‌های کوتاه‌مدت رو تو قالب ویدیوهای ۵ دقیقه‌ای یاد بگیرن.مشکل واقعی؟ کمبود وقت و تمرکز برای آموزش.۲. Feature (فیچر یا ویژگی)فیچر یعنی یه قابلیت مشخص از محصول که یه بخش از اون مشکل رو حل می‌کنه.مثال لرنادو:قابلیت پخش ویدیوهای کوتاه با سرعت متغیر یه فیچره.قابلیت پیشنهاد درس بعدی بر اساس سابقه‌ی یادگیری هم یه فیچره.هر فیچر معمولاً خودش شامل چند تا تسک فنی و طراحی می‌شه.۳. User Story (یوزر استوری یا داستان کاربر)یوزر استوری یعنی تعریف نیاز کاربر به زبون خودش.نه به زبون فنی، نه به زبون بیزنسی، بلکه به زبون واقعی آدمی که قراره از اون قابلیت استفاده کنه.قالب معروفش اینه:به‌عنوان یه [نقش کاربر]، می‌خوام [کاری انجام بدم] تا [به یه هدف برسم].مثال لرنادو:به‌عنوان یه کارمند پرمشغله، می‌خوام بتونم ویدیوها رو با سرعت ۱.۵ برابر ببینم تا وقت کمتری صرف یادگیری کنم.این جمله‌ی ساده، باعث می‌شه همه‌ی اعضای تیم بدونن برای کی و چرا دارن یه چیز رو می‌سازن.۴. Acceptance Criteria (اکسپنس کریتریا یا معیار پذیرش)اکسپتنس کریتریا که بهش اِی سی (AC) هم می‌گن یعنی شرایطی که باید برآورده بشن تا یه یوزر استوری کامل تلقی بشه.به زبون ساده‌تر، چیزی که قراره تستر یا مدیر محصول بر اساسش بگه «آره، تمومه».مثال لرنادو:برای استوری بالا، معیار پذیرش می‌تونه این باشه:کاربر بتونه سرعت پخش رو بین ۰.۵ تا ۲ برابر تنظیم کنهمقدار سرعت انتخاب‌شده ذخیره بشه و در جلسه‌ی بعدی هم اعمال بشهدر نسخه موبایل و دسکتاپ هر دو درست کار کنه۵. Persona (پرسونا)پرسونا نماینده‌ی یه نوع کاربر واقعیه که داری براش می‌سازی.نه صرفاً سن و شغلش، بلکه سبک زندگی، انگیزه‌ها و دردهاش.مثال لرنادو:سارا، ۲۹ ساله، طراح رابط کاربری که زمان زیادی برای آموزش ندارهمی‌خواد مهارت‌های جدید رو سریع یاد بگیره تا تو کارش رشد کنهتو مسیر رفت‌وآمد با موبایل آموزش می‌بینههر تصمیم پروداکتی که می‌گیری، باید یه پرسونا پشتش باشه.۶. MVP (Minimum Viable Product)MVP یعنی ساده‌ترین نسخه‌ی محصول که می‌تونه ارزش واقعی به کاربر بده و بازخورد بگیره.نه ناقص، نه خام — ولی فقط شامل ضروری‌ترین چیزها.مثال لرنادو:نسخه‌ی اولیه لرنادو فقط پخش ویدیو و پیشنهاد درس بعدی داشت.هنوز کامنت، ذخیره، یا نوتیف نداشت.اما همون کافی بود تا بفهمیم کاربرها از ایده استقبال می‌کنن یا نه.۷. Metric (متریک)هرچیزی که با عدد نشون بده محصولت چقدر موفقه.بدون متریک، نمی‌فهمی در مسیر درستی هستی یا نه.مثال لرنادو:میانگین زمان تماشای هر ویدیونرخ بازگشت کاربر در هفته‌ی دومتعداد ویدیوهای تکمیل‌شده در روز۸. North Star Metric (ستاره شمالی)اون مهم‌ترین عددیه که موفقیت کلی محصول رو نشون می‌ده.یعنی اگه فقط یه عدد رو بخوای دنبال کنی، همینه.مثال لرنادو:درصد کاربرانی که حداقل سه درس کامل تماشا می‌کنن در هفته.جمع‌بندی فصل اولتو این فصل با واژه‌های پایه‌ی محصول آشنا شدیم:Product = چی می‌سازیمFeature = تکه‌ای از اون چیUser Story = برای کی و چراAcceptance Criteria = چطوری بفهمیم تموم شدهPersona = کی قراره ازش استفاده کنهMVP = اولین نسخه‌ای که ارزش دارهMetric و NSM = چطوری بفهمیم موفقیماین مفاهیم پایه‌ن، ولی ۹۰٪ تفاوت بین یه تیم گیج و یه تیم حرفه‌ای، همین‌جاست.فصل دوم: از Epic تا Bug — ساختار وظایف در اجایلتو دنیای واقعی تیم‌های محصول، هر ایده یا کاری یه اندازه و اهمیت خاصی داره.بعضیا بزرگن و چند هفته زمان می‌خوان، بعضیا کوچیکن و تو یه روز جمع می‌شن، بعضیا هم فقط رفع یه باگ لعنتی‌اناینجاست که ساختار سلسله‌مراتبی اپیک =&gt; استوری =&gt; تسک =&gt; ساب‌تسک میاد وسط.۱. Epic (اِپیک)اپیک یعنی یه هدف بزرگ و قابل اندازه‌گیری که خودش از چندین بخش یا فیچر تشکیل شده.در واقع اپیک یه چتره برای چند تا استوری یا تسک مرتبط.مثال از لرنادو:اپیک: بهبود تجربه‌ی یادگیری شخصی‌سازی‌شدهاین اپیک شامل فیچرهایی مثل:پیشنهاد درس بعدی بر اساس سابقه تماشانمایش پیشرفت یادگیریارسال نوتیف یادآوری مطالعهیعنی اگه بخوای تو برد تیم بنویسی:اپیک = «Personalized Learning» یا «یادگیری شخصی سازی شده»زیرش چندین استوری داری که هرکدوم بخشی از اون هدف بزرگ رو محقق می‌کنن.۲. Story (استوری)استوری معمولا از همون یوزر استوری‌ای میاد که تو فصل قبل یاد گرفتیم.هر استوری یه نیاز خاص از کاربر رو نشون می‌ده که لازمه برای رسیدن به هدف اپیک برآورده بشه.مثال از لرنادو:استوری: به‌عنوان کاربر، می‌خوام درس بعدی رو براساس ویدیوهای قبلیم ببینم.زیر این استوری، چند تا تسک داری:طراحی API برای پیشنهاد درس بعدیساخت مدل یادگیری در بک‌اندطراحی UI برای کارت درس پیشنهادیهر استوری باید نتیجه‌محور باشه، نه فعالیت‌محور.یعنی بگی «کاربر بتونه...»، نه «من بنویسم...»۳. Task (تسک)تسک یعنی کار مشخصی که باید انجام بدی تا یه استوری کامل بشه.تسک‌ها معمولاً فنی‌تر و دقیق‌ترن.مثال از لرنادو:برای استوری بالا، تسک می‌تونه باشه:ایجاد endpoint /api/recommendationsنوشتن unit test برای الگوریتمادغام پیشنهادها در صفحه‌ی داشبوردتسک‌ها معمولاً با زمان تخمینی یا استوری پوینت اندازه‌گیری می‌شن.۴. Sub-task (ساب‌تسک یا زیرتسک)وقتی یه تسک خودش خیلی بزرگه یا بین چند نفر تقسیم می‌شه، به ساب‌تسک‌ها خردش می‌کنی.این‌جوری کارها موازی پیش می‌رن و مدیریت‌ش راحت‌تره.مثال از لرنادو:تسک: ساخت API برای پیشنهاد درسساب‌تسک‌ها:نوشتن مدل پیشنهاد با پایتوناتصال مدل به دیتابیس کاربراننوشتن تست و داکیومنت۵. Bug (باگ)باگ یعنی هر چیزی که برخلاف انتظار کاربر کار می‌کنه.ممکنه تو بک‌اند باشه، UI، یا حتی تجربه‌ی کاربری.مثال از لرنادو:بعد از پخش سه ویدیو، سیستم به اشتباه درس تکراری پیشنهاد می‌دهدکمه‌ی «ادامه یادگیری» تو موبایل کار نمی‌کنهنکته مهم اینه که تو تیم‌های حرفه‌ای، باگ‌ها هم تسک محسوب می‌شن و وارد همون برد اجایل می‌شن، با اولویت مخصوص خودشون.۶. Spike (اِسپایک)اسپایک یعنی تحقیقی کوتاه و هدف‌دار برای پیدا کردن جواب یه سوال فنی یا محصولی قبل از شروع توسعه.هدفش کدنویسی نیست، یادگیریه.مثال از لرنادو:«بررسی اینکه آیا استفاده از OpenAI برای پیشنهاد درس بعدی مقرون‌به‌صرفه‌ست یا نه؟»نتیجه‌ی اسپایک معمولاً یه سند خلاصه از یافته‌هاست، نه کد.۷. Technical Debt (بدهی فنی)بدهی فنی یعنی تصمیم‌های موقتی یا راه‌حل‌های سریع که در آینده باید برگردی و اصلاحشون کنی.مثل وقتی یه میانبر زدی برای رسیدن سریع‌تر به ددلاین.مثال از لرنادو:«فعلاً ولیدیشن سمت سرور رو حذف کنیم تا نسخه‌ی MVP سریع‌تر لانچ شه.»اگه این بدهی‌ها رو تسویه نکنی، بعداً تبدیل به زمین باتلاقی می‌شن که تیم رو کند می‌کننسلسله‌مراتب در یک نگاهجمع‌بندی فصل دومتو این فصل یاد گرفتیم چطور از یه هدف بزرگ (اپیک) برسیم به کارهای کوچک (تسک و ساب‌تسک)، و چطور باگ‌ها و تحقیقات فنی هم بخشی از چرخه‌ی طبیعی توسعه‌ان.یادت باشه:تیمی که اپیک و تسک‌هاش شفافه، سریع‌تر حرکت می‌کنه و کمتر گیج می‌شه.فصل سوم: از اسپرینت تا دیلی — چطور کارهامون رو زمان‌بندی و اجرا کنیموقتی تسک‌ها و اپیک‌ها مشخص شدن، حالا وقتشه تصمیم بگیریم کِی، چطوری و با چه سرعتی انجام‌شون بدیم.اینجا دقیقاً همون‌جاست که فلسفه‌ی اجایل (Agile) وارد بازی می‌شه.۱. Sprint (اسپرینت)اسپرینت یعنی یه بازه زمانی ثابت (معمولاً دو هفته‌ای) که تیم توش یه مجموعه از تسک‌ها رو انتخاب می‌کنه و تعهد می‌ده تا آخر بازه انجامش بده.بهش مثل یه مسابقه‌ی دو سرعت نگاه کن:یه مسیر کوتاه، با هدف مشخص، و تمرکز کامل.مثال از لرنادو:اسپرینت دوم مهر:هدف: بهبود تجربه‌ی دیدن ویدیوشامل:ساخت پلیر جدید با کنترل سرعترفع باگ تکرار ویدیواضافه کردن نوار پیشرفت دیدن درسنکته مهم: توی اسپرینت، تمرکز تیم باید روی انجام کارهای انتخاب‌شده باشه، نه اضافه کردن کار جدید وسط راه.۲. Backlog (بک‌لاگ)بک‌لاگ یعنی لیست همه‌ی ایده‌ها، تسک‌ها و فیچرهایی که هنوز تو برنامه‌ی فعلی نیستن ولی ممکنه بعدا انجام بشن.بهش فکر کن مثل یه «صف انتظار» برای فیچرها.مثال از لرنادو:امکان گذاشتن کامنت زیر هر درسحالت تاریک اپسیستم امتیازدهی به مدرس‌هااینا هنوز تو اسپرینت فعلی نیستن، ولی تو بک‌لاگ نگه‌داری می‌شن تا در زمان مناسب اولویت بگیرن.۳. Sprint Planning (اسپرینت پلنینگ یا برنامه‌ریزی اسپرینت)جلسه‌ایه که در ابتدای هر اسپرینت برگزار می‌شه تا تیم تصمیم بگیره کدوم تسک‌ها قراره تو این بازه انجام بشن.توی این جلسه، معمولاً سه کار انجام می‌شه:بررسی تسک‌های بک‌لاگانتخاب تسک‌هایی که با ظرفیت تیم هم‌خونی دارنتخمین استوری پوینت برای هر تسکمثال از لرنادو:تو جلسه‌ی برنامه‌ریزی، تیم تصمیم می‌گیره فیچر «کنترل سرعت ویدیو» رو وارد اسپرینت کنه و براش ۸ استوری پوینت زمان تخمین بزنه.۴. Daily Standup (دیلی استندآپ)جلسه‌ی روزانه‌ی کوتاه (۱۰ تا ۱۵ دقیقه) که معمولا سرپا برگزار می‌شه.هدفش این نیست که گزارش کار بدی، بلکه برای هماهنگی سریعه.سه سؤال اصلی تو دیلی:دیروز چی کار کردی؟امروز چی قراره انجام بدی؟چیزی هست که جلو کارت رو گرفته؟مثال از لرنادو:«دیروز API پیشنهاد درس رو تموم کردم، امروز تستش می‌کنم. فقط دیتاست تست هنوز آماده نیست.»نکته: دیلی باید کوتاه، دقیق و بدون بحث طولانی باشه. بحث‌های فنی بمونه برای بعد جلسه.۵. Sprint Review (بررسی اسپرینت)در پایان اسپرینت، تیم خروجی‌هاش رو به مدیر محصول یا ذی‌نفع‌ها نشون می‌ده.اینجا وقتِ «دمو»ست؛ یعنی نشون دادن اون چیزی که واقعاً ساخته شده.مثال از لرنادو:«تیم نسخه‌ی جدید پلیر ویدیو با کنترل سرعت رو دمو می‌کنه و فیدبک می‌گیره.»۶. Retrospective (رترو)رترو هم جلسه‌ایه، ولی نه برای محصول — برای خود تیم.هدفش یادگیری از اسپرینت قبلیه:چی خوب پیش رفت؟ چی نه؟ چطوری اسپرینت بعدی رو بهتر کنیم؟مثال از لرنادو:تو رترو تیم می‌گه:کار طراحی و توسعه همزمان خیلی مؤثر بودتخمین تسک‌ها زیاد بودتصمیم می‌گیریم از اسپرینت بعد هر تسک رو قبلش pair review کنیماین جلسات باعث می‌شن تیم به مرور باهوش‌تر، سریع‌تر و هماهنگ‌تر بشه.۷. Velocity (ولاسیتی)ولاسیتی یعنی میزان کاری که تیم تو هر اسپرینت انجام می‌ده.معمولاً با جمع استوری پوینت‌های تموم‌شده اندازه‌گیری می‌شه.مثال از لرنادو:اسپرینت اول: ۲۱ پوینت تموم شداسپرینت دوم: ۲۷ پوینتیعنی تیم داره بهتر می‌شه یا کارها دقیق‌تر تخمین زده شدن.۸. Burndown Chart (نمودار سوختن کار)یه نمودار ساده که نشون می‌ده تو طول اسپرینت، چقدر از کار باقی مونده.اگه خط نمودار صاف بمونه یعنی تیم کند شدهاگه شیبش ملایمه یعنی اسپرینت داره طبق برنامه پیش می‌ره.مثال از لرنادو:روز اول: ۲۵ استوری پوینت باقی‌موندهروز هفتم: ۱۰ تاروز آخر: ۰۹. Definition of Done (DOD یا تعریف انجام‌شده)یعنی اون استانداردی که تیم باهاش تعیین می‌کنه «یه کار کی تموم شده حساب می‌شه».این تعریف باید برای همه‌ی اعضا روشن باشه.مثال از لرنادو:«کدی که مرج شده، تست خودکار داره، داکیومنت نوشته شده و تو محیط staging تست شده.»جمع‌بندی فصل سومخلاصه‌ی کل فصل:اجایل فقط یه روش مدیریت نیست، یه طرز فکره.یعنی تکرار، یادگیری و بهبود مداوم — نه فقط تحویل فیچرها.فصل چهارم: ابزارها و مفاهیم مدیریتی تکمیلیهمه‌ی تیم‌ها اپیک و اسپرینت دارن، ولی فقط تیم‌های حرفه‌ای بلدن چطور کار رو اندازه بگیرن، اولویت بدن و جلو ببرن.اینجا با هم یاد می‌گیری چی باعث می‌شه یه تیم اجایل واقعی بشه، نه فقط ظاهراً اجایل.۱. Kanban Board (تخته کانبان)تخته‌ی کانبان یعنی یه صفحه‌ی تصویری برای نمایش وضعیت همه‌ی تسک‌ها.ستون‌ها معمولاً این‌طورن:| To Do | Doing | Review | Test | Done |هر تسک یه کارت کوچیکه که از چپ به راست حرکت می‌کنه تا تموم شه.هدفش اینه که همیشه بدونی تیم کجای کاره.مثال از لرنادو:فیچر «سرعت پخش» در ستون Doingباگ «پخش دوباره ویدیو» در Reviewفیچر «نوتیف مطالعه» در Doneابزارهای معروف برای کانبان:ترلو، جیرا، کلیک‌آپ و ...۲. Story Point (استوری پوینت)استوری پوینت یعنی میزان سختی، پیچیدگی یا زمان تقریبی انجام یه تسک.اعدادش واقعی نیستن (مثل ساعت)، بلکه نسبی‌ان.بیشتر تیم‌ها از دنباله‌ی فیبوناچی استفاده می‌کنن:۱، ۲، ۳، ۵، ۸، ۱۳، ۲۱ و ...مثال از لرنادو:طراحی UI: 3 پوینتساخت API: 5 پوینتنوشتن مدل هوش مصنوعی: 13 پوینتهدفش تخمین مطلق نیست، بلکه کمک به مقایسه‌ی تلاش‌ها و اندازه‌گیری ظرفیت تیمه.۳. Priority (اولویت)اولویت یعنی اهمیت نسبی هر تسک نسبت به بقیه.تسک‌ها معمولاً یکی از این سطح‌ها رو دارن:مثال از لرنادو:رفع باگ پرداخت = Highاضافه کردن تم تاریک = Mediumتغییر فونت اَپ = Low۴. Estimation (تخمین)تخمین یعنی پیش‌بینی منطقی از زمانی که انجام یه تسک طول می‌کشه.این معمولا تو جلسه‌ی اسپرینت پلنینگ انجام می‌شه.تکنیک معروفش پلنینگ پوکره (Planning Poker) — یعنی اعضای تیم با کارت‌هایی از استوری پوینت رای می‌دن و بعد از بحث، به یه عدد نهایی می‌رسن.مثال از لرنادو:تیم برای تسک «مدل پیشنهاد درس» بین ۸ و ۱۳ پوینت اختلاف داره → بحث می‌کنن → به ۱۳ رای می‌دن.۵. Roadmap (رودمپ)رودمپ نقشه‌ی راه محصوله.می‌گه تو چه بازه‌ای، چه فیچرهایی قراره ساخته بشن و چرا.رودمپ خوب همیشه به هدف و متریک وصل می‌شه، نه فقط به تاریخ.مثال از لرنادو:۶. Techniques for Prioritization (تکنیک‌های اولویت‌بندی)وقتی ده تا فیچر داری و فقط وقت برای ساخت سه‌تاش، باید بدونی کدوم سه‌تا بیشترین ارزش رو دارن.الف) MoSCoWچهار سطح اولویت:Must Have (باید داشته باشیم)Should Have (خوبه داشته باشیم)Could Have (می‌تونیم داشته باشیم)Won’t Have (فعلاً نداریم)مثال از لرنادو:Must Have: سیستم ویدیو و پیشنهاد درسShould Have: اعلان‌های شخصیCould Have: حالت تاریکWon’t Have: بلاگ داخلیب) RICE Frameworkیکی از دقیق‌ترین روش‌ها برای اولویت‌بندی فیچرها.هر فیچر یه امتیاز داره از حاصل فرمول:RICE = (Reach × Impact × Confidence) ÷ Effortمثال از لرنادو:فیچر «پیشنهاد درس بعدی»Reach = زیادImpact = بالاConfidence = 80٪Effort = زیاد=&gt; امتیاز RICE بالا =&gt; اولویت بالا۷. Definition of Ready (تعریف آمادگی)برخلاف Definition of Done، این یکی قبل از شروع کاره.می‌گه یه تسک چه شرایطی باید داشته باشه تا بتونه وارد اسپرینت بشه.مثال از لرنادو:معیار پذیرش تعریف شدهطراحی UI تایید شدهوابستگی‌ها مشخص شدن۸. Dependencies (وابستگی‌ها)یعنی یه تسک بدون انجام شدن یه کار دیگه نمی‌تونه پیش بره.وابستگی‌ها اگه درست مدیریت نشن، کل برنامه رو قفل می‌کنن.مثال از لرنادو:«نمی‌تونی API نوتیف بسازی تا وقتی سیستم احراز هویت تموم نشده.»۹. Burndown vs Burnupهر دو نمودارن ولی با جهت مخالفمثال از لرنادو:اگه تو Burndown نمودار سریع پایین نیاد، یعنی تیم داره کند پیش می‌ره.اگه تو Burnup صاف بمونه، یعنی کاری انجام نشده.۱۰. KPIs و OKRsKPI (شاخص کلیدی عملکرد)یعنی اون عددهایی که نشون می‌دن تیم چقدر خوب داره هدفش رو پیش می‌بره.مثال از لرنادو:KPI ماهانه = نرخ تکمیل ویدیوها، نرخ بازگشت کاربران جدید.OKR (هدف و نتیجه کلیدی)مدلی برای هدف‌گذاری هدفمند.هر Objective یه یا چند Key Result داره.مثال از لرنادو:Objective: افزایش تعامل کاربرانKey Result 1: نرخ تکمیل ویدیو از ۴۰٪ به ۶۰٪ برسهKey Result 2: میانگین جلسات یادگیری از ۲ به ۳ برسهجمع‌بندی فصل چهارمخلاصه‌ی فصل:ابزارهای اجایل مثل استوری پوینت یا RICE فقط ابزار نیستن — زبون مشترک تیم‌ان.باعث می‌شن تصمیم‌گیری از «حس» تبدیل بشه به «داده».فصل پنجم: سناریوی واقعی از اجرای یک اسپرینت در لرنادواینجا دیگه تئوری نداریم، فقط عمل.بریم ببینیم یه تیم محصول حرفه‌ای دقیقاً چطوری با همین مفاهیمی که تا الان یاد گرفتیم کار می‌کنه.مقدمه‌ی سناریومحصول ما، لرنادو، داره وارد مرحله‌ی جدید می‌شه.تا الان نسخه‌ی اولیه (MVP) بالا اومده: کاربر می‌تونه ثبت‌نام کنه، ویدیو ببینه، و درس‌های مشابه براش پیشنهاد بشه.اما مشکل جدیدی پیش اومده:تیم متوجه شده کاربرها درس‌ها رو نصفه رها می‌کنن.Retention افت کرده و تو کوهورت هفته‌ی سوم، فقط ۲۵٪ کاربرها برمی‌گردن 😬برای همین، تیم تصمیم می‌گیره یه اپیک جدید باز کنه:اپیک: افزایش نرخ تکمیل ویدیوهای آموزشی.گام ۱: تعریف اپیک و استوری‌هاگام ۲: انتخاب تسک‌ها برای اسپرینااسپرینت هفتم – مدت: ۲ هفتههدف: افزایش تعامل کاربر با ویدیوهااپیک مرتبط: نرخ تکمیل ویدیوکل پوینت‌ها: 34ظرفیت تیم در اسپرینت قبلی: 30 =&gt; کمی چالشی، ولی قابل انجام.گام ۳: Daily Standup (روز سوم اسپرینت)توسعه‌دهنده:دیروز endpoint ذخیره‌ی پیشرفت رو نوشتم، امروز تستش می‌کنم.فقط API نوتیف هنوز endpoint نداره، اون می‌تونه مانعم باشه.طراح UI:طراحی نوار پیشرفت تموم شد، در حال اتصال با تیم فرانت‌اند هستیم.مدیر محصول:یادتون باشه این اسپرینت هدف‌مون فقط تحویل کد نیست، می‌خوایم ببینیم »نرخ تکمیل درس» حداقل ۱۵٪ رشد کنه.گام ۴: Mid-Sprint Review (مرور میانی)نیمه‌ی اسپرینت، تیم یه جلسه سریع مرور می‌ذاره:API کار می‌کنهنوتیف هنوز درگیر پرمیشن‌هاستتست‌ها روی دستگاه‌های iOS کند انجام می‌شننتیجه: یکی از تسک‌های استوری ۳ (امتیازدهی) به اسپرینت بعد منتقل می‌شه.به‌جاش باگ پخش مجدد ویدیو که روی تجربه اثر می‌ذاشت وارد اسپرینت می‌شه.گام ۵: اسپرینت ریویو (نمایش خروجی)آخر اسپرینت، تیم نسخه‌ی جدید رو نشون می‌ده:نسخه‌ی جدید لرنادو:نوار پیشرفت زیر هر ویدیونوتیف هوشمند برای درس ناتمامرفع باگ پخش مجددمدیر محصول شاخص‌های اولیه رو می‌خونه:نرخ تکمیل ویدیو از ۴۵٪ به ۵۸٪ رسیدهمیانگین زمان تماشا ۲.۴ برابر شده.همه خوشحال، ولی هنوز کار تموم نیست...گام ۶: Retrospective (جلسه بازنگری)توی رترو، تیم یادداشت‌هاش رو مرور می‌کنه:گام ۷: متریک‌ها بعد از اسپرینتنتیجه واضح بود:اپیک موفقیت‌آمیز بود، اما استوری ۳ باید در اسپرینت بعدی ادامه پیدا کنه.گفت‌وگوی پایانی تیمتوسعه‌دهنده:حالا فهمیدم چرا می‌گین اپیک مهمه؛ چون هدف کل اسپرینت رو مشخص می‌کنه.طراح:من تازه دیدم چقدر نوتیف ساده می‌تونه رفتار کاربر رو عوض کنه.مدیر محصول:اجایل یعنی همین. تکرار، یادگیری، و بهبود مداوم.جمع‌بندی فصل پنجماین سناریو خلاصه‌ی کل مسیر دنیای محصول بود:یه مشکل واقعی شناسایی شد (ریزش کاربر).اپیک و استوری‌ها بر اساس داده ساخته شدن.تسک‌ها تخمین زده و تو اسپرینت برنامه‌ریزی شدن.دیلی و ریویو باعث شفافیت و هم‌راستایی شدن.رترو مسیر رشد تیم رو روشن کرد.در واقع، مدیریت محصول یعنی همین چرخه‌ی مداوم:فکر کردن، ساختن، سنجیدن، اصلاح کردن، و دوباره فکر کردن.جمله پایانیبرنامه‌نویس خوب کد تمیز می‌نویسه.تیم خوب محصول تمیز می‌سازه.ولی تیمی که فکر می‌کنه، یاد می‌گیره و بهبود می‌ده — آینده رو می‌سازه.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Mon, 10 Nov 2025 17:55:50 +0330</pubDate>
            </item>
                    <item>
                <title>راهنمای کامل ساخت محصول دیجیتال از صفر تا صد، همراه با مثال</title>
                <link>https://virgool.io/@pakzad/product-guide-l1yvs7oaryil</link>
                <description>برنامه‌نویس‌ها فقط کد نمی زنن، گاهی باید آینده محصول رو هم پیش بینی کننگاهی وقت‌ها وسط یه تسک فنی سنگین، یه چیزی ته ذهنم رو قلقلک میده: اگه من بتونم تصمیم بگیرم، این فیچر بهتره کِی بره پروداکشن؟ اصلا این فیچر کاربردی و لازمه؟ کاربر دوستش داره یا فقط خودم فکر می‌کنم چیز خفنیه؟اگه تو هم یه توسعه دهنده‌ای که کم‌کم داری وارد تصمیم‌گیری‌های مهم‌تر تو تیم می‌شی، احتمالاً این فکرها برات آشناست. از یه جایی به بعد، فقط بلد بودن فریم‌ورک و دیزاین پترن و دیپلوی کافی نیست. باید بدونی چرا یه فیچر قراره ساخته بشه، واسه کی ساخته می‌شه، و چه دردی رو حل می‌کنه.به این سبک فکر کردن، تفکر پروداکتی می‌گن. یه مدل ذهنی که برای هر کسی که قراره مسئولیت یه محصول رو به‌عهده بگیره، ضروریه. فرقی نمی‌کنه CTO باشی، مدیر محصول، یا حتی دولوپری که تازه به تیم ملحق شده.تو این مقاله قراره با هم یاد بگیریم:تفکر پروداکتی یعنی چی و چرا مهمه؟چطور از دل یه پروژه فنی، به تصمیم‌های پروداکتی برسیم؟پرسونای کاربر یعنی چی و چه کمکی به ما می‌کنه؟چطور رودمپ (Roadmap) بچینیم، Core Loop طراحی کنیم و متریک موفقیت محصول رو بسنجیم؟با مثال واقعی از یه فروشگاه اینترنتی که هنوز نرفته بازار ولی تیمش داره براش فکر استراتژیک می‌کنهو همه‌چی رو با یه لحن ساده و کاربردی می‌گیم، نه با واژه‌های خشک.تو این مقاله، مثالی که می‌زنیم یه پروژه‌ی فرضی فروشگاهی به اسم فروشگاه دیجینورم هست. یه فروشگاه اینترنتی خیالی مواد غذایی ارگانیک که هنوز MVP نداره، ولی تیم فنی و مدیر محصولش دارن فاز طراحی و توسعه‌ش رو می‌چینن.چرا از پروژه‌های خودم مثال نمی‌زنم؟ چون هدف این مقاله اینه که مدل فکر کردن رو یاد بگیریم، نه فقط داستان یه ایده خاص رو.تفکر پروداکتی یعنی چی؟ فرقش با فقط کد زدن چیه؟یه روزهایی بود که فقط کد می‌زدیم. یه تسک می‌اومد تو تسک‌بورد، می‌دیدی که نوشته مثلاً:امکان آپلود فایل اکسل برای محصولات اضافه بشهبعد هم شروع می‌کردی یه پکیج نصب کردی، روت، کنترلر، ریکوئست فایل و سایر فایل‌های منطبق با پروژه رو نوشتی، تستش کردی و تمام.اما از یه جایی به بعد، دیگه این مدل فکر کردن کافی نیست. چون اون کسی که کد می‌زنه، در واقع داره منطق اجرایی یه تصمیم تجاری یا پروداکتی رو می‌سازه. یعنی چی؟یعنی اگه نفهمی اون اکسل قراره چه دردی از کاربر دوا کنه، ممکنه اون‌قدر بد و سرسری پیاده‌ش کنی که اصلاً نشه بعداً تغییرش داد، یا خیلی پیش‌فرض‌های اشتباه توش بذاری.تفکر پروداکتی یعنی چی؟یعنی به‌جای اینکه فقط بپرسی چطوری پیاده‌سازی کنم؟ اول بپرسی چرا این فیچر قراره ساخته بشه؟ برای کیه؟ چه مشکلی رو حل می‌کنه؟ اگه حذفش کنیم چی می‌شه؟در واقع میشه گفت محصول روی چرایی تاکید داره و تکنیکال روی چگونگی.تفکر پروداکتی یا محصول محور، یعنی تو یه توسعه‌دهنده‌ای که دغدغه‌ی تجربه کاربر رو هم داری، نه فقط اجرای درست توی مرورگر یا ذخیره درست دیتا توی دیتابیس.مثال از دیجینورمتیم فنی یه تسک گرفتن: فیلتر محصولات بر اساس نوع تغذیه (مثلاً گیاه‌خوار، وگان، بدون گلوتن)حالا تفاوت دو مدل فکر رو ببین:مدل فنی و پروداکتیپس تفاوت کجاست؟تفاوت توسعه‌دهنده و توسعه‌دهنده با ذهن پرواکتیآیا باید حتماً مدیر محصول باشی که اینطوری فکر کنی؟نه، ولی اگه می‌خوای یه CTO خوب باشی، یا می‌خوای تو استارتاپت تصمیم‌ساز بشی، باید این مدل فکر کردن رو یاد بگیری.یادت باشه: کسی که فقط کد بلده، همیشه بهش دستور داده می‌شه.ولی کسی که محصول رو می‌فهمه، خودش هم تصمیم‌گیرنده‌ست.سوال‌هایی که یه آدم پروداکت‌فکر از خودش می‌پرسه:چرا این فیچر اصلاً باید ساخته بشه؟کاربر کیه؟ الان چی داره اذیتش می‌کنه؟آیا این فیچر مشکل واقعی رو حل می‌کنه یا فقط یه ایده‌ی قشنگه؟اگه این فیچر ساخته نشه، کاربر چی رو از دست می‌ده؟موفقیت این فیچر با چی سنجیده می‌شه؟ (کدوم متریک؟)جمع‌بندی بخش اولتفکر پروداکتی یه مهارت یک شبه نیست. اما از همین امروز می‌تونی تو تیم خودت این سؤال‌ها رو بپرسی، قبل از اینکه کدتو بنویسی و پوش (push) کنی.مخصوصا وقتی یه پروژه هنوز نرفته بازار (مثل فروشگاه دیجینورم)، تو بهترین زمان برای شکل دادن به محصول هستی. حالا نوبت توئه که فقط کدنویس نباشی، بلکه طراح تجربه هم باشی.این سوالات یه مفهوم آشنا رو به یادت نمیاره؟ آره، منظورم پرسونای کاربره.پرسوناپرسونا چیه؟ چرا باید از دید کاربر به محصول نگاه کنیم؟فرض کن داری برای فروشگاه دیجینورم یه فیچر طراحی می‌کنی:پیشنهاد غذای سالم برای سبد خرید کاربران بر اساس سابقه خریدشونایده باحاله، فنی هم جذابه. ولی یه سوال اساسی این وسطه:این فیچر دقیقاً برای کیه؟اگه جوابش این باشه: «واسه همه کاربرا»، بدون که داری راهو اشتباه میری. چون هیچ فیچری &quot;برای همه&quot; نیست.تو باید بدونی که اون آدمی که قراره از این فیچر استفاده کنه، چه زندگی‌ای داره، دغدغه‌ش چیه، و اصلاً چرا اومده سراغ فروشگاه تو.پرسونا یعنی چی؟پرسونا یعنی یه نمایه خیالی اما واقعی از یه کاربر هدف.انگار داری یه شخصیت خلق می‌کنی که می‌تونه نماینده‌ی صدها یا هزاران نفر از مشتری‌هات باشه.نه صرفاً یه دیتاپوینت مثل سن و جنسیت، بلکه یه انسان با رفتار، احساس، نیاز، انگیزه، و حتی ترس!چرا ساختن پرسونا مهمه؟چون تا وقتی ندونی داری برای کی می‌سازی، نمی‌تونی تصمیم بگیری:این فیچر اصلاً لازمه یا نه؟توی چه لحظه‌ای از سفر کاربر باید نشونش بدی؟چطوری باید UI و متن و زمان‌بندی‌ش باشه؟اصلاً انتظار چه تعاملی ازش داریم؟مثال از فروشگاه دیجینورمبیاین با هم سه پرسونا برای این فروشگاه طراحی کنیم. هم ساده‌ست، هم واقعیه، هم می‌شه ازش کلی تصمیم پروداکتی درآورد.پرسونا ۱: علیرضا، کارمند مجردپرسونای علیرضاپس چی یاد گرفتیم؟برای علیرضا، ما باید:دسته‌بندی آماده ولی سالم بسازیمتوی صفحه اصلی یا سبد خریدش، غذاهای آماده پیشنهاد بدیمتایم نوتیفمون باید بعد ساعت کاری باشه (مثلاً ۱۸ تا ۲۰)پرسونا ۲: نسترن، مادر دو فرزندنتیجه؟برای نسترن، بهتره:پیشنهادهای سبد خانواده با تخفیف نشون بدیممحتوای آموزشی سبک مثل چی بخوریم که هم بچه‌ها بخورن هم سالم باشه براش بفرستیمتوی تجربه خرید، از اصطلاحات پیچیده تغذیه‌ای استفاده نکنیمپرسونا ۳: کیوان، ورزشکار منظمچی درمیاد از این؟برای کیوان لازمه:فیلتر دقیق برای «پروتئین بالا»، «بدون قند»، «بدون لاکتوز» بسازیممقایسه محصولات با هم فراهم کنیم (مثلاً بین دو برند کره بادام زمینی)رابط کاربری اَپِمون یه حس تخصصی بهش بده، نه فقط عام‌پسندپس چی شد؟وقتی این سه پرسونا رو داشته باشیم:می‌دونیم هر فیچر برای کی ساخته می‌شهطراحی‌ها هدف‌دارتر می‌شنتبلیغات هدفمندتری اجرا می‌شنتیم فنی بهتر می‌فهمه چطور تست کنه یا اولویت بدهدر بخش بعدی مقاله، می‌ریم سراغ ساختار تصمیم‌گیری حرفه‌ای با ابزارهایی مثل:رودمپCore Loopمتریک ستاره شمالی (North star Metric)که همش از دل همین پرسونای بالا درمیاد.از پرسونا تا تصمیم‌گیری – چطوری رودمپ، کور لوپ و متریک ستاره شمالی رو بچینیم؟خب، حالا که پرسوناهای کاربرامون رو شناختیم، وقتشه تصمیم‌هایی که قراره درباره‌ی محصول بگیریم بر اساس همونا باشه، نه صرفا ایده‌هایی که تو ذهن خودمون قشنگ به نظر میان.بریم سراغ ابزارهایی که هر تیم فنی-محصولی باید بلد باشه و استفاده کنه:رودمپ چیه و چرا باید داشته باشیم؟یه رودمپ در واقع نقشه‌ی راه محصوله. نشون می‌ده که چه چیزهایی قراره کی ساخته بشه، به چه دلیل، و با چه اولویتی.اما فرق یه رودمپ خوب با یه لیست فیچر چیه؟یه لیست فیچر صرفاً می‌گه چی داریم می‌سازیم.ولی رودمپ می‌گه چرا داریم می‌سازیم، برای کی داریم می‌سازیم و چه نتیجه‌ای براش در نظر داریم.نمونه رودمپ سه‌ماهه برای دیجینورمماه اول: زیرساخت و هسته اولیهساخت سیستم ورود / ثبت‌نام با موبایلطراحی صفحه لیست محصولاتساخت سبد خرید اولیهاضافه کردن برچسب‌ محصولات (پروتئین بالا، بدون شکر، و...)هدف: آماده‌سازی ساختار پایه برای نمایش و خرید محصول، هماهنگ با نیاز کیوان (پرسونای ورزشکار)ماه دوم: بهبود تجربه کاربرسیستم پیشنهاد هوشمند (بر اساس دسته‌بندی یا سابقه خرید)اضافه کردن فیلتر پیشرفته برای محصولات خاصشروع نوتیف‌های شخصی‌سازی‌شده (پیشنهاد امروز، تخفیف شخصی)هدف: پاسخ به نیاز علیرضا و نسترن که دنبال پیشنهاد و راحتی هستنماه سوم: وفادارسازی و رشداضافه‌کردن برنامه وفاداری یا تخفیف پلکانیامکان ثبت آدرس متعدد و خرید سریعراه‌اندازی کمپین دعوت از دوستانهدف: رشد ارگانیک با حفظ کاربران فعلی + افزایش تعاملچطور اولویت‌گذاری کنیم؟برای هر فیچر توی رودمپ، از خودت بپرس:این فیچر به کدوم پرسونا کمک می‌کنه؟چه مشکلی رو براش حل می‌کنه؟بعد از پیاده‌سازی این فیچر، چه رفتاری از کاربر انتظار داریم؟می‌تونیم نتیجه‌ش رو اندازه‌گیری کنیم یا نه؟دیاگرام حلقه خریدCore Loop چیه و چطوری طراحی‌ش کنیم؟Core Loop همون چیزیه که باعث می‌شه کاربر دوباره و دوباره برگرده سراغ محصول. یه چرخه‌ی ساده اما اثرگذار از تجربه.مثالی از دیجینورم:Core Loop پیشنهادی:کاربر محصولی می‌خرهبراساس خریدش، محصولات مشابه یا مکمل پیشنهاد داده می‌شهتخفیف کوچیکی برای خرید بعدی می‌گیرهمیاد دوباره می‌خرهو این چرخه ادامه پیدا می‌کنه.مثال از پرسونا:نسترن وقتی خریدشو تموم می‌کنه، تو صفحه «تشکر از خرید» یه پیشنهاد «سبد تغذیه خانواده برای هفته آینده» می‌بینهچون از پیشنهاد خوشش میاد و تخفیف ۱۰٪ هم داره، می‌ره سراغ خرید بعدینتیجه؟کاربر با هر خرید، یه حلقه جدید از تعامل رو شروع می‌کنه.متریک ستاره شمالی چیه؟ستاره شمالی متریکیه که بیشترین ارتباط رو با ارزش اصلی محصول داره.یعنی اگه این عدد رشد کنه، یعنی واقعاً داری ارزش تولید می‌کنی.متریک ستاره شمالی به صورت مخفف NSM هم نامیده می‌شهاشتباه رایج:خیلیا فکر می‌کنن تعداد ثبت‌نام کاربر یا بازدید از سایت متریک خوبیه.اما یه NSM واقعی اونیه که ارزش محصولت رو منعکس کنه.برای دیجینورم چی می‌تونه باشه؟تعداد سبدهای خرید کامل‌شده در ماه که شامل حداقل یک محصول سالم پیشنهادی هستنچرا این خوبه؟فقط بازدید یا ورود نیست، یعنی کاربر داره خرید می‌کنهفقط خرید نیست، یعنی داره پیشنهادهای سالم رو می‌پذیرهمستقیم نشون می‌ده محصول داره چطور رفتار خرید سالم رو جا می‌ندازهچند مثال دیگه برای درک بهتر:جمع‌بندیرودمپ خوب یعنی بدونی چی رو کی و چرا می‌سازیCore Loop یعنی ایجاد رفتار تکرارشونده و وابستهستاره شمالی یعنی بدونی موفقیت واقعی محصولت با چی سنجیده می‌شهاین سه ابزار، ستون فقرات تفکر پروداکتی هستن.تو بخش بعدی مقاله می‌ریم سراغ چیزی که خیلیا جدی نمی‌گیرن اما کل بازیو می‌تونه عوض کنه:متریک‌های شکست، ریزش کاربر (Churn)، و اینکه چطوری محصول رو بهتر کنیم قبل از اینکه دیر بشه.ریزش کاربر، متریک‌های هشدار و اصلاح محصول قبل از سقوطیکی از بزرگ‌ترین توهم‌های پروداکتی اینه که چون کاربر اومده، پس مونده!نه عزیز، اومدن مهم نیست، موندن مهمه.و اینجا دقیقاً جاییه که متریک‌های Retention و Churn میان وسط.Churn Rate چیه؟Churn یعنی ریزش و Churn Rate یعنی نرخ ریزش کاربر.به زبون ساده کاربری که یه بار اومده، ولی دیگه برنگشته.یعنی کسی که یه تجربه با محصولت داشته ولی دلیل کافی برای ادامه ندیده.اگه یه کاربر ثبت‌نام کنه ولی هیچ‌وقت خرید نکنه، یا یه بار خرید کنه ولی دیگه وارد اپ نشه، این یعنی Churn.Retention Rate چیه؟ریتِنشن یعنی بازگشت کاربر یا به زبون ساده یعنی اینکه تونستی کاربر رو نگه داری و کاملا برعکس Churn است.یعنی چند درصد از کاربرهایی که روز اول اومدن، روز ۷ هم باهاتن؟ روز ۳۰ چی؟ روز ۹۰؟مثالی از دیجینورم:فرض کن در ماه اول ۱۰۰۰ نفر ثبت‌نام کردن.این یعنی ۹۱۰ نفر دیگه برنگشتن! تازه شاید از اون ۹۰ نفر هم فقط ۲۰ تا خرید انجام داده باشن.چرا کاربرها ریزش می‌کنن؟دلایلش خیلی گسترده‌ست ولی معمولاً به یکی از این ۵ مورد برمی‌گرده:ارزش واقعی محصول رو دریافت نکردنUI/UX پیچیده یا گیج‌کننده بودهزمان مناسبی وارد تعامل نشدنفیچرها با نیازشون هم‌راستا نبودهرقیب دیگه‌ای تجربه‌ی بهتری ارائه دادهچطوری ریزش رو اندازه‌ بگیریم؟یکی از ابزارهای خوب برای این کار Cohort Analysis یا آنالیز کوهورت هست.کوهورت یعنی گروهی از کاربران که در یک بازه زمانی مشابه ثبت‌نام کردن یا کاری انجام دادن، و رفتار اون گروه طی زمان بررسی می‌شه.مثال آنالیز کوهورت برای دیجینورم:جدول کوهورتاین جدول نشون می‌ده که تو هفته دوم، وضعیت retention بدتر شده. شاید آپدیتی زدی که تجربه‌ی کاربری رو بدتر کرده؟ یا تبلیغاتی کردی که آدمای اشتباهی رو جذب کرده؟نکته: جدول بالا میگه که مثلا ۱۴ روز بعد از هفته اول ۱۸۰ نفر و ۱۴ روز بعد از هفته دوم ۱۲۰ نفر بازگشت داشتیم.چه متریک‌هایی باید دائم چک بشن؟ (متریک‌های هشدار)چطور جلوی Churn رو بگیریم؟آنبوردینگ ساده و هدایت‌شده بسازتو روز اول، کاری نکن کاربر فقط بگرده. هدایتش کن به یه موفقیت کوچیک.پیشنهادهای شخصی‌سازی‌شده بدههمون پرسوناها رو یادت هست؟ فیچرها رو با توجه به اون طراحی کن.نوتیف هوشمند و به‌موقع بفرستنه زیاد، نه دیر. نه کلی، نه عمومی.استفاده از تخفیف یا امتیاز برای برگشتکسی که ۷ روز نیومده، براش یه کد تخفیف ۲۴ ساعته بفرستبازخورد واقعی بگیرساده‌ترین راه: یه فرم یا یه نوتیف بفرست که بپرسه: &quot;چرا دیگه نیومدی؟ چی اذیتت کرد؟&quot;مثال نهایی از دیجینورم:علیرضا (پرسونا اول)، هفته‌ی اول ثبت‌نام کرده ولی هیچ خریدی نکرده.آنالیز کوهورت نشون می‌ده که ۷۰٪ کسایی که مثل علیرضا خرید نکردن، هیچ‌وقت هم برنگشتن.راه‌حل؟یه نوتیف (نوتیف اپلیکیشن موبایل یا SMS)‌ با این متن:علیرضا جان، دیدیم هنوز سبد خریدت خالیه... اگه خرید اولتو انجام بدی، ۱۵٪ تخفیف هم می‌گیری. یه پیشنهاد سبک و سالم همین الان برات داریمنتیجه‌گیریفقط ساختن فیچر کافی نیست. نگه داشتن کاربر، کار اصلیه.و نگه داشتن کاربر فقط با کدنویسی تمیز به دست نمیاد، با تفکر پروداکتی و رفتارشناسی و طراحی تجربه‌ست.مسیر تبدیل شدن به یک CTO با ذهن پروداکتی (جمع‌بندی + دستورالعمل عملیاتی)اگه تا اینجای مقاله رو خوندی، یعنی احتمالاً تو هم مثل من زمانی فقط یه توسعه‌دهنده بودی که وظیفه‌ش فقط تحویل درست و به‌موقع تسک‌ها بود.اما الان می‌دونی که نقش تو می‌تونه خیلی فراتر از کد زدن باشه؛ تو می‌تونی کسی باشی که آینده‌ی محصول رو شکل می‌ده.تو این بخش می‌خوایم همه‌ی چیزایی که یاد گرفتیم رو خلاصه کنیم و یه مسیر روشن برای ارتقاء فکری و کاری طراحی کنیم.۱. ذهنیت پروداکتی چیه؟ یادمون نره...همیشه بپرس «چرا؟» قبل از اینکه بپرسی «چطور؟»بدون که کار تو فقط تحویل کد نیست؛ تو داری یه تکه از تجربه‌ی کاربر رو می‌سازیبه جای “فیچرزدن”، دنبال “حل مسئله” باشهمه‌ی کارهات باید یه “پرسونا” پشتش باشه. اگه نباشه، داری برای خلا می‌سازیاولویت بده به چیزی که باعث رفتار واقعی می‌شه، نه فقط «قشنگ به نظر میاد»۲. دستورالعمل عملیاتی برای ساخت محصول درستدستورالعمل عملیاتی ساخت محصول درست۳. مهارت‌هایی که باید جدی یاد بگیریاینا چیزاییه که یه CTO یا محصول‌ساز واقعی بهشون نیاز داره:Behavioral Design: چطور عادت ایجاد کنی؟Product Metrics: با عدد حرف بزن، نه فقط حسUser Research: بفهم کاربر چی می‌خواد، نه اینکه فقط فکر کنی می‌دونیPrioritization Techniques: یاد بگیر چی رو کی و چرا انجام بدی (مثلاً RICE یا MoSCoW)Storytelling: بتونی تصمیماتت رو برای تیم، مدیر یا سرمایه‌گذار توضیح بدی۴. ضدالگوهایی که باید حواست باشهضد الگوها۵. تمرین‌هایی برای تقویت تفکر پروداکتیاین تمرین‌ها رو برای خودم هم نوشتم، چون یادگیری‌اش دائمیه:هر فیچری که نوشتی رو با پرسونا تطبیق بده. اگه جواب نداشتی برای &quot;این به درد کی می‌خوره؟&quot; فیچر رو متوقف کن.هر هفته یک بار جلسه تحلیل رفتار کاربر بذار. حتی اگه فقط یه کاربر، یه ایمیل فرستاده.هر تسک فنی جدید، باید یه متریک خروجی داشته باشه. مثلاً انتظار داری بعدش نرخ خرید بره بالا؟ زمان موندن کاربر افزایش پیدا کنه؟با تیم غیرفنی صحبت کن. مارکتینگ، پشتیبانی، فروش... اونا خط مقدم تعامل با کاربرن.فیچرهایی که استفاده نمی‌شن رو حذف کن. این نشونه بلوغه. نه ضعف.یه CTO خوب، فقط چیزی نمی‌سازه که کار کنه؛ چیزی می‌سازه که معنا داشته باشه.نتیجه‌گیریتو دنیایی که پر از برنامه‌نویس خوبه، اونی موفق‌تره که بتونه محصول بسازه.محصول ساختن فقط ابزار و تکنولوژی نمی‌خواد، درک عمیق از انسان‌ها، انگیزه‌ها و رفتارها می‌خواد.تو اگه بخوای، می‌تونی توی تیم بعدی‌ات، نه‌فقط یه دولوپر خوب باشی، بلکه کسی باشی که موقع تصمیم‌گیری همه به حرفش گوش می‌دن. چون تو با ذهن پروداکتی فکر می‌کنی.اگر شما سال‌ها تجربه‌ی مدیریت محصول دارید، یا در حوزه‌های بزرگ‌تر مثل B2B یا SaaS کار می‌کنید، احتمالاً بخش زیادی از مباحث این مقاله براتون آشناست.برای یادگیری عمیق‌تر، پیشنهاد می‌کنم به منابع حرفه‌ای‌تری مثل:کتاب Inspired از Marty Cagan: این کتاب با نام الهام بخش توسط انتشارات هورمزد ترجمه و چاپ شدهکتاب Lean Product &amp; Lean Analyticsپادکست‌های Lenny’s Podcast یا Product Thinkingیا راهنمای عملی Reforge سر بزنیداما اگه تازه‌کارید یا از مسیر فنی وارد مدیریت محصول شدید، این مقاله براتون می‌تونه تبدیل به یه لنگر دائمی بشه.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Mon, 10 Nov 2025 02:18:54 +0330</pubDate>
            </item>
                    <item>
                <title>فرمول من برای سه برابر کردن سرعت مطالعه و یادگیری</title>
                <link>https://virgool.io/@pakzad/3x-reading-speed-cnv1fmqfiiuy</link>
                <description>چند ماه پیش به خاطر کار و پروژه‌های مختلف اون‌قدر ‌سرم شلوغ شد که حتی وقت سر خاروندن هم نداشتم؛ ولی هنوز دلم می‌خواست کتاب بخوانم، مهارت‌های جدید یاد بگیرم و مهم‌تر از همه، چیزایی که یاد گرفتم رو فراموش نکنم. دقیقاً تو همین وضعیت بود که با دوره‌ی SuperLearner آشنا شدم و تصمیم گرفتم تکنیک‌هاش رو روی خودم امتحان کنم.نتیجه چی شد؟ سرعت مطالعه‌ام تقریبا سه برابر شد و در طول یادگیری به یک الگوی خیلی ساده رسیدم که تو این مقاله، قدم به قدم تجربه‌ام رو می‌نویسم تا با خوندنش بتونین سه برابر سریع‌تر یاد بگیرین و مطالبی که می‌خونین رو خیلی راحت‌تر تو ذهنتون نگه دارین.حالا این یادگیری دقیقا چطور اتفاق می‌افته؟هر بار که یه مطلب جدید می‌خونین، سیگنالی الکتریکی از یه نورون به نورون دیگه می‌پره و دقیقا جایی که این دو تا نورون به هم می‌رسن (یعنی سیناپس)، جرقه می‌زنه. اگه این مسیر تکرار بشه، سیناپس مثل ردپایی که تو برف می‌ذاریم عمیق‌تر می‌شه. دانشمندا اسم این پدیده رو گذاشتن تقویت درازمدت (Long-Term Potentiation).بعد از چند بار مرور کردن، ماده‌ای به اسم میلین مثل یه روکش عایق دورِ این مسیر عصبی رو می‌گیره و باعث میشه سرعت عبور پیام، مثل سرعت انتقال دیتا تو فیبر نوری بالا می‌بره.میلین یه ساختار چربی‌ماننده که دور آکسون (رشته عصبی) بعضی از نورون‌ها تشکیل می‌شه و مثل یه عایق الکتریکی عمل می‌کنه. غلاف میلین رپی خیلی از آکسون‌ها و بعضی از دندریت‌ها شکل می‌گیره و باعث میشه نورون‌ها سفید به نظر بیان.به خاطر همین ویژگیه که مرور فاصله‌دار مثل معجزه جواب می‌ده: هر بار که مطالب قبلی رو مرور و دوباره یادآوری می‌کنین، در واقع مسیر عصبی رو دارین آسفالت می‌کنین و یادگیری رو از حالت موقت به بلندمدت تبدیل می‌کنین.نتیجه چی میشه؟ اطلاعات به جای اینکه کوتاه مدت سر بزنن و فرار کنن، مثل یه هم‌اتاقی دائمی کنارتون باقی می‌مونن.اول ذهنیت درست، بعد تکنیکقبل از اینکه دنبال تکنیک خاص و عجیب بگردین، یه چیزی رو باید مثل میخ تو ذهنتون محکم کنین: مغز مثل عضله است.مغز دقیقا مثل عضله‌های دیگه است؛ هر چی بیشتر تمرینش بدین، قوی‌تر و کارآمدتر میشه. تمرین منظم برابر با بهبود عملکرد مغزه.یادگیری یه مهارته، نه یه استعداد. اگر امروز آروم یا کند می‌خونین، معنیش این نیست که همیشه همین‌جوری می‌مونین.تعهد روزانه خیلی مهم‌تر از ابزاره. کلید جادویی و خاصی وجود نداره؛ کلید اصلی همون تکرار کردنه.پس قرار نیست با یک پلاگین کروم یا یه اپلیکیشن جادویی راه صدساله رو یه شبه طی کنین؛ ولی با یه مقدار تعهد روزانه میشه به طرز محسوسی سرعت و کیفیت یادگیری رو بالا برد.راهکار عملییک هدف شفاف بنویس؛ مثلاً «می‌خوام توی شش هفته کتاب Designing Data-Intensive Applications رو تموم کنم».پیشرفت روزانه‌تون رو تو یه دفترچه یا ابزار Habit Tracker ثبت کنین. فقط روزهایی رو حساب کنین که واقعاً تمرین کردین.البته اپلیکیشن TickTick هم برای یادداشت برداری و مدیریت زمان خیلی خوبه و پیشنهاد می‌کنم حداقل یه بار امتحانش کنین.پشت صحنه حافظه را بشناسینحافظه سه تا ایستگاه اصلی داره:سه سلاح موثر برای انتقال مطالب از حافظه کوتاه‌مدت به بلندمدت وجود داره:مرور فعال: بعد از خوندن یه پاراگراف، کتاب رو ببندین و از خودتون بپرسین «چی یاد گرفتم؟ چرا مهم بود؟ کجا به دردم می‌خوره؟»فاصله‌گذاری هوشمند: یادداشت‌ها رو با فاصله‌های زمانی ۱، ۳، ۷، ۱۴ و ۳۰ روزه مرور کنین. برای این کار می‌تونین از اپلیکیشن‌هایی مثل Anki یا SuperMemo استفاده کنین که این فاصله‌گذاری‌ها رو به روش لایتنر مدیریت می‌کنن.اتصال به دانش قبلی: مطلب جدید رو به چیزایی که از قبل بلدین وصل کنین؛ مغز عاشق ایجاد ارتباطه و ساختار اصلیش هم بر اساس ارتباطه. این ارتباط می‌تونه بین تعداد حروف، موضوعات متفاوت و یا هر چیز دیگه‌ای باشه. مثلا مفهوم میدلور (Middleware) رو اگه یاد گرفتین، ربطش بدین به نگهبان ساختمون که قبل از ورود هر کسی چک می‌کنه که اون فرد ساکن ساختمونه (مالک یا مستأجر) یا مهمون یکی از واحدهاست یا نه، وگرنه اجازه ورود بهش نمی‌ده.کتاب، مهره شطرنج، سیبِ یادگیری، جام پیروزی، گیاه رشد مغز ما تصاویر رو ده‌ها هزار برابر سریع‌تر از متن پردازش می‌کنه؛ پس هر جا می‌تونین متن رو به تصویر تبدیل کنین. دو تکنیک طلایی برای این کار وجود داره:کاخ ذهنی (Memory Palace) بسازین: خونه خودتون می‌تونه کاخ یا خانه ذهنی باشه؛ هر اتاق رو یه موضوع در نظر بگیرین. مثلا اتاق پذیرایی رو برای مفاهیم شبکه در نظر بگیرین و سوئیچ رو به شکل چندراهی برق روی میز تلویزیون در نظر بگیرین، روتر رو به جای مودم کنار پنجره تصویر کنین. آشپزخونه رو برای مفاهیم امنیت در نظر بگیرین، دیوار یخچال رو با برچسب TLS قفل کنین و فر رو به فایروال تشبیه کنین. دفعه بعد که دنبال مفهوم صف بودین، کافیه در پارکینگ کاخ ذهنی رو به یاد بیارین که ماشین‌ها پشت سر هم برای خروج منتظرن.داستان‌سازی تصویری بسازین: اگر می‌خواین مثلا مفهوم «TCP Handshake» یادتون بمونه، دو همکار رو تصور کنین که سه بار کارت شناسایی خودشون رو با لبخند نشون میدن و دست میدن تا اجازه ورود بگیرن. اگر قراره پروتکل TLS رو بخاطر بسپرین، تصویر یه پستچی با قفل طلایی رو در نظر بگیرین که یه قفل طلایی توی دستشه و نامه رو فقط به صاحب نامه تحویل میده، این مثال سادگی و امنیت رمزنگاری رو توی ذهنتون تداعی می‌کنه.رنگ و کمی اغراق اضافه کنین؛ یک لود بالانسر رو مثل مامور راهنمایی با جلیقه فسفری وسط چهارراهی از داده‌ها تصور کنین که با سوت زردش هر دسته از داده‌ها رو به مسیر درستش هدایت می‌کنه. هرچی تصویر زنده‌تر و بامزه‌تری خلق کنین، راحت‌تر تو ذهن می‌مونه.نمادهای ذهنی؛ آیکون‌هایی برای مغزبه هر مفهوم یک نماد یا تصویر نسبت بدین، مثلا:کد تمیز: میز کار تمیز و مرتببنچمارک: خط پایان مسابقه دو با ساعت بالای ستونشکوبرنتیز: فانوس دریایی هشت ضلعی وسط اقیانوسنمادها باید ساده، منحصر‌به‌فرد و تا حدی بامزه باشن تا مغز عاشقشون بشه، اشکالی نداره که اغراق آمیز و خنده‌دار باشن حتی نتیجه بهتری هم میده. وقتی نیاز به یادآوری داشته باشین، مغز همون نماد رو صدا می‌زنه و اطلاعات پشتش میاد بیرون، درست مثل فلاش زدن دوربین برای ثبت عکس، همین قدر سریع.پیش‌خوانی؛ گرم‌کردن قبل از مسابقهاین کار مثل این می‌مونه که نقشه‌ی مسیر رو قبل از سفر ببینی؛ مغز در طول مطالعه تمام تابلوهای آشنا رو سریع‌تر تشخیص می‌ده.مراحل پیشنهادی پیش‌خوانی:تیترها و زیر‌تیترها رو سریع و با یه نگاه کوتاه اسکن کنین.چکیده یا خلاصه‌ی متن رو بخونین.جدول‌ها، نمودارها و تصاویر رو ببین.چند سوال کلیدی یادداشت کنین مثلاً این فصل چه مسئله‌ای حل می‌کند؟این کارها مسیر عصبی آشنایی می‌سازه؛ وقتی خوندن رو شروع کنین، مغز می‌گه: آهان، این دقیق همون موضوعیه که باید بفهمم! و سرعت درک به طرز چشم‌گیری افزایش پیدا می‌کنه.Photo by Mauro Lima on Unsplashحذف صدای ذهنی؛ راز اصلی تندخوانیهمون‌طور که با زیرلب زمزمه‌کردن نمی‌شه مسابقه دوی سرعت دوید، با درون‌گویی (Subvocalization) یا به اصلاح خوندن توی سر هم نمی‌شه تند خوند. در واقع درون گویی نمیزاره سرعت چشمت بالا بره.برای خاموش کردن این صدای سمج، چند تا راه وجود داره:انگشت یا قلم رو مثل لیزر زیر خط بکشین تا چشم فقط قلم رو دنبال کنه و باهاش جلو بره.ریتم حرکت چشمتون رو بالا ببرین؛ سعی کنین هر خط رو توی یه دم و بازدم بخونی و نذارین نگاهتون به عقب برگرده.پخش موسیقی بی‌کلام باعث میشه تا گوش مشغول بشه و مغز فرصت تکرار کلمات رو پیدا نکنه.گسترش میدان دید چشم؛ خواندن جمله‌های بلندترچشم انسان در هر پرش (Fixation) می‌تونه حدود سه تا پنج کلمه رو بگیره ولی احتمالا از این قابلیتش استفاده نکردین. به‌جای خوندن کلمه‌به‌کلمه، سعی کنین هر بار سه تا پنج کلمه رو با هم بخونین. تمرینش ساده است:روی یک متن مثلا متن کتاب، بلاک‌های سه‌کلمه‌ای بکشین.سعی کنین چشماتون رو روی همون بلاک قفل کنین و برین بعدی، یعنی در هر پرش فقط اول و آخر بلاک رو ببینین.سرعت رو کم‌کم بالا ببرین؛ بعد از دو هفته بلاک رو ۵کلمه‌ای کنین.مسیر چشم در مطالعهعادت‌های کوچک، نتایج بزرگ۱۵ دقیقه تمرین ثابت روزانه؛ اگر زمان بیشتری دارین، نوش جونتون، ولی این ۱۵ دقیقه باید مقدس باشه. بخاطر داشته باشین که باید هر روز این تایم رو بزارین، پس یه روز ۲ ساعت و یه روز صفر نباشه با همون ۱۵ دقیقه شروع کنین، اجازه بدین کم باشه ولی بتونین پیوسته انجامش بدین.مرور فاصله‌ای خودکار (Spaced Repetition)؛ واژه‌های زبان یا یادداشت‌های خودتون رو توی Anki وارد کنین و زمان‌بندی رو به الگوریتم بسپارین. این مرور فاصله‌ای دقیقا همون کاری رو می‌کنه که میلین برای نورون‌ها انجام میده؛ مسیر رو قطور و ماندگار می‌کنه.جمع‌بندی هفتگی؛ جمعه‌ها که معمولا تعطیله و زمان بیشتری دارین دو صفحه خلاصهٔ چیزهایی که یاد گرفتین رو توی دفترچه شخصی یا گوگل داکز بنویسین. این کار برای مرورهای آینده هم خیلی کاربردیه.استفاده عملیاین تکنیک‌ها فقط برای روز امتحان نیستن؛ در عمل هم بارها کارایی‌شون ثابت شده:مطالعه فنی: من با همین ترفندها، مستندات پیچیده فنی رو سریع‌تر می‌خونم و توی جلسات هم سریع بخش‌های مهم رو از کاخ ذهنی استخراج می‌کنم.مذاکره: ارقام و استدلال‌ها از قبل توی اتاق پذیرایی کاخ ذهنی چیده شدن و با یه مرور ذهنی، همه داده‌ها حاضر و آماده در اختیارم قرار می‌گیرن.جلسات مدیریتی: آمارها و KPIها را به نمادهای ساده مرتبط می‌کنم؛ بنابراین وقتی می‌خوام گزارشی ارائه بدم، بدون نگاه کردن به کاغذ یا اسلاید، اطلاعات دقیق از حافظم بازیابی می‌شن.جمع‌بندی و چک لیست نهاییخاموش‌کردن صدای ذهنی: متن باید با حرکت چشم اسکن بشه، نه با زمزمهٔ درونی.پیش‌خوانی سه‌دقیقه‌ای: پیش از ورود به هر مطلب، مرور سریع تیترها و چکیده، مسیر یادگیری رو هموار می‌کنه.تصویرسازی برای هر مفهوم: تخصیص یک نماد یا تصویر ذهنی به هر ایده، بازیابی اطلاعات رو چندبرابر آسون‌تر می‌کنه.مرورِ فاصله‌ای: استفاده از جعبه لایتنر (فیزیکی یا دیجیتال) مسیر عصبی رو تقویت و ماندگار می‌کنه.تمرین روزانهٔ ۱۵ دقیقه‌ای: حجم کم اما پیوسته، موتور حافظه رو روشن نگه می‌داره.یادگیری سریع عصای جادویی نیست؛ ترکیبی است از ذهنیت درست، تصویر سازی هدفمند، تکرار هوشمند و تمرین مداومه. از همین امروز، کتاب دلخواهتون رو بردارین و با این فرمول بخونین و نتایج ر. توی کامنت‌ها به اشتراک بزارین؛ دوست دارم بدونم از کدوم تکنیک‌ها استفاده کردین و نتیجه گرفتین.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Fri, 09 May 2025 22:10:08 +0330</pubDate>
            </item>
                    <item>
                <title>بازسازی زیرساخت‌ها در ۶ ماه: افزایش ۱۰۰ درصدی فروش با بهبودهای فنی</title>
                <link>https://virgool.io/@pakzad/ecommerce-consulting-l4qfxtenhots</link>
                <description>Photo by Campaign Creators on Unsplashاوایل امسال به‌عنوان مشاور در پروژه‌ای دعوت شدم که در نگاه اول، حجم زیادی از مشکلات و البته پتانسیل رشد داشت. من یه آدم فنی هستم و ترکیب تجربیات عملی من در کارآفرینی و مارکتینگ با دانش آکادمیک MBA دانشگاه تهران، به من کمک کرد تا به سراغ بهبودهای جدی و تأثیرگذار برم.شفافیت و ایجاد ساختاردر همان ابتدای پروژه، برای ایجاد شفافیت و دسترسی راحت‌تر مدیران به گزارشات، گزارش‌ها و نمودارهای متنوعی ایجاد کردیم که تمامی روندها و اقدامات به‌طور دقیق برای مدیریت قابل‌مشاهده باشن. علاوه بر این، گزارشات منظم هفتگی نیز به مدیرعامل ارسال می‌شد تا از روند پیشرفت و دستاوردها مطلع باشه. این شفافیت باعث شد تا هم مسیر پیشرفت برای تیم فنی روشن بشه و هم مدیران دید واضح‌تری از روند بهبود‌ها داشته باشن.Photo by Scott Graham on Unsplashتوسعه زیرساخت فنیدر همون مراحل اولیه، مشکلات متعددی در زیرساخت فنی پروژه شناسایی شدن. این مشکلات شامل ارورهای ۵۰۰ به دلیل Too many connections و عدم کارایی در هاست اشتراکی بود. با انتقال پروژه به سرور مجازی و تغییرات در کانفیگ سرور، نه تنها مشکلات اولیه حل شد، بلکه سرعت و پایداری سایت هم بهبود پیدا کرد. همچنین، در قدم‌های اول، با فعال‌سازی Gzip بهبود چشمگیری در سرعت لود صفحات ایجاد شد و این موضوع تأثیر خیلی خوبی روی تجربه کاربری گذاشت. در همین مرحله، مشکلات دیتابیس هم بررسی و بهینه‌سازی شد تا کارایی سیستم بیشتر بشه.الان به جایی رسیدیم که زیرساخت‌ها تثبیت شده و به یه وضعیت نرمال رسیدیم. تو این نقطه عطف، تمرکزمون باید روی قوی‌تر کردن زیرساخت‌ها و ریفکتور تدریجی کدها باشه. همچنین، مسائلی که قبلاً تو کوتاه‌مدت اولویت نداشتن ولی تو میان‌مدت و بلندمدت برای پایداری و رشد پروژه خیلی مهم هستن، حالا در دستور کار قرار می‌گیرن تا بهبود پیدا کنن.دستاوردهای فنی قابل توجهبا انجام بهینه‌سازی‌های مختلف روی کوئری‌ها، حل مشکل N+1، ایندکس گذاری صحیح و ...، عملکرد دیتابیس بهبود قابل توجهی پیدا کرد.نوشتن کش برای بخش‌های مختلف سایت تاثیر بسیار زیادی روی پرفورمنس پروژه داشت.استفاده از ردیس برای ذخیره سازی دیتای موقت (کش و سشن) باعث شد سرعت بارگذاری سایت رو در حد چشمگیری افزایش داد.استفاده از تلسکوپ برای رصد دقیق‌تر مشکلات، به شناسایی و رفع سریع ارورها کمک کرد و ارورهای ۵۰۰ تقریباً به صفر رسید.تبدیل پردازش‌های سنگین به صف‌ها و استفاده از Horizon برای مدیریت صف‌ها باعث شد که ارورهای ۵۰۰ کم بشه و نرخ موفقیت پردازش‌ها افزایش پیدا کنه.بهینه‌سازی تجربه کاربری و فرآیند سبد خریدبهبود فرآیند خرید یکی از دستاوردهای مهم پروژه بود. حجم سبد خرید از ۱.۰۷ به ۱.۸۳ رسید، که این نشون‌دهنده بهبود تجربه کاربری و افزایش فروش بوده. همچنین، برای سبدهای ناقص و مشتریانی که کد OTP به هر دلیلی به دستشون نمی‌رسید، بخشی اضافه شد که تیم فروش با تماس مستقیم بتونه این سبدها رو به خرید نهایی تبدیل کنه. امکان ثبت سفارش به صورت مهمان هم اضافه شد که منجر به افزایش ۱۵٪ فروش شد.افزایش دسترسی‌ها و امکان تغییر سریع قیمتدر این پروژه، امکان تغییر سریع موجودی و قیمت‌ها با دابل کلیک و آپدیت محصول از طریق اکسل اضافه شد. این فیچر سرعت و دقت تیم رو تو تغییرات قیمت بالا برد. همچنین دسترسی‌های مبتنی بر نقش کاربری پیاده‌سازی شد تا امنیت و دسترسی‌ها بهتر مدیریت بشه. این فیچرهای جدید باعث افزایش کارایی تیم و صرفه‌جویی در زمان شد.بهبود سئو و افزودن امکانات بهینه‌سازیبرای تیم سئو قابلیت‌هایی اضافه شد تا بدون نیاز به دخالت فنی، سئو رو از پنل مدیریت تنظیم کنن. مثل قابلیت تنظیم نوفالو، نوایندکس، اپن‌گراف و کارت‌های توئیتر. اضافه شدن امکان بروزرسانی robots.txt و تنظیم کنونیکال‌ها هم بهبود چشم‌گیری در سئوی سایت داشت.بهبود لجستیک و کاهش هزینه‌های ارسالدر بررسی‌های دقیق و جلساتی که با تیم فروش و مدیریت داشتیم، به این نتیجه رسیدیم که با استخدام نیروی لجستیک، هزینه‌های ارسال رو کاهش بدیم. این اقدام، علاوه بر کاهش هزینه‌ها، به افزایش نرخ تکمیل سفارشات کمک کرد و بخشی از سفارشات که به دلیل هزینه‌های بالا رها می‌شدند، به سرانجام رسیدند.برنامه فروش اقساطیبا توجه به نیاز مشتریان، فروش اقساطی برای کاربران تهران فعال شد که مورد استقبال خوبی قرار گرفت و به زودی به سایر مناطق هم گسترش پیدا می‌کنه. برای آینده هم برنامه داریم که گزینه‌های فروش اقساطی رو بیشتر کنیم و شرایط پرداخت رو منعطف‌تر کنیم.Photo by a Stephen Dawson on Unsplash
دستاوردها و نتایج ملموساین اقدامات نتایج قابل چشمگیری داشت:بهبود ۱۰۰ درصدی فروش و افزایش ۳ برابری تراکنش‌ها، نشون‌دهنده تاثیر مستقیم این بهبودها است.به صفر رسیدن ارورهای ۵۰۰ که در زمان شروع پروژه، روزانه لاگ‌های چند مگابایتی ایجاد می‌شد و حالا تقریبا به صفر رسیده.کسایی که تجربه عملی در این نوع پروژه‌ها دارن، می‌دونن که رسیدن به این نتایج تو شش ماه چقدر چشم‌گیره. هنوز هم مشکلاتی باقی مونده که در حال رفع‌شون هستیم و این تغییرات همراه با کمپین‌های مارکتینگ، تأثیر بیشتری بر افزایش فروش خواهد داشت.درس‌هایی که آموختماین پروژه و دوره MBA دانشگاه تهران دید من رو نسبت به مدیریت و توسعه پروژه‌ها بازتر کرد. یاد گرفتم که با ترکیب نگاه فنی و تجربه تجاری، استراتژی‌های بهینه‌سازی رو با اهداف بلندمدت تجاری همسو کنم و تو این مسیر، نه‌تنها کارایی فنی پروژه، بلکه اهداف تجاری رو هم بهبود بدم.شما هم در پروژه‌هاتون با چنین چالش‌های فنی روبرو بودین؟ خوشحال می‌شم تجربیات شما را هم بشنوم.اگر به تجربیات قبلی من در پروژه‌های مشابه علاقه‌مند هستید، می‌توانید مقاله ده ماه توسعه پروژه را مطالعه کنید.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Sat, 09 Nov 2024 02:07:42 +0330</pubDate>
            </item>
                    <item>
                <title>دسترسی مبتنی بر نقش کاربری یا RBAC</title>
                <link>https://virgool.io/@pakzad/rbac-dzwvomgtgaxr</link>
                <description>کاور پکیج spatie/laravel-permissionدسترسی مبتنی بر نقش کاربری یا Role Based Access Control که به اختصار RBAC هم نامیده می‌شود مفهومی است که می‌گوید کاربران می‌توانند نقش‌های کاربری مختلفی داشته باشند که هر نقش کاربری، دسترسی‌های مختلفی دارد.برای مثال یک کاربر دارای نقش‌های کاربری «نویسنده مقاله» و «مدیر محصولات» باشد. این کاربر دارای دو نقش کاربری است و در هر نقش، دسترسی‌ها (یا پرمیشن‌هایی) از قبیل افزودن، ویرایش، حذف و ... وجود دارند. در نتیجه این کاربر به صورت غیرمستقیم به تمامی پرمیشن‌های این دو نقش کاربری دسترسی دارد.تفاوت بین احراز هویت (Authentication) و مجوزها (Authorization)‌ چیست؟احراز هویت به این معنی است که کاربر هویت خود را از طریق یوزر (موبایل، ایمیل، نام کاربری یا ...) و پسورد و یا از طریق توکن (token) یا ... هویت خود را اثبات کنید. کاربران قبل از احراز هویت، مهمان نام دارند و پس از احراز هویت، کاربر احراز هویت شده هستند که ممکن است مشتری، کاربر عادی، ادمین و ... باشند.وقتی سیستم مجوزها به هر روشی در یک اپلیکیشن (وب اپلیکیشن، موبایل اپلیکیشن و ...) پیاده‌سازی شود،‌ کاربران آن پس از احراز هویت برای دسترسی به برخی بخش‌های اپلیکیشن یا انجام برخی از قابلیت‌ها نیاز به مجوز دارند. یکی از بهترین روش‌ها برای اعطای مجوز؛ پیاده سازی RBAC است.مزیتاین ارتباطات باعث جلوگیری از افزونگی پیاده سازی می‌شوند و اطمینان بیشتری را برای توسعه محصول در آینده به می‌دهد. به این صورت که برای افزودن پرمیشن جدید، تنها کافیست که پرمیشن را اضافه کرده و در بخش فرانت و بک اند استفاده کرد و مدیر (دارای مجوز اعطای پرمیشن)، این پرمیشن را به نقش‌های کاربری مورد نظر خود بدهد.از کدنویسی‌های سنتی و پیچیده جلوگیری می‌شود و سیستم انعطاف پذیری بالایی دارد. مخصوصا وقتی تعداد کاربران سیستم بالا می‌رود، RBAC و کارآمد بودن آن خود را بیشتر نیز نشان می‌دهد.نگاه دیتابیسیمعمولا ساختار دیتابیسی RBAC بسط داده می‌شود، ولی در پایه‌ترین حالت ما یک تیبل برای نگهداری مشخصات کاربران، یک تیبل برای نگهداری نقش‌های کاربری، یک تیبل برای نگهداری پرمیشن‌ها، همچنین یک تیبل واسطه (pivot)‌ برای نگهداری رابطه بین نقش‌های کاربری و دسترسی‌ها و یک تیبل واسطه برای نگهداری ارتباط بین نقش‌های کاربری و کاربران وجود دارد.ممکن است کاربران ما در تیبل‌های مختلف نگهداری شوند و برای هر کدام بخواهیم نقش‌های کاربری مخصوص خود را داشته باشیم؛ در این حالت یکی از بهترین پیاده‌سازی‌ها را در پکیج laravel-permission توسعه داده شده توسط Spatie می‌بینیم که با استفاده از guard_name و قابلیت ارتباط پلیمورفیک این قابلیت را به ما می‌دهد که بتوانیم چندین تیبل برای نگهداری کاربران برای مثال، مشتریان، مدیران، پیک‌ها و ... داشته باشیم.پیاده سازیبستگی به زبان و فریمورک‌های مختلف، کدنویسی و ایجاد ارتباط متفاوت است. ما پکیج لاراول پرمیشن را در ادامه بررسی می‌کنیم. برای پیاده سازی آن کافی است یکی از پروژه‌های لاراولی خود را در IDE باز کرده و یا یک پروژه لاراول خام ایجاد کنید.این پکیج به کاربران امکان مدیریت نقش‌های کاربری و پرمیشن‌ها در دیتابیس را می‌دهد.نصب پکیجcomposer show spatie/laravel-permissionبا استفاده از دستور بالا، پکیج را نصب کنید.افزودن تریت به مدلاین پکیج از لایه گیت لاراول برای ارائه قابلیت‌های احرازهویت استفاده کنید. مدل User یا هر مدلی که مربوط به تیبل کاربران شما است، تریت HasRoles را اضافه کنید.توجه: دقت کنید که این مدل نباید دارای پراپرتی‌های role و roles و permission و permissions یا متدهای permissions و roles باشند، زیرا پراپرتی‌ها و یا متدهای تریت توسط مدل بازنویسی نشود. فایل کانفیگاین پکیج یک فایل کانفیگ با نام config/permission.php منتشر میکند که می‌توانید تنظیمات پکیج را توسط آن انجام دهید.ساخت رول و پرمیشنبرای ساخت رول و پرمیشن می‌توان از نمونه کدهای زیر استفاده کرد. دقت کنید که اگر نیاز به افزودن ستونی مثل غیرقابل حذف بودن نقش سوپر ادمین دارید؛ مایگریشن مربوطه را ویرایش کنید. نگران نباشید نیازی به تغییر مدل Role و Permission نیست زیر این مدل‌ها از guard استفاده می‌کنند نه از fillable.use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role = Role::create([&#039;name&#039; =&gt; &#039;writer&#039;]);
$permission = Permission::create([&#039;name&#039; =&gt; &#039;edit articles&#039;]);اساین کردن پرمیشن به یک نقش کاربریبا استفاده از متدهای زیر می‌توان یک پرمیشن را به یک نقش کاربری اضافه کرد:$role-&gt;givePermissionTo($permission);
$permission-&gt;assignRole($role);سینک کردن پرمیشن‌ها برای یک نقش کاربریبرای سینک کردن چندین پرمیشن با یک نقش کاربری و برعکس، از متدهای زیر می‌توان استفاده کرد:$role-&gt;syncPermissions($permissions);
$permission-&gt;syncRoles($roles);حذف پرمیشن از یک نقش کاربریبرای حذف یک پرمیشن از یک نقش کاربری و برعکس، از متدهای زیر می‌توان استفاده کرد:$role-&gt;revokePermissionTo($permission);
$permission-&gt;removeRole($role);گرفتن پرمیشن‌های یک کاربرتریت HasRoles که به مدل الکوئنتی اضافه کردیم، دسترسی مستقیم به پرمیشن‌ها را نیز فراهم می‌کند. یکی از کاربردهای گرفتن همه پرمیشن‌ها می‌تواند ساختن منوی متناسب برای هر کاربر یا نمایش برای حذف و ایجاد پرمیشن مستقیم و بدون واسطه نقش کاربری و ... است.لیست تمام پرمیشن‌هایی که به صورت مستقیم به کاربر اساین (تخصیص داده) شده است:// get a list of all permissions directly assigned to the user
$permissionNames = $user-&gt;getPermissionNames(); // collection of name strings
$permissions = $user-&gt;permissions; // collection of permission objectsلیست تمام پرمیشن‌هایی که به صورت مستقیم، غیرمستقیم و یا هر دو به کاربر اساین شده است:// get all permissions for the user, either directly, or from roles, or from both
$permissions = $user-&gt;getDirectPermissions();
$permissions = $user-&gt;getPermissionsViaRoles();
$permissions = $user-&gt;getAllPermissions();نام نقش‌های کاربری اساین شده به کاربر// get the names of the user&#039;s roles
$roles = $user-&gt;getRoleNames(); // Returns a collectionاسکوپ‌هاتریتی که به مدل اضافه کردیم دو اسکوپ withoutRole و withoutRole نیز به مدل اضافه می‌کند.به ترتیب کاربرانی که دارای نقش writer هستند و کاربرانی که دارای نقش کاربری editor نیستند:$users = User::role(&#039;writer&#039;)-&gt;get(); // Returns only users with the role &#039;writer&#039;
$nonEditors = User::withoutRole(&#039;editor&#039;)-&gt;get(); // Returns only users without the role &#039;editor&#039;به ترتیب کاربرانی که پرمیشن edit articles دارند و کاربرانی این پرمیشن را ندارند:$users = User::permission(&#039;edit articles&#039;)-&gt;get(); // Returns only users with the permission &#039;edit articles&#039; (inherited or directly)
$usersWhoCannotEditArticles = User::withoutPermission(&#039;edit articles&#039;)-&gt;get(); // Returns all users without the permission &#039;edit articles&#039; (inherited or directly)فراخوانی با قدرت الوکوئنتاز آنجایی که رول‌ها (نقش‌های کاربری) و پرمیشن‌ها مدل‌هایی هستند که از مدل‌های الوکوئنت اکستند شده‌اند، کانونشن‌ها و کاندیشن‌های الوکوئنت در آنها نیز صدق می‌کنند:$all_users_with_all_their_roles = User::with(&#039;roles&#039;)-&gt;get();
$all_users_with_all_their_direct_permissions = User::with(&#039;permissions&#039;)-&gt;get();
$all_roles_in_database = Role::all()-&gt;pluck(&#039;name&#039;);
$users_without_any_roles = User::doesntHave(&#039;roles&#039;)-&gt;get();
$all_roles_except_a_and_b = Role::whereNotIn(&#039;name&#039;, [&#039;role A&#039;, &#039;role B&#039;])-&gt;get();تعداد کاربران با نقش کاربری خاصیک راه که برای شمردن تعداد کاربران با یک نقش کاربری خاص وجود دارد، استفاده از متد filter بر روی کاربران است:$superAdminCount = User::with(&#039;roles&#039;)-&gt;get()-&gt;filter(
    fn ($user) =&gt; $user-&gt;roles-&gt;where(&#039;name&#039;, &#039;Super Admin&#039;)-&gt;toArray()
)-&gt;count();اساین کردن مستقیم پرمیشن به کاربرانافزودن پرمیشن مشخص به کاربر$user-&gt;givePermissionTo(&#039;edit articles&#039;);

// You can also give multiple permission at once
$user-&gt;givePermissionTo(&#039;edit articles&#039;, &#039;delete articles&#039;);

// You may also pass an array
$user-&gt;givePermissionTo([&#039;edit articles&#039;, &#039;delete articles&#039;]);حذف پرمیشن از کاربر$user-&gt;revokePermissionTo(&#039;edit articles&#039;);سینک (افزودن/حذف) پرمیشن‌ها برای کاربر$user-&gt;hasPermissionTo(&#039;edit articles&#039;);بررسی اینکه کاربر پرمیشن خاصی را دارد به وسیله id$user-&gt;hasPermissionTo(&#039;1&#039;);
$user-&gt;hasPermissionTo(Permission::find(1)-&gt;id);
$user-&gt;hasPermissionTo($somePermission-&gt;id);بررسی اینکه کاربر پرمیشن خاصی را دارد به وسیله نام پرمیشن$user-&gt;hasAnyPermission([&#039;edit articles&#039;, &#039;publish articles&#039;, &#039;unpublish articles&#039;]);بررسی اینکه کاربر تمامی پرمیشن‌های مشخص شده را دارد$user-&gt;hasAllPermissions([&#039;edit articles&#039;, &#039;publish articles&#039;, &#039;unpublish articles&#039;]);برای بررسی امکان پاس دادن id پرمیشن نیز وجود دارد$user-&gt;hasAnyPermission([&#039;edit articles&#039;, 1, 5]);با استفاده از متد پیش فرض لاراولی can می‌توانید چک کنید که آیا یک کاربر پرمیشن خاصی را دارد:$user-&gt;can(&#039;edit articles&#039;);استفاده از پرمیشن‌ها به وسیله نقش‌های کاربریاساین کردن نقش کاربری به کاربر$user-&gt;assignRole(&#039;writer&#039;);

// You can also assign multiple roles at once
$user-&gt;assignRole(&#039;writer&#039;, &#039;admin&#039;);
// or as an array
$user-&gt;assignRole([&#039;writer&#039;, &#039;admin&#039;]);حذف نقش کاربری از کاربر$user-&gt;removeRole(&#039;writer&#039;);سینک نقش کاربری برای کاربر// All current roles will be removed from the user and replaced by the array given
$user-&gt;syncRoles([&#039;writer&#039;, &#039;admin&#039;]);بررسی نقش‌های کاربریآیا یک کاربر دارای نقش کاربری خاصی است:$user-&gt;hasRole(&#039;writer&#039;);

// or at least one role from an array of roles:
$user-&gt;hasRole([&#039;editor&#039;, &#039;moderator&#039;]);آیا کاربر یکی از نقش‌های کاربری مشخص شده را دارد:$user-&gt;hasAnyRole([&#039;writer&#039;, &#039;reader&#039;]);
// or
$user-&gt;hasAnyRole(&#039;writer&#039;, &#039;reader&#039;);آیا یک کاربر دارای تمامی نقش‌های مشخص شده است:$user-&gt;hasAllRoles(Role::all());آیا یک کاربر دقیقا و فقط و فقط نقش‌های مشخص شده را دارا است:$user-&gt;hasExactRoles(Role::all());اساین کردن پرمیشن به نقش‌های کاربریاساین کردن پرمیشن به نقش کاربری:$role-&gt;givePermissionTo(&#039;edit articles&#039;);آیا نقش کاربری دارای پرمیشن مشخص است:$role-&gt;hasPermissionTo(&#039;edit articles&#039;);حذف پرمیشن از نقش کاربری:$role-&gt;revokePermissionTo(&#039;edit articles&#039;);سینک کردن پرمیشن‌ها با نقش‌های کاربری$role-&gt;syncPermissions([&#039;edit articles&#039;, &#039;delete articles&#039;]);یک نقش کاربری چه پرمیشن‌هایی دارد؟// get collection
$role-&gt;permissions;

// return only the permission names:
$role-&gt;permissions-&gt;pluck(&#039;name&#039;);

// count the number of permissions assigned to a role
count($role-&gt;permissions);
// or
$role-&gt;permissions-&gt;count();اساین کردن پرمیشن به صورت مستقیم به کاربر$role = Role::findByName(&#039;writer&#039;);
$role-&gt;givePermissionTo(&#039;edit articles&#039;);

$user-&gt;assignRole(&#039;writer&#039;);

$user-&gt;givePermissionTo(&#039;delete articles&#039;);آیا یک کاربر پرمیشن‌های مشخص شده را دارد:// Check if the user has Direct permission
$user-&gt;hasDirectPermission(&#039;edit articles&#039;)

// Check if the user has All direct permissions
$user-&gt;hasAllDirectPermissions([&#039;edit articles&#039;, &#039;delete articles&#039;]);

// Check if the user has Any permission directly
$user-&gt;hasAnyDirectPermission([&#039;create articles&#039;, &#039;delete articles&#039;]);دایرکتیوهای بلیدساده‌ترین راه استفاده از دایرکتیو can در است، راه جایگزین دیگر استفاده از متد can برای کاربر است:@can(&#x27;edit articles&#x27;)  //@endcanیا@if(auth()-&gt;user()-&gt;can(&#x27;edit articles&#x27;) &amp;&amp; $some_other_condition)  //@endifهمچنین استفاده از دایرکتیوهای cannot و canany و guest نیز امکان‌پذیر است.پارامتر دوم دایرکتیو can مشخص می‌کند که پرمیشن فقط برای گارد مشخصی بررسی شود. (گارد را در ابتدای مقاله توضیح دادم.)دایرکتیو اختصاصی پکیج نیز haspermission است که دایرکتیو متناظر آن endhaspermission است.توجه: توصیه اکید می‌کنم که صرفا دسترسی کاربران به بخش‌های مختلف اپلیکیشن را با پرمیشن‌ها بدهید و رول‌ها را مبنای اعطای حق دسترسی به بخش‌های مختلف قرار ندهید.اگر مجبور به استفاده شدید می‌توانید از دایرکتیوها و متدهای زیر استفاده کنید.آیا کاربر دارای نقش کاربری مشخصی است:@role(&#039;writer&#039;)
    I am a writer!
@else
    I am not a writer...
@endroleبه صورت مشابه:@hasrole(&#039;writer&#039;)
    I am a writer!
@else
    I am not a writer...
@endhasroleبا دایرکتیو پیش فرض لاراول@if(auth()-&gt;user()-&gt;hasRole(&#039;writer&#039;))
  //
@endifبررسی اینکه یک کاربر یک یا همه نقش‌های کاربری مشخص شده را دارد:@hasanyrole($collectionOfRoles)
    I have one or more of these roles!
@else
    I have none of these roles...
@endhasanyrole
// or
@hasanyrole(&#039;writer|admin&#039;)
    I am either a writer or an admin or both!
@else
    I have none of these roles...
@endhasanyroleآیا کاربر تمامی نقش‌های کاربری مشخص شده را دارد:@hasallroles($collectionOfRoles)
    I have all of these roles!
@else
    I do not have all of these roles...
@endhasallroles
// or
@hasallroles(&#039;writer|admin&#039;)
    I am both a writer and an admin!
@else
    I do not have all of these roles...
@endhasallrolesآیا کاربر نقش کاربری مشخص شده را ندارد:@unlessrole(&#039;does not have this role&#039;)
    I do not have the role
@else
    I do have the role
@endunlessroleآیا یک کاربر دقیقا و فقط و فقط تمامی نقش‌های کاربری مشخص شده را دارد:@hasexactroles(&#039;writer|admin&#039;)
    I am both a writer and an admin and nothing else!
@else
    I do not have all of these roles or have more other roles...
@endhasexactrolesکامندهای آرتیزانایجاد نقش کاربری و پرمیشن با استفاده از کامندهای آرتیزان:php artisan permission:create-role writer
php artisan permission:create-permission writerاگر نام نقش کاربری بیش از یک کلمه باشد در کوتیشن قرار می‌گیرد. همچنین اگر بخواهیم این نقش کاربری در گارد مشخصی ایجاد شود، نام گارد را به عنوان پارامتر دوم به این کامندها پاس می‌دهیم:php artisan permission:create-permission &amp;quotedit articles&amp;quot
php artisan permission:create-role writer web
php artisan permission:create-permission &amp;quotedit articles&amp;quot webبرای ساخت همزمان چندین نقش کاربری:php artisan permission:create-role writer web &amp;quotcreate articles|edit articles&amp;quotنمایش پرمیشن‌ها در ترمینالphp artisan permission:showریست کردن کشاگر می‌خواهید کش پرمیشن‌ها را به صورت دستی پاک کنید از کامندهای زیر استفاده کنید:php artisan permission:cache-resetمیدلورمیدلور پیش فرضRoute::group([&#039;middleware&#039; =&gt; [&#039;can:publish articles&#039;]], function () { ... });

// or with static method (requires Laravel 10.9+)
Route::group([&#039;middleware&#039; =&gt; [\Illuminate\Auth\Middleware\Authorize::using(&#039;publish articles&#039;)]], function () { ... });میدلورهای پکیجدر لاراول ۱۱ فایل bootstrap/app.php را باز کرده و میدلورهای پکیج را رجیستر کنید:-&gt;withMiddleware(function (Middleware $middleware) {
        $middleware-&gt;alias([
            &#039;role&#039; =&gt; \Spatie\Permission\Middleware\RoleMiddleware::class,
            &#039;permission&#039; =&gt; \Spatie\Permission\Middleware\PermissionMiddleware::class,
            &#039;role_or_permission&#039; =&gt; \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
        ]);
    })در لاراول ۹ و ۱۰ می‌توانید میدلورها را در فایل app/Http/Kernel.php اضافه کنید:// Laravel 9 uses $routeMiddleware = [
//protected $routeMiddleware = [
// Laravel 10+ uses $middlewareAliases = [
protected $middlewareAliases = [
    // ...
    &#039;role&#039; =&gt; \Spatie\Permission\Middleware\RoleMiddleware::class,
    &#039;permission&#039; =&gt; \Spatie\Permission\Middleware\PermissionMiddleware::class,
    &#039;role_or_permission&#039; =&gt; \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
];استفاده از میدلورها در روت‌هاRoute::group([&#039;middleware&#039; =&gt; [&#039;role:manager&#039;]], function () { ... });
Route::group([&#039;middleware&#039; =&gt; [&#039;permission:publish articles&#039;]], function () { ... });
Route::group([&#039;middleware&#039; =&gt; [&#039;role_or_permission:publish articles&#039;]], function () { ... });

// for a specific guard:
Route::group([&#039;middleware&#039; =&gt; [&#039;role:manager,api&#039;]], function () { ... });

// multiple middleware
Route::group([&#039;middleware&#039; =&gt; [&#039;role:manager&#039;,&#039;permission:publish articles&#039;]], function () { ... });برای چندین رول یا پرمیشن از علامت پایپ | با مفهوم OR استفاده کنید.Route::group([&#039;middleware&#039; =&gt; [&#039;role:manager|writer&#039;]], function () { ... });
Route::group([&#039;middleware&#039; =&gt; [&#039;permission:publish articles|edit articles&#039;]], function () { ... });
Route::group([&#039;middleware&#039; =&gt; [&#039;role_or_permission:manager|edit articles&#039;]], function () { ... });

// for a specific guard
Route::group([&#039;middleware&#039; =&gt; [&#039;permission:publish articles|edit articles,api&#039;]], function () { ... });کنترلرهادر لاراول ۱۱، اگر کنترلرتان اینترفیس را ایمپلمنت می‌کند، می‌توانید میدلورهای کنترلر را با استفاده از متد رجیستر کنید:public static function middleware(): array
{
    return [
        // examples with aliases, pipe-separated names, guards, etc:
        &#039;role_or_permission:manager|edit articles&#039;,
        new Middleware(&#039;role:author&#039;, only: [&#039;index&#039;]),
        new Middleware(\Spatie\Permission\Middleware\RoleMiddleware::using(&#039;manager&#039;), except:[&#039;show&#039;]),
        new Middleware(\Spatie\Permission\Middleware\PermissionMiddleware::using(&#039;delete records,api&#039;), only:[&#039;destroy&#039;]),
    ];
}در لاراول ۱۰ و قبلتر، میدلورها را می‌توانید در کانستراکتور رجیستر کنید:public function __construct()
{
    // examples:
    $this-&gt;middleware([&#039;role:manager&#039;,&#039;permission:publish articles|edit articles&#039;]);
    $this-&gt;middleware([&#039;role_or_permission:manager|edit articles&#039;]);
    // or with specific guard
    $this-&gt;middleware([&#039;role_or_permission:manager|edit articles,api&#039;]);
}نقش‌های کاربری در مقابل پرمیشن‌هارول‌ها یا نقش‌های کاربری برای گروه‌بندی کاربران دارای مجموعه‌ای از پرمیشن‌ها تعریف می‌شوند. بنابراین همانطور که قبلتر گفتم بهتر است که پرمیشن‌ها به رول‌ها و رول‌ها به کاربران اساین شوند.سید کردن دیتابیسدر ابتدای راه اندازی پروژه، معمولا پرمیشن‌ها، رول‌ها، کاربران، تنظیمات و ... را به صورت سید در پروژه تعریف می‌کنند. برای جلوگیری از ارورهای کانفلیتی بخاطر کش، بهتر است قبل از اجرای سیدها که منجر به ایجاد رول‌ها و پرمیشن‌های جدید می‌شود، کش آنها را پاک کنیم:// reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]-&gt;forgetCachedPermissions();در زیر یک نمونه ساده از فایل سیدر دیتابیس برای ایجاد پرمیشن‌ها و رول‌های پیش فرض سیستم را می‌بینید:use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class RolesAndPermissionsSeeder extends Seeder
{
    public function run(): void
    {
        // Reset cached roles and permissions
        app()[\Spatie\Permission\PermissionRegistrar::class]-&gt;forgetCachedPermissions();

        // create permissions
        Permission::create([&#039;name&#039; =&gt; &#039;edit articles&#039;]);
        Permission::create([&#039;name&#039; =&gt; &#039;delete articles&#039;]);
        Permission::create([&#039;name&#039; =&gt; &#039;publish articles&#039;]);
        Permission::create([&#039;name&#039; =&gt; &#039;unpublish articles&#039;]);

        // create roles and assign created permissions

        // this can be done as separate statements
        $role = Role::create([&#039;name&#039; =&gt; &#039;writer&#039;]);
        $role-&gt;givePermissionTo(&#039;edit articles&#039;);

        // or may be done by chaining
        $role = Role::create([&#039;name&#039; =&gt; &#039;moderator&#039;])
            -&gt;givePermissionTo([&#039;publish articles&#039;, &#039;unpublish articles&#039;]);

        $role = Role::create([&#039;name&#039; =&gt; &#039;super-admin&#039;]);
        $role-&gt;givePermissionTo(Permission::all());
    }
}کشنکته: هرگاه تغییری در پرمیشن‌‌ها و یا رول‌ها ایجاد شود که این تغییر می‌تواند شامل ایجاد، حذف و اضافه آنها شود؛ کش به صورت اتوماتیک پاک می‌شود. دقت کنید که این تغییرات باید حتما از طریق کامندها و یا متدهای خود پکیج انجام گیرد.برای مقال متدهای زیر موجب ریست شدن کش می‌شوند:// When handling permissions assigned to roles:
$role-&gt;givePermissionTo(&#039;edit articles&#039;);
$role-&gt;revokePermissionTo(&#039;edit articles&#039;);
$role-&gt;syncPermissions(params);

// When linking roles to permissions:
$permission-&gt;assignRole(&#039;writer&#039;);
$permission-&gt;removeRole(&#039;writer&#039;);
$permission-&gt;syncRoles(params);این پکیج دارای امکانات بسیار زیادی است که پرکاربردترین امکانات آن را در این مقاله به صورت خلاصه نوشتم. برای مطالعه امکانات کامل آن توصیه می‌کنم که داکیومنت آن را مطالعه نمایید.بعضی از پست‌هام که ممکنه دوست داشته باشید:پورتو (الگوی معماری نرم افزار)مسیر ۱۰ ماهه توسعه پروژهشروع یک کسب‌وکار به دلیل موفقیت دیگران</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Sat, 13 Apr 2024 02:23:15 +0330</pubDate>
            </item>
                    <item>
                <title>پورتو (الگوی معماری نرم افزار)</title>
                <link>https://virgool.io/@pakzad/porto-oaemrj7r3h1z</link>
                <description>پورتو (الگوی معماری نرم افزار)مقدمهپورتو یک الگوی معماری نرم افزار مدرن است که مجموعه‌ای از دستورالعمل‌ها، اصول، و الگوها را به توسعه دهندگان ارائه می‌دهد تا کد خود را به روشی با قابلیت نگهداری و استفاده مجدد بسیار بالا سازماندهی کنند. هدف اصلی پورتو کمک به توسعه دهندگان برای ایجاد نرم افزاری است که مقیاس پذیر و انعطاف پذیر بوده و نگهداری آن در طول زمان آسان باشد.«سادگی نهایت پیچیدگی است.» - لئوناردو داوینچیپورتو به ویژه برای پروژه‌های وب با اندازه متوسط تا بزرگ که به انعطاف‌پذیری و مقیاس‌پذیری بالایی نیاز دارند، مناسب است. با پورتو، توسعه‌دهندگان می‌توانند پروژه‌های مونولیتیک بسیار مقیاس‌پذیری بسازند که به راحتی می‌توانند هر زمان که نیاز باشد به چندین میکروسرویس تقسیم شوند. این رویکرد استفاده مجدد از بیزنس لاجیک یا فیچرهای کاربردی در چندین پروژه را ممکن می‌سازد و آن را به انتخابی ایده‌آل برای تیم‌هایی تبدیل می‌کند که روی پروژه‌های مختلف کار می‌کنند.این معماری بر اساس چندین مفهوم معماری تثبیت شده، از جمله معماری‌های Domain Driven Design (DDD)، ماژولار، Model View Controller (MVC)، میکروکرنل، چندلایه، و Action Domain Responder (ADR) ساخته شده است. پورتو با استفاده از این مفاهیم تثبیت شده، چارچوبی قابل اعتماد و تست شده برای ساختن نرم افزار در اختیار توسعه دهندگان قرار می دهد.علاوه بر این مفاهیم اساسی، پورتو همچنین به مجموعه‌ای از اصول طراحی ثابت مانند Generalization، سالید، LIFT، برنامه‌نویسی شی‌گرا، DRY یا عدم تکرار، Low Coupling یا حداقل وابستگی، GRASP یا الگوهای نرم افزاری تفویض کلی مسئولیت، CoC و High Cohesion پایبند است. این اصول به گونه‌ای طراحی شده‌اند که اطمینان حاصل شود که نرم افزار ساخته شده با استفاده از پورتو قابل نگهداری، مقیاس‌پذیر و قابل درک است.به طور کلی، پورتو یک الگوی معماری نرم افزار قدرتمند و انعطاف‌پذیر است که مجموعه‌ای جامع از ابزارها را برای ساختن نرم افزارهای مقیاس‌پذیر، قابل نگهداری و قابل استفاده مجدد به توسعه‌دهندگان ارائه می‌دهد. چه در حال کار بر روی یک پروژه کوچک یا یک برنامه سازمانی در مقیاس بزرگ باشید، پورتو می‌تواند به شما کمک کند تا نرم افزاری بسازید که نیازهای امروز و آینده شما را برآورده کند.نکته: پورتو به عنوان یک معماری آزمایشی شروع به کار کرد که با این هدف طراحی شده بود که مشکلات رایجی که توسعه دهندگان وب هنگام ساخت پروژه‌های بزرگ با آن مواجه می‌شوند، را حل کند. پورتو از همان ابتدای پیدایش به یک الگوی معماری نرم افزاری محبوب در میان توسعه دهندگان تبدیل شده است که مجموعه‌ای قدرتمند از ابزارها را برای ساختن نرم افزارهای مقیاس‌پذیر، قابل نگهداری و قابل استفاده مجدد ارائه می‌دهد. از بازخوردها و مشارکت‌ها قدردانی ویژه دارد.شروع مقالهبررسی لایه‌هاپورتو از دو لایه تشکیل شده است: &quot;کانتینرها یا  containers&quot; و &quot;کشتی یا ship&quot;.لایه کانتینرز حاوی کد کل بیزنس لاجیک اپلیکیشن شما است.لایه شیپ کد زیرساخت (کد مشترک بین همه کانتینرها) را نگهداری می‌کند.این لایه‌ها را می‌توانید در هر جایی از فریمورک منتخب خودتان ایجاد کرد. به عنوان مثال، در لاراول یا Rails، آن‌ها را می‌توان در دایرکتوری app/ یا در یک دایرکتوری جدید با نام src/ در روت ایجاد کرد.پورتو با جدا کردن کد اپلیکیشن شما به این دو لایه، به شما این امکان را می‌دهد که بیزنس لاجیک را از کد زیرساخت جدا نگه دارید که نگهداری و به روزرسانی اپلیکیشن را در گذر رمان آسان‌تر می‌کند. لایه کانتینرز شامل تمام کدهای مختص اپلیکیشن شما است، در حالی که لایه شیپ حاوی کدهای مشترکی است که می‌تواند در چندین کانتینر استفاده شوند.این جداسازی مفاهیم همچنین به شما این امکان را می‌دهد تا به راحتی و با افزودن یا حذف کانتینرهای مورد نیازتان، بدون تحت تأثیر قرار دادن کد زیرساخت، اپلیکیشن خود را مقیاس‌بندی کنید. با پورتو، می‌توانید یک معماری نرم‌افزاری مقیاس‌پذیر و قابل نگهداری ایجاد کنید که می‌تواند با نیازهای در حال تغییر شما در طول زمان سازگار شود.بررسی بصریدیاگرام بصری معماری پورتوقبل از بررسی دقیق‌تر، بیاید دقایقی را برای درک سطوح مختلف کدی صرف کنیم که در کدبیس خود خواهید داشت:سطوح کدکد سطح پایین: کد فریمورک (عملیات اساسی مانند خواندن فایل‌ها از یک دیسک یا تعامل با دیتابیس را پیاده‌سازی می‌کند). معمولا در دایرکتوری Vendor قرار دارد.کد سطح متوسط: کد عمومی برنامه (عملکردی را پیاده‌سازی می‌کند که کد سطح بالا را سرو می‌کند و برای عملکرد به کد سطح پایین متکی است). باید در لایه Ship باشد.کد سطح بالا: کد بیزنس لاجیک (لاجیک پیچیده اپلیکیشن را در بر می‌گیرد و برای عملکرد به کد سطح متوسط متکی است). باید در لایه Containers باشد.با درک این سه سطح کد، کدبیس خود را می‌توانید بهتر سازماندهی کنید و اطمینان حاصل کنید که هر سطح مسئولیت تسک‌های مناسبی را بر عهده دارد. کد سطح پایین عملکرد اصلی برنامه شما را آماده می‌کند، در حالی که کد سطح متوسط به عنوان پلی بین کدهای سطح پایین و سطح بالا عمل می‌کند. کد سطح بالا حاوی بیزنس لاجیک خاص برنامه شما است و عملیات پیچیده را در بر می‌گیرد.با پورتو، به آسانی می‌توانید کد خود را به این سطوح مختلف جدا کنید و اطمینان حاصل کنید که هر سطح مسئولیت وظایف مناسب را بر عهده دارد. این جداسازی مفاهیم کمک می‌کند تا کدتان در طول زمان قابل نگهداری و مقیاس پذیرتر شود.دیاگرام لایه‌هابرای تجسم بهتر رابطه بین لایه کانتینرها، لایه شیپ و فریمورک زیرین، می‌توانید لایه کانتینر را به عنوان کانتینرهای باری در نظر بگیرید که به لایه شیپ (کشتی باری) متکی است که به نوبه خود به فریمورک زیرین (دریا) متکی است. این نمودار رابطه بین لایه‌های مختلف را نشان می‌دهد:لایه کانتینر (کانتینرهای باری) &gt;&gt; متکی بر &gt;&gt; لایه شیپ (کشتی باری) &gt;&gt; متکی بر &gt;&gt; فریمورک (دریا)دیاگرام بصری لایه‌ها در معماری پورتومونولیتیک به میکروسرویسپورتو به گونه‌ای طراحی شده است که بر حسب مقیاس پروژه شما اسکیل می‌شود! در حالی که بسیاری از شرکت‌ها با افزایش مقیاس و رشد پروژه، از مونولیتیک به میکروسرویس (و اخیراً سرورلِس) حرکت می‌کنند، پورتو این انعطاف‌پذیری را ارائه می‌دهد که در هر زمان با کمترین تلاش، پروژه مونولیتیک خود را به میکروسرویس (یا SOA) تبدیل کنید.پورتو از دید واژه شناسی، یک پروژه مونولیتیک را معادل یک کشتی باری حاوی کانتینرهای مختلف می‌داند، در حالی که میکروسرویس‌ها را معادل چندین کشتی باری حاوی کانتینرهای مختلف (و بدون در نظر گرفتن اندازه آنها) می‌داند. مفهوم این جملات این است که با پورتو، می‌توانید با یک سرویس مونولیتیک کوچک به خوبی سازمان‌یافته، کار خود را آغاز کنید و در صورت نیاز با انتقال کانتینرها به چندین سرویس مجزا، همزمان با رشد تیم و کسب‌وکارتان، رشد کنید.پورتو با سازماندهی کد خود در کانتینرها، که در سِکشن‌های مجزا گروه‌بندی می‌شوند، استخراج سکشن‌های جداگانه و دپلوی جداگانه آنها به عنوان میکروسرویس را آسان می‌کند. این قابلیت به شما این امکان را می‌دهد تا معماری برنامه خود را با توجه به نیازهای‌تان در طول زمان تغییر دهید، بدون اینکه نیازی به بازنویسی کل اپلیکیشن‌تان از ابتدا داشته باشید.با این حال، بهره‌برداری از چندین سرویس (با مخازن متعدد، خطوط لوله CI و غیره) به جای یک سرویس یکپارچه (مونولیتیک) می‌تواند هزینه تعمیر و نگهداری را افزایش دهد و نیازمند یک رویکرد جدید برای ارتباط بین سرویس‌ها است. نحوه ارتباط سکشن‌های «سرویس‌ها» با یکدیگر کاملاً به توسعه‌دهندگان بستگی دارد، با این حال پورتو استفاده از اِونت‌ها و یا کامندها را توصیه می‌کند.با پورتو، می‌توانید یک معماری نرم‌افزاری مقیاس‌پذیر و انعطاف‌پذیر ایجاد کنید که بتواند با نیازهای در حال تغییر کسب‌وکار شما سازگار شود. این مسئله به شما این امکان را می‌دهد که از مشکلات جلوتر بمانید و بهترین تجربه ممکن را برای کاربران خود فراهم کنید.لایه شیپلایه شیپ یا کشتی یک جزء حیاتی از معماری پورتو است. این لایه شامل کلاس‌های پایه Parent است، که کلاس‌هایی هستند که توسط هر کامپوننت مستقلی در کانتینرها اکستند شده‌اند. همچنین برخی از کدهای کاربردی نیز در این لایه قرار گرفته‌اند.کلاس‌های Parent در لایه شیپ به توسعه‌دهندگان کنترل کامل روی کامپوننت‌های کانتینر می‌دهد. به عنوان مثال، افزودن یک فانکشن به کلاس پایه Model، آن را در هر مدل موجود در کانتینرهای شما در دسترس قرار می‌دهد و در زمان و تلاش صرفه‌جویی می‌کند.لایه شیپ همچنین نقش مهمی در جداسازی کد اپلیکیشن از کد فریمورک دارد. این جداسازی ارتقاء فریمورک را بدون تأثیر بر کد برنامه تسهیل می‌کند و به مرور زمان نگهداری و به‌روزرسانی اپلیکیشن شما را آسان‌تر می‌کند.در پورتو، لایه Ship سبک و متمرکز نگه داشته می‌شود و فقط شامل کلاس‌های اصلی Parent و کدهای ابزاری است. این لایه شامل قابلیت‌های قابل استفاده مجدد متداول مانند احراز هویت یا مجوز نمی‌شود، زیرا کانتینرها این قابلیت‌ها را ارائه می‌کنند. این روش جداسازی لایه‌ها به توسعه‌دهندگان انعطاف‌پذیری بیشتری برای سفارشی‌سازی برنامه‌های خود برای رفع نیازهای خاص خود می‌دهد.پورتو با جدا کردن کد زیرساخت از کد بیزنس لاجیک، به شما این امکان را می‌دهد تا کد برنامه خود را سازماندهی شده و قابل نگهداری نگه دارید، در حالی که انعطاف پذیری را برای سفارشی‌سازی و مقیاس‌بندی برنامه خود در صورت نیاز فراهم می‌کند.ساختار لایه شیپلایه شیپ از چندین نوع کد تشکیل شده است که با هم کار می‌کنند تا به اپلیکیشن شما قدرت دهند:کد هسته: این موتور کشتی است که تمام کامپوننت‌های کانتینر شما را به صورت خودکار ریجستر و لود می‌کند تا اپلیکیشن شما را بوت کند. این نوع کد شامل اکثر کدهای جادویی است که هر چیزی را که بخشی از بیزنس لاجیک شما نیست کنترل می‌کند و بیشتر شامل کدهایی است که توسعه را با گسترش فیچرهای فریمورک تسهیل می‌کند.کد مشترک بین کانتینرها:کلاس‌های والد (Parent): این کلاس‌ها، کلاس‌های پایه هر کامپوننت در کانتینر شما هستند. افزودن فانکشن‌ها به کلاس‌های والدین، آن‌ها را در تمامی کانتینرها در دسترس قرار می‌دهد، و کلاس‌های والد به گونه‌ای طراحی شده‌اند که حاوی کد مشترک بین کانتینرهای شما باشند.کلاس‌های عمومی (Generic): این کلاس‌ها، فیچرها و کلاس‌های قابل استفاده مجدد مانند اکسپشن‌های گلوبال، میدلورهای اپلیکیشن، فایل‌های کانفیگ گلوبال و غیره هستند که می‌توانند توسط هر کانتینری استفاده شوند.توجه به این نکته مهم است که تمام کامپوننت‌های کانتینر باید از لایه Ship اکستند یا به ارث برده شوند، به ویژه پوشه Parent.هنگام جداسازی هسته به یک پکیج خارجی، Parentهای شیپ باید از Parentهای هسته (که می‌توان آن‌ها را اَبسترکت نامید، زیرا اغلب آنها قرار است کلاس‌های ابستزکت باشند) اکستند شوند. Parentهای شیپ، بیزنس لاجیک مشترک اپلیکیشن سفارشی شما را نگه می‌دارند، در حالی که ‌‌Parentهای هسته (ابسترکت‌ها) کد مشترک فریمورک شما را نگه می‌دارند. اساساً، هر چیزی که بیزنس لاجیک نباشد باید از اپلیکیشن واقعی در حال توسعه پنهان شود.با سازماندهی کد خود به این روش، پورتو نگهداری و به روزرسانی اپلیکشن شما را در طول زمان آسان می‌کند، در حالی که به شما این امکان را می‌دهد تا فیچرهای فریمورک را برای رفع نیازهای خاص خود گسترش دهید و سفارشی کنید.لایه کانتینرهالایه کانتینر قلب معماری پورتو است. اینجا جایی است که بیزنس لاجیک خاص اپلیکیشن، شامل تمامی فیچرها و عملکردهای اپلیکیشن، قرار دارند. شما ۹۰٪ از زمان خود را صرف کار در این لایه، توسعه فیچرهای جدید و نگهداری فیچرهای موجود خواهید کرد.یکی از مزایای اصلی استفاده از پورتو این است که پیچیدگی یک مسئله را با شکستن آن به کانتینرهای کوچکتر و قابل مدیریت‌تر مدیریت می‌کند. هر کانتینر به گونه‌ای طراحی شده است که بخش خاصی از عملکرد را در خود جای دهد و توسعه، آزمایش و نگهداری آن را آسان‌تر کند.با سازماندهی کد خود به این روش، پورتو به شما کمک می‌کند تا کدبیسی ماژولارتر و با قابلیت استفاده مجدد ایجاد کنید. این باعث می‌شود مقیاس‌بندی و نگهداری برنامه شما در طول زمان آسان‌تر شود و همچنین میزان تکرار کد در بخش‌های مختلف برنامه شما کاهش می‌یابد.به طور کلی، لایه کانتینرها کلید ایجاد یک معماری کاربردی قابل نگهداری و مقیاس پذیر با پورتو است.کانتینرهایک کانتینر یک ماژول مستقل است که بخش خاصی از عملکرد در اپلیکیشن شما را در برمی‌گیرد. این ماژول می‌تواند یک فیچر، یک ظرف نگهدارنده APIهای RESTful یا هر چیز دیگری که بخواهید باشد.مثال 1:به عنوان مثال، در یک برنامه TODO، آبجکت‌های &quot;Task&quot; و &quot;User&quot; و &quot;Calendar&quot; هر کدام در یک کانتینر متفاوت با روت‌ها، کنترلرها، مدل‌ها، اکسپشن‌ها و موارد دیگر قرار می‌گیرند. هر کانتینر مسئول دریافت ریکوئست‌ها و ریترن کردن ریسپانس‌ها از هر رابط کاربری پشتیبانی‌شده (وب، API و غیره) است.در حالی که توصیه می‌شود در هر کانتینر فقط از یک مدل استفاده کنید، در برخی موارد، ممکن است به بیش از یک مدل نیاز داشته باشید، و این کاملاً صحیح است. همچنین می توانید از Value Objectها استفاده کنید که شبیه به مدل‌ها هستند اما دیتای خود را در دیتابیس ذخیره نمی‌کنند، بلکه به عنوان داده در مدل‌ها نشان داده می‌شوند. این آبجکت‌ها پس از دریافت داده‌ها از دیتابیس به طور خودکار ساخته می‌شوند، مانند قیمت، لوکیشن، زمان و موارد دیگر.مهم است که به خاطر داشته باشید که دو مدل به معنای دو ریپازیتوری، دو ترنسفورمر و ... است. جز در حالتی که بخواهید از هر دو مدل همیشه با هم استفاده کنید، آنها را به دو کانتینر تقسیم کنید.اگر بین دو کانتینر وابستگی بالایی دارید، قرار دادن آنها در یک سکشن، استفاده مجدد از آنها در پروژه‌های دیگر را آسان‌تر می‌کند.مثال 2:به عنوان مثال، اگر به اِپیاتو، اولین پروژه پیاده‌سازی با پورتو نگاهی بیندازید، متوجه خواهید شد که Authentication و Authorization هر دو فیچر‌هایی هستند که به عنوان کانتینر ارائه می‌شوند.پورتو با شکستن اپلیکیشن شما به کانتینرهای کوچکتر و قابل مدیریت‌تر، توسعه، تست و  نگهداری کدبیس شما را در طول زمان آسان‌تر می‌کند.ساختار پایه کانتینرهاContainerA
├── Actions
├── Tasks
├── Models
└── UI
    ├── WEB
    │   ├── Routes
    │   ├── Controllers
    │   └── Views
    ├── API
    │   ├── Routes
    │   ├── Controllers
    │   └── Transformers
    └── CLI
        ├── Routes
        └── Commands

ContainerB
├── Actions
├── Tasks
├── Models
└── UI
    ├── WEB
    │   ├── Routes
    │   ├── Controllers
    │   └── Views
    ├── API
    │   ├── Routes
    │   ├── Controllers
    │   └── Transformers
    └── CLI
        ├── Routes
        └── Commandsارتباط بین کانتینرهاکانتینرها می‌توانند به روش‌های مختلفی در یک سکشن با یکدیگر ارتباط برقرار کنند:هر کانتینر ممکن است به یک یا چند کانتینر دیگر وابستگی داشته باشد.یک کنترلر می‌تواند تسک‌های (Tasks) داخل کانتینر دیگری را فراخوانی کند.یک مدل ممکن است با مدلی از کانتینر دیگر ریلیشن داشته باشد.سایر شکل‌های ارتباطی مانند اونت‌ها و کامندها نیز امکان‌پذیر هستند.اگر از ارتباطات مبتنی بر رویداد بین کانتینرها استفاده می‌کنید، پس از جداسازی کدبیس خود به چندین سرویس، می‌توانید از همان مکانیسم استفاده کنید.توجه داشته باشید که اگر با تفکیک کد خود به ماژول‌ها/دامنه‌ها آشنا نیستید یا ترجیح می‌دهید از آن رویکرد استفاده نکنید، می‌توانید کل برنامه خود را در یک کانتینر ایجاد کنید. با این حال، روش توصیه شده‌ای نیست و ممکن است در طول زمان آنقدر مقیاس‌پذیر یا قابل نگهداری نباشد.سکشن‌هاسکشن یکی دیگر از گونه‌های بسیار مهم در معماری پورتو است.یک سکشن گروهی از کانتینرهای مرتبط است. هر سکشن می‌تواند یک سرویس (میکرو یا بزرگتر)، یا یک سیستم فرعی در سیستم اصلی یا هر چیز دیگری باشد.یک سکشن را به عنوان ردیف‌هایی از کانتینرها در یک کشتی باری در نظر بگیرید. کانتینرها به خوبی سازماندهی شده در ردیف‌ها، سرعت بارگیری و تخلیه کانتینرهای مرتبط را برای یک مشتری خاص افزایش می دهد.تعریف اولیه سکشن پوشه‌ای است که حاوی کانتینرهای مرتبط است. با این حال مزایای آن بسیار زیاد است. (یک سکشن معادل یک bounded context در Domain-driven design است) هر سکشن بخشی از سیستم شما را نشان می دهد و کاملاً از سکشن‌های دیگر جدا شده است.هر سکشن می‌تواند به طور جداگانه دپلوی شود.مثال 1:اگر در حال ساخت یک بازی مسابقه‌ای مانند Need for Speed هستید، ممکن است دو سکشن زیر را داشته باشید: سکشن مسابقه و سکشن لابی، که هر سکشن شامل یک کانتینر Car و یک مدل Car در داخل آن است، اما با پراپرتی‌ها و عملکردهای متفاوت. در این مثال، مدل Car از سکشن Race می‌تواند شامل بیزنس لاجیک شتاب دادن و کنترل ماشین باشد، در حالی که مدل Car از سکشن Lobby شامل بیزنس لاجیک سفارشی کردن ماشین (رنگ، لوازم جانبی...) قبل از مسابقه است.سکشن‌ها این امکان را فراهم می‌آورند تا مدل‌های بزرگ را به مدل‌های کوچکتر بشکنید. و می‌توانند مرزهایی را برای مدل‌های مختلف در سیستم شما فراهم کنند.اگر سادگی را ترجیح می‌دهید یا تنها یک تیم دارید که روی پروژه کار می‌کند، می‌توانید هیچ سکشنی (جایی که همه کانتینرها در پوشه کانتینرها قرار دارند) نداشته باشید، به این معنی که پروژه شما تنها یک سکشن است. در این حالت اگر پروژه به سرعت رشد کرد و تصمیم گرفتید که باید از سکشن‌ها استفاده کنید، می‌توانید یک پروژه جدید با یک سکشن ایجاد کنید که به آن میکروسرویس می گویند. در میکروسرویس هر سکشن &quot;بخش پروژه&quot; در پروژه خود (ریپازیتوری) قرار گرفته است و آنها می‌توانند از طریق شبکه معمولاً با استفاده از پروتکل HTTP ارتباط برقرار کنند.مثال 2:در یک اپلیکیشن ایکامرس معمولی می‌توانید سکشن‌های زیر را داشته باشید: سکشن موجودی، سکشن حمل و نقل، سکشن سفارش، سکشن پرداخت، سکشن کاتالوگ و موارد دیگر...همانطور که می‌توانید تصور کنید هر یک از این سکشن‌ها می‌توانند به تنهایی یک میکروسرویس باشند. و می‌توانند بر اساس ترافیکی که دریافت می‌کند استخراج و در سرور خود دپلوی شود.ارتباط بین سکشن‌هایک سکشن باید ایزوله باشد و نباید به هیچ سکشن دیگری وابسته باشد.یک سکشن ممکن است به اونت‌هایی که توسط سکشن‌های دیگر فایر می‌شوند گوش دهد. (کامندها را می‌توان به عنوان جایگزینی برای اونت‌ها استفاده کرد.)این معماری امکان اتصال آزاد بین سکشن‌ها را فراهم می‌کند و سیستم مقیاس‌پذیرتر و انعطاف‌پذیرتر را امکان‌پذیر می‌کند. از رویدادها و کامندها می‌توان برای برقراری ارتباط بین سکشن‌های مختلف استفاده کرد که امکان گسترش و اصلاح آسان سیستم را در طول زمان فراهم می‌کند.کامپوننت‌هادر لایه کانتینر، مجموعه‌ای از کلاس‌های Component با مسئولیت‌های از پیش تعریف شده وجود دارند. هر تکه کدی که می‌نویسید باید در یک کامپوننت (عملکرد کلاس یا class function) قرار داده شود. پورتو لیست بزرگی از آن کامپوننت‌ها را برای شما تعریف می‌کند، همراه با مجموعه‌ای از دستورالعمل‌ها که باید هنگام استفاده از آن‌ها رعایت کنید تا فرآیند توسعه را روان نگه دارید.کامپوننت‌ها یکپارچگی و تبات را تضمین می‌کنند و نگهداری از کد شما را آسان‌تر می‌کنند، زیرا از قبل می‌دانید هر قطعه کد را کجا باید پیدا کنید.انواع کامپوننتهر کانتینر از تعدادی کامپوننت تشکیل شده است. کامپوننت‌ها در پورتو به دو نوع تقسیم می‌شوند: کامپوننت‌های اصلی و کامپوننت‌های اختیاری.کامپوننت‌های اصلی: کامپوننت‌های ضروری که برای کانتینر خود نیاز دارید. این کامپوننت‌ها اجباری هستند و برای دستیابی به عملکرد اصلی کانتینر شما استفاده می‌شوند.کامپوننت‌های اختیاری: این‌ها کامپوننت‌هایی هستند که می‌توانید از آن‌ها برای افزودن عملکرد اضافی به کانتینر خود استفاده کنید. این کامپوننت‌ها اختیاری هستند و بسته به نیاز خود می‌توانید انتخاب کنید که از آنها استفاده کنید یا نه.با استفاده از این کامپوننت‌ها، می‌توانید یک کدبیس ماژولار و قابل استفاده مجدد ایجاد کنید و نگهداری و اصلاح کد خود را در آینده آسان‌تر کنید.کامپوننت‌های اصلیشما باید از این کامپوننت‌ها استفاده کنید زیرا تقریباً برای همه انواع برنامه‌های وب ضروری هستند:روت‌ها - کنترلرها - ریکوئست‌ها - اکشن‌ها - تسک‌ها - مدل‌ها - ویوها - ترنسفورمرها.ویوها: باید در مواردی استفاده شود که برنامه صفحات HTML را سرو می‌کند.ترنسفورمر: باید در مواردی استفاده شود که برنامه داده‌های جیسون یا XML را سرو می‌کند.برای تعاریف و اصول دقیق هر یک از اجزای اصلی، لطفاً به بخش &quot;اصول و تعاریف برخی از کامپوننت‌ها&quot; در بخش مراجعه کنید.دیاگرام تعامل کامپوننت‌هادیاگرام تعامل بین کامپوننت‌ها در معماری پورتولایف سایکل ریکوئستلایف سایکل ریکوئست یا چرخه عمر درخواست فرآیندی است که یک ریکوئست از زمان فراخوانی یک API و حرکت از طریق کامپوننت‌ها، تا آماده‌سازی ریسپانس طی می‌کند. مراحل زیر یک سناریوی فراخوانی یک API بیسیک را توضیح می‌دهد:کاربر یک اندپوینت را در یک فایل روت فراخوانی می‌کند.اندپوینت یک میدلور را برای هندل کردن احراز هویت فراخوانی می‌کند.اندپوینت فانکشن متناظرش را در کنترلر فراخوانی می‌کند.آبجکت ریکوئست، که به صورت خودکار به کنترلر اینجکت شده، ولیدیشن‌های ریکوئست و قوانین احراز هویت را اعمال می‌کند.کنترلر یک اکشن را فراخوانی کرده و داده‌ها را از طریق آبجکت ریکوئست به آن پاس می‌دهد.اکشن بیزنس لاجیک را اجرا می‌کند، یا می‌تواند هر تعداد تسکی که برای اجرای زیرمجموعه‌های قابل استفاده مجدد بیزنس لاجیک مورد نیاز دارد را فراخوانی کند.تسک‌ها زیرمجموعه‌های قابل استفاده مجدد بیزنس لاجیک را اجرا می‌کنند، هر تسک مسئول یک بخش از اکشن اصلی است.اکشن داده‌هایی را برای ریترن کردن به کنترلر آماده می‌کند، و ممکن است در صورت نیاز این داده‌ها را از تسک‌ها جمع آوری کرده باشد.کنترلر ریسپانس را با استفاده از یک ویو یا ترنفسفورمر می‌سازد و آن را برای کاربر ارسال می‌کند.مهم است که توجه داشته باشید که آبجکت ریکوئست قوانین ولیدیشن و احرازهویت ریکوئست را هندل می‌کند، در حالی که اکشن بیزنس لاجیک را اجرا می‌کند. تسک‌ها می‌توانند برای اجرای زیرمجموعه‌های قابل استفاده مجدد از بیزنس لاجیک استفاده شوند که هر تسک مسئول یک بخش از اکشن اصلی است. ویو یا ترنسفورمر برای ایجاد ریسپانسی  استفاده می‌شود که به کاربر ارسال می‌شود.اصول و تعاریفروت‌ها (Routes)روت‌ها مسئول مَپ کردن ریکوئست‌های HTTP ورودی به متدهای متناظر خود در کنترلرها هستند. هنگامی که یک ریکوئست HTTP به اپلیکیشن ارسال می‌شود، اندپوینت‌ها، پترن URL منطبق با خودشان رو یافته و متد کنترلر متناظر با آن را فراخوانی می‌کنند.اصولسه نوع روت وجود دارد، روت‌های API، روت‌های وب و روت‌های CLI.فایل‌های مربوط به روت‌های API باید از فایل‌های روت‌های Web جدا باشند و هر کدام در پوشه خود قرار گیرند.پوشه روت‌های Web تنها حاوی اندپوینت‌های Web (قابل دسترسی توسط مرورگرهای وب) خواهند بود. و پوشه روت‌های API تنها حاوی اندپوینت‌های API (قابل دسترسی توسط هر اپلکیشن مصرف کننده‌ای) خواهد بود.هر کانتینری باید روت‌های خود را داشته باشد.هر فایل روت تنها باید حاوی یک اندپوینت باشد.کار اندپوینت این است که وقتی یک ریکوئست از هر نوعی ساخته شد، یک متد در کنترلر متناظرش فراخوانی کند (اندپوینت هیچ کار دیگری نباید انجام دهد).کنترلرهاکنترلر‌ها مسئول اعتبارسنجی ریکوئست‌ها، سرور کردن داده‌های ریکوئست و ساختن ریسپانس هستند. اعتبارسنجی و ریسپانس در کلاس‌های جداگانه اتفاق می‌افتد اما از کنترلر فراخوانی می‌شود.کنترلرها مفهومی مشابه مفهوم‌شان در MVC دارند (حرف C در MVC هستند)، اما با مسئولیت‌های محدود و از پیش تعریف شده.اصولکنترلرها نباید چیزی درباره بیزنس لاجیک یا هر آبجکت بیزنسی دیگری بدانند.یک کنترلر تنها باید کارهای زیر را انجام دهد: خواندن داده‌های یک ریکوئست (ورودی کاربر)، فراخوانی یک یک اکشن (و ارسال داده‌های ریکوئست به آن) و ساخت یک رسپانس (معمولاً ریسپانس را بر اساس داده‌های جمع آوری شده از اکشن فراخوانی شده می‌سازد)کنترلرها نباید حاوی هیچ شکلی از بیزنس لاجیک باشند (برای اجرای بیزنس لاجیک باید یک اکشن را فراخوانی کنند).کنترلرها نباید تسک‌های کنترلر را به صورت مستقیم فراخوانی کنند. آنها فقط می‌توانند اکشن‌ها را فراخوانی کنند (و سپس اکشن‌ها، می توانند تسک‌ها کانتینر را فراخوانی کنند).کنترلرها را تنها می‌توان توسط اندپوینت‌های روت‌ها فراخوانی کرد.هر پوشه UI کانتینر (Web، API، CLI) کنترلرهای خود را خواهد داشت.ممکن است تعجب کنید که چرا وقتی می‌توانیم مستقیماً اکشن را از روت فراخوانی کنیم، به Controller نیاز داریم. لایه کنترلر کمک می‌کند تا اکشن در چندین رابط کاربری (Web &amp; API) قابل استفاده مجدد باشد، زیرا اکشن ریسپانسی ایجاد نمی‌کند و این باعث کاهش میزان تکرار کد در رابط‌های کاربری مختلف می‌شود.در زیر مثالی آورده شده است:رابط کاربری (وب): روت W-R1 -&gt; کنترلر W-C1 -&gt; اکشن A1.رابط کاربری (API): روت A-R1 -&gt; کنترلر A-C1 -&gt; اکشن A1.همانطور که در مثال بالا می بینید، اکشن A1 توسط هر دو روت W-R1 و A-R1 استفاده شده که این به لطف لایه کنترلرهای موجود در هر UI محقق شده است.ریکوئست‌هاریکوئست‌ها عمدتاً ورودی کاربر را در اپلیکیشن سِرو می‌کنند. آنها برای اعمال خودکار قوانین اعتبارسنجی و احرازهویت بسیار کاربردی هستند.ریکوئست‌‌ها بهترین مکان برای اعمال اعتبارسنجی‌ها هستند زیرا هر مجموعه قوانین اعتبارسنجی مربوط به یک ریکوئست می‌شوند. ریکوئست‌ها همچنین می‌توانند مجوزهای دسترسی (Authorization) را بررسی کنند، به‌عنوان مثال، بررسی کنند که آیا این کاربر به این متد کنترلر دسترسی دارد یا خیر (برای مثال، بررسی کند که آیا کاربر خاصی که قصد حذف محصولی را دارد مالک آن محصول است، یا بررسی کند که آیا این کاربر، ادمین است که بتواند چیزی را ویرایش است).اصولیک ریکوئست می‌تواند قوانین اعتبارسنجی/مجوزهای دسترسی را نگهداری کند.ریکوئست‌ها تنها باید در کنترلرها اینجکت شوند. هنگامی که اینجکت شدند، به طور خودکار بررسی می‌کنند که آیا داده‌های ریکوئست با قوانین اعتبارسنجی مطابقت دارند یا خیر، و اگر ورودی‌های ریکوئست معتبر نباشد، یک اکسپشن تولید می‌کنند.همچنین از ریکوئست‌ها می‌توان برای قوانین دسترسی استفاده کرد. آنها می‌توانند بررسی کنند که آیا کاربر مجاز به ارسال ریکوئست است یا خیر.اکشن‌هااکشن‌ها نشان دهنده موارد استفاده از اپلیکیشن (یعنی اکشن‌ها یا عملیاتی که توسط کاربر یا نرم افزار در اپلیکیشن قابل انجام است) هستند.اکشن‌ها می‌توانند حاوی بیزنس لاجیک باشند و یا تسک‌ها را برای اجرای بیزنس لاجیک مدیریت کنند.اکشن‌ها ساختارهای داده را به عنوان ورودی می‌گیرند، آن‌ها را مطابق بیزنس رول (business rules) دستکاری می‌کنند و ساختارهای داده جدید را به عنوان خروجی ارائه می‌دهند.اکشن‌ها نباید کانسرنی راجع به مربوط به نحوه جمع آوری داده‌ها یا نحوه نمایش آنها داشته باشد.با نگاه کردن به پوشه اکشن‌های یک کانتینر، می‌توانید بفهمید که کانتینر شما چه موارد استفاده (فیچرهایی) را ارائه می‌دهد. با مشاهده تمام اکشن‌ها، می‌توانید بگویید که یک اپلیکیشن چه کارهایی می‌تواند انجام دهد.اصولهر اکشن تنها باید مسئول انجام یک مورد استفاده در اپلیکیشن باشد.یک اکشن می‌تواند داده‌ها را از تسک‌ها گرفته و آنها را به تسک دیگری پاس دهد.یک اکشن ممکن است چندین تسک را فراخوانی کند، و حتی می تواند تسک‌های داخل سایر کانتینرها را نیز فراخوانی کند.اکشن‌ها می‌توانند داده‌ها را به کنترلر برگرداند.اکشن‌ها نباید ریسپانسی برگردانند (وظیفه کنترلر این است که یک ریسپانس برگرداند).یک اکشن نباید اکشن دیگری را فراخوانی کند. درعوض، اگر نیاز به استفاده مجدد از بخش بزرگ از بیزنس لاجیک در چندین اکشن دارید، و این تکه در حال فراخوانی چندین تسک است، می‌توانید یک ساب اکن ایجاد کنید (به بخش ساب اکشن در زیر مراجعه کنید).اکشن‌ها عمدتاً از طریق کنترلرها استفاده می‌شوند. با این حال، آنها را می‌توان از طریق اونت‌‌ها، لسنرها، کامندها و یا کلاس‌های دیگر استفاده کرد، اما نباید از طریق تسک‌ها استفاده شوند.هر اکشن تنها باید یک متد با نام run() داشته باشد.متد اصلی اکشن یعنی run() می تواند یک آبجکت ریکوئست را به عنوان پارامتر بپذیرد.اکشن‌ها مسئول هندل کردن اکسپشن‌های مورد انتظار هستند.تسک‌هاتسک‌ها کلاس‌هایی هستند که بیزنس لاجیک مشترک بین چندین اکشن از کانتینرهای مختلف را نگه می‌دارند.هر تسک مسئول بخش کوچکی از لاجیک است و معمولاً دارای یک متد به نام run() است. با این حال، تسک‌ها در صورت نیاز می‌تواند توابع بیشتری با نام‌های صریح داشته باشند، که باعث می‌شود کلاس تسک جایگزین مفهوم پرچم‌های فانکشن شود.تسک‌ها اختیاری هستند، اما در بیشتر موارد، ناچار به استفاده از آنها خواهید بود. به عنوان مثال، اگر اکشن ۱ را تعریف کرده‌اید که باید رکوردی را با ID خود از دیتابیس پیدا کند، سپس یک اونت را فایر کند. و اکشن ۲ دارید که باید رکورد مشابهی را با ID خود پیدا کند، سپس یک API خارجی را فراخوانی می‌کند. از آنجایی که هر دو اکشن لاجیک &quot;یافتن یک رکورد با ‌ID&quot; را اجرا می‌کنند، می‌توانیم آن بیزنس لاجیک را گرفته و در کلاس خودش یعنی تسک قرار دهیم. این تسک اکنون توسط این اکشن‌ها و هر اکشن دیگری که ممکن است در آینده ایجاد کنید قابل استفاده مجدد است.قانون این است که هر زمان که امکان استفاده مجدد از تکه کدی از یک اکشن را یافتید، باید آن قطعه کد را در یک تسک قرار دهید. کورکورانه برای همه چیز تسک ایجاد نکنید. همیشه می‌توانید با نوشتن تمام بیزنس لاجیک در یک اکشن شروع کنید و فقط زمانی که نیاز به استفاده مجدد از آن دارید یک تسک اختصاصی ایجاد کنید. ریفکتور کردن برای سازگاری با رشد کدها ضروری است.اصولهر تسک باید یک تنها مسئولیت (شغل) داشته باشد.یک تسک می‌تواند داده‌ها را دریافت کرده و برگرداند. (تسک نباید ریسپانسی را ریترن کند، وظیفه کنترلر این است که یک ریسپانس را ریترن کند).یک تسک نباید تسک دیگری را فراخوانی کند. زیرا این ما را به معماری سرویس‌ها برمی‌گرداند، که می‌تواند به یک بهم ریختگی بزرگ منجر شود.یک تسک نباید یک اکشن را فراخوانی کند. چون کد شما در آن صورت منطقی نخواهد بود!تسک‌ها تنها باید از طریق اکشن‌ها فراخوانی شوند. (آنها را می توان از ظریق اکشن‌های کانتینرهای دیگر نیز فراخوانی کرد!).یک تسک نباید از کنترلر فراخوانی شود. زیرا این منجر به فیچرهای غیر مستند در کد شما می‌شود. داشتن چندین اکشن (به عنوان مثال، FindUserByIdAction و FindUserByEmailAction) که هر دو اکشن یک تسک یکسان را فراخوانی می‌کنند، بسیار خوب و منطقی است، همچنین بسیار خوب است که یک اکشن FindUserAction تصمیم بگیرد که کدام تسک را باید فراخوانی کند.یک تسک نباید یک آبجکت ریکوئست را در هیچ یک از فانکشن‌های خود بپذیرد. تسک می تواند هر چیزی را در پارامترهای فانکشن خود بگیرد اما هرگز یک آبجکت ریکوئست در آنجا جایی ندارد. این اصل باعث می‌شود آن تسک را برای استفاده در هر جایی آزاد نگه دارید و می‌توان آن را به طور مستقل تست کرد.مدل‌هامدل‌ها یک انتزاع برای داده‌ها ارائه می‌کنند و داده‌ها را در دیتابیس نشان می‌دهند. (آنها حرف M در MVC هستند).مدل‌ها مسئول نحوه مدیریت داده‌ها هستند و اطمینان حاصل می‌کنند که داده‌ها به درستی در بک‌اند (به عنوان مثال دیتابیس) ذخیره می‌شوند.اصولیک مدل نباید حاوی بیزنس لاجیک باشد، بلکه فقط باید کد و داده‌هایی داشته باشد که خود را نشان می‌دهد (مانند روابط با مدل‌های دیگر، فیلدهای پنهان، نام جدول، و اتریبیوت‌های فیلیبل).یک کانتینر به تنهایی می‌تواند حاوی چندین مدل باشد.یک مدل می‌تواند روابط بین خود و سایر مدل‌ها را تعریف کند (در صورت وجود چنین روابطی).ویوهاویوها حاوی HTML ارائه شده توسط اپلیکیشن شما هستند.هدف اصلی آنها جداسازی لاجیک اپلیکیشن از لاجیک پرزنتیشن است. (آنها حرف V در MVC هستند).ویوها داده‌ها را از کنترلر دریافت می‌کنند و از آن برای تولید HTML خروجی‌ای استفاده می‌کنند که به مرورگر کلاینت ارسال می‌شود. ویوها همچنین می‌توانند شامل فایل‌های قالبی باشند که ساختار و طرح‌بندی HTML را تعریف می‌کنند و حفظ یکپارچگی در چندین صفحه را آسان‌تر می‌کنند.اصولویوها فقط باید از طریق کنترلرهای وب استفاده شوند.ویوها باید بر اساس آنچه نمایش داده می‌شود به چندین فایل و پوشه تفکیک شوند.یک کانتینر ممکن است حاوی چندین فایل ویو باشد.ویوها نباید دارای بیزنس لاجیک یا دستکاری داده باشند. آنها فقط مسئول ارائه هستند.ترنسفورمرهاترنسفورمرها، مخفف ترنسفورمرهای ریسپانس (Response Transformers)، معادل ویوها هستند اما برای ریسپانس‌های جیسون. در حالی که ویوها داده‌ها را می‌گیرد و آن‌ها را در قالب HTML نمایش می‌دهد، ترنسفورمرها داده‌ها را می‌گیرند و آن‌ها را در قالب JSON نمایش می‌دهند.ترنسفورمرها مسئول تبدیل مدل‌ها به آرایه هستند. آنها یک مدل یا گروهی از مدل‌ها &quot;کالکشن&quot; را می‌گیرند و آن را به یک آرایه قابل سریالایز فرمت شده تبدیل می‌کنند.اصولهمه ریسپانس‌های API باید از طریق ترنسفورمرها قالب‌بندی (فرمت) شوند.هر مدلی (که با فراخوانی API برگردانده می‌شود) باید یک ترنسفورمر متناظر داشته باشد.یک کانتینر به تنهایی می‌تواند چندین ترنسفورمر داشته باشد.معمولاً، هر مدل دارای یک ترنسفورمر برای اطمینان از سازگاری با فرمت ریسپانس API است.اکسپشن‌هااکسپشن‌ها نیز شکلی از خروجی هستند که مورد انتظار (مانند یک اکسپشن API) هستند و باید به خوبی تعریف شوند.اکسپشن‌ها راهی برای هندل کردن خطاها با ساختار از پیش تعریف شده و مورد انتظار است. در اپلیکیشنی که به خوبی طراحی شده است، هر زمان که خطایی رخ می‌دهد که نمی‌تواند توسط کد در زمینه فعلی آن هندل شود، باید اکپشن‌هایی رخ دهند.اصولدو نوع اکسپشن شامل اکسپشن‌های کانتینری (در کانتینرها قرار می‌گیرند) و اکسپشن‌های عمومی (در شیپ قرار می‌گیرند) وجود دارد.تسک‌ها، ساب تسک‌ها، مدل‌ها، و هر کلاسی به طور کلی می‌تواند یک اکسپشن بسیار خاص ایجاد کند.کلاس فراخوان باید تمام اکسپشن‌های مورد انتظار از کلاس فراخوانی شده را مدیریت کند.اکشن‌ها باید همه اکسپشن‌ها را هندل کنند و مطمئن شوند که به کامپوننت‌های بالایی نشت نمی‌کنند و باعث رفتارهای غیرمنتظره نمی‌شوند.اسامی اکسپشن‌ها باید تا حد امکان خاص باشد و باید دارای پیام های توصیفی واضح باشد.ساب اکشن‌هاساب اکشن‌ها برای حذف کدهای تکراری در اکشن‌ها طراحی شده‌اند. ساب اکشن‌ها به اکشن‌ها اجازه می‌دهند تا دنباله ای از تسک‌ها را به اشتراک بگذارد، در حالی که تسک‌ها به اکشن‌ها اجازه می‌دهند تا بخشی از عملکرد را به اشتراک بگذارد.ساب اکشن‌ها برای حل یک مشکل ایجاد می‌شوند. گاهی اوقات یک بخش بزرگ از بیزنس لاجیک در چندین اکشن مجددا استفاده می‌شود و آن کد قبلاً برخی از تسک‌ها را فراخوانی می‌کند. در چنین مواردی راه حل ایجاد یک ساب اکشن است.به عنوان مثال، با فرض اینکه یک اکشن A1 در حال فراخوانی تسک ۱، تسک ۲ و تسک ۳ است و یک اکشن دیگری با نام اکشن A2، تسک ۲، تسک ۳، تسک ۴ و تسک ۵ را فراخوانی می‌کند. توجه داشته باشید که هر دو اکشن وظایف ۲ و ۳ را فراخوانی می‌کنند. برای از بین بردن تکرار کد، می‌توانیم یک ساب اکشن ایجاد کنیم که حاوی تمام کدهای مشترک بین هر دو اکشن باشد.اصولساب اکشن‌ها باید تسک‌ها را فراخوانی کنند. اگر یک ساب اکشن تمام بیزنس لاجیک را بدون کمک حداقل یک تسک انجام می‌دهد، احتمالاً نباید یک ساب اکشن بلکه باید یک تسک باشد.یک ساب اکشن می‌تواند داده‌ها را از تسک گرفته و آنها را به تسک دیگری پاس دهد.یک ساب اکشن می‌تواند چندین تسک را فراخوانی کند (آنها حتی می‌توانند تسک‌ها را از کانتینرهای دیگر فراخوانی کنند).ساب اکشن‌ها می‌توانند داده‌ها را به اکشن برگردانند.ساب اکشن نباید هیچ ریسپانسی را برگرداند (وظیفه کنترلر این است که یک ریسپانس را برگرداند).ساب اکشن نباید ساب اکشن دیگری را فراخوانی کند (تا حد امکان از آن اجتناب کنید).ساب اکشن باید از اکشن‌ها استفاده کند. با این حال، آنها را می‌توان از طریق اونت‌ها، کامندها، و یا کلاس‌های دیگر استفاده کرد. اما آنها نباید از طریق کنترلرها یا تسک‌ها استفاده شوند.هر ساب اکشن تنها باید یک فانکشن به نام run()داشته باشد.کامپوننت‌های اختیاریکامپوننت‌های اختیاری مختلفی وجود دارند که می‌توانند بر اساس نیازهای خاص شما به اپلیکیشن‌تان اضافه شوند. اگرچه ممکن است همه آنها ضروری نباشند، برخی از آنها به شدت توصیه می‌شود. این کامپوننت‌ها عبارتند از:تست‌ها: برای تست خودکار اپلیکیشن شمااونت‌ها: برای برادکست و لسنینگ اونت‌های برنامهلسنرها: برای هندل کردن اونت‌‌های اپلیکیشنکامندها: برای ایجاد کامندهای CLI سفارشیمایگریشن‌ها: برای مدیریت تغییرات در اسکیمای دیتابیس شماسیدرها: برای پر کردن دیتابیس با داده‌های تستیفکتوری‌ها: برای تولید داده‌های تستیمیدلورها: برای هندل کردن ریکوئست‌ها و ریسپانس‌های HTTPریپازیتوری‌ها: برای ایجاد انتزاع در لاجیک پایداری داده‌هاکریتریا: برای کوئری زدن به دیتابیس با معیارهای پیچیدهپالسی‌ها: برای تعریف پالسی‌های authorization سرویس پرووایدرها: برای رجیستر کردن سرویس‌ها در کانتینر اپلیکیشنکانترکت‌ها: برای تعریف اینترفیس‌هایی که باید توسط کلاس‌ها پیاده‌سازی شوندتریت‌ها: برای به اشتراک‌گذاری کد بین کلاس‌هاجاب‌ها: برای اجرای تسک‌های طولانی مدت در بک گراندولیوها: برای نمایش آبجکت ولیوهای سادهترنسپورترها: برای ارسال و دریافت داده‌ها بین سیستم‌هاایمیل‌ها: برای ارسال پیام‌های ایمیلنوتیفیکشن‌ها: برای ارسال نوتیفیکیشن به کاربرانو بیشتر...: در صورت نیاز کامپوننت‌های اضافی اضافه کنیددر صورت نیاز برای بهبود عملکرد و قابلیت نگهداری آن، این کامپوننت‌ها را به برنامه خود اضافه کنید.ساختار یک کانتینر معمولیContainer
├── Actions
├── Tasks
├── Models
├── Values
├── Events
├── Listeners
├── Policies
├── Exceptions
├── Contracts
├── Traits
├── Jobs
├── Notifications
├── Providers
├── Configs
├── Mails
│   └── Templates
├── Data
│   ├── Migrations
│   ├── Seeders
│   ├── Factories
│   ├── Criteria
│   ├── Repositories
│   ├── Validators
│   ├── Transporters
│   └── Rules
├── Tests
│   └── Unit
└── UI
    ├── API
    │   ├── Routes
    │   ├── Controllers
    │   ├── Requests
    │   ├── Transformers
    │   └── Tests
    │       └── Functional
    ├── WEB
    │   ├── Routes
    │   ├── Controllers
    │   ├── Requests
    │   ├── Views
    │   └── Tests
    │       └── Acceptance
    └── CLI
        ├── Routes
        ├── Commands
        └── Tests
            └── Functionalویژگی‌های کیفی پورتوماژولار بودن و قابلیت استفاده مجدددر پورتو، بیزنس لاجیک اپلیکیشن شما در کانتینرها قرار می‌گیرد. کانتینرهای پورتو از نظر ماهیت شبیه به ماژول‌ها (از معماری ماژولار) و دامنه‌ها (از معماری DDD) هستند.کانتینرها می‌توانند به کانتینرهای دیگر وابسته باشند، مشابه اینکه یک لایه می‌تواند به لایه‌های دیگر در معماری چندلایه وابسته باشد.قوانین و دستورالعمل‌های پورتو، جهت‌های وابستگی بین کانتینرها را به حداقل رسانده و تعریف می‌کند تا از ارجاعات دایره‌ای بین آنها جلوگیری شود.علاوه بر این، امکان گروه‌بندی کانتینرهای مرتبط را در سکشن‌های مختلف فراهم می‌کند و امکان استفاده مجدد از آنها را در پروژه‌های مختلف فراهم می‌کند. هر سکشن شامل یک بخش قابل استفاده مجدد از بیزنس لاجیک اپلیکیشن شما است.وقتی صحبت از مدیریت وابستگی به میان می‌آید، توسعه‌دهنده مختار است که هر کانتینر را به ریپازیتوری خود منتقل کند یا همه کانتینرها را با هم در یک ریپازیتوری نگه دارد.قابلیت نگهداری و مقیاس‌پذیریهدف پورتو کاهش هزینه‌های نگهداری با صرفه‌جویی در زمان توسعه‌دهندگان است. ساختار آن به گونه‌ای است که مستقل بودن کدها از هم را تضمین کرده و یکپارچگی را در سیستم اجباری کند، که همگی به قابلیت نگهداری آن کمک می‌کنند.داشتن یک فانکشن مستقل در هر کلاس برای توصیف یک عملکرد، افزودن و حذف ویژگی‌ها را به یک فرآیند آسان تبدیل می‌کند.پورتو یک کدبیس بسیار سازمان یافته دارد و وابستگی کد آن صفر است. علاوه بر این، یک گردشکار (workflow) توسعه واضح با مسیرهای جریان داده (data flow) و وابستگی‌های از پیش تعریف شده دارد که همه این‌ها به مقیاس پذیری آن کمک می‌کنند.قابلیت تست و اشکال زداییپایبندی بسیار به اصل تک مسئولیتی (Single Responsibility Principle) با داشتن یک عملکرد واحد در هر کلاس منجر به داشتن کلاس‌های سبک می‌شود که منجر به تست‌پذیری آسان‌تر می‌شود.در پورتو، هر کامپوننت انتظار یک نوع ورودی و خروجی یکسان را دارد که تست کردن، ماک کردن و اشکال‌زدایی را ساده می‌کند.ساختار پورتو خود باعث می‌شود نوشتن تست‌های خودکار فرآیندی روان باشد. هر کانتینر دارای یک پوشه tests در ریشه خود است که حاوی یونیت تست‌هایی برای تسک‌های خود باشد. علاوه بر این، هر پوشه UI دارای یک پوشه tests است که حاوی فانکشنال تست‌ها است (برای آزمایش هر UI به طور جداگانه).کلید آسان کردن تست و اشکال زدایی، تنها در سازماندهی تست‌ها و مسئولیت از پیش تعریف شده اجزا نیست، بلکه در جداسازی کد شما نیز هست.سازگاری و تکامل‌پذیریپورتو امکان تطبیق آسان تغییرات آینده را با حداقل تلاش فراهم می کند.به عنوان مثال، فرض کنید یک برنامه وب دارید که HTML خاصی را ارائه می‌دهد و تصمیم می‌گیرید که به یک اپلیکیشن تلفن همراه با API نیز نیاز دارید. رابط کاربری قابل اتصال پورتو (WEB، API و CLI) شما را قادر می‌سازد ابتدا بیزنس لاجیک اپلیکیشن خود را بنویسید و سپس یک UI برای تعامل با کد خود پیاده‌سازی کنید. این قابلیت به شما انعطاف‌پذیری می‌دهد تا رابط‌ها مورد نیاز خود را اضافه کنید و به راحتی با تغییرات آینده سازگار شوید.دلیل اینکه این امکان وجود دارد این است که اکشن‌ها اصل سازماندهی مرکزی هستند، نه کنترلرها، و می‌توانند در چندین UI به اشتراک گذاشته شوند. علاوه بر این، رابط‌های کاربری از بیزنس لاجیک اپلیکیشن جدا شده و در هر کانتینر از یکدیگر جدا می‌شوند.قابلیت استفاده و یادگیریپورتو سهولت استفاده و قابل فهم بودن را در اولویت قرار می‌دهد. پیاده‌سازی زبان تخصصی دامنه هنگام نام‌گذاری کلاس‌ها و پیروی از قانون تک فانکشنی در هر کلاس، امکان مکان‌یابی سریع هر فیچر یا عملکرد را فراهم می‌کند. این بدان معنی است که شما به راحتی می توانید هر مورد استفاده (اکشن) را در کد خود به سادگی با مرور فایل ها پیدا کنید.پورتو تضمین می‌کند که می‌توانید هر فیچر را در کمتر از 3 ثانیه پیدا کنید. به عنوان مثال، اگر به دنبال مکان‌هایی هستید که آدرس‌های کاربر در حال اعتبارسنجی هستند، کافیست سری به کانتینر ‌Adress بزنید، لیست اکشن‌ها را باز کنید و ValidateUserAddressAction را جستجو کنید.توسعه پذیری و انعطاف پذیریپورتو رشد آینده را در نظر می‌گیرد و تضمین می‌کند که کد شما بدون توجه به اینکه پروژه چقدر بزرگ می‌شود قابل نگهداری است. ساختار ماژولار، جداسازی کانسرن‌ها، و کوپلینگ سازمان‌یافته بین کلاس‌های داخلی (&quot;کامپوننت‌ها&quot;) اجازه می‌دهد تا تغییرات بدون عوارض جانبی نامطلوب انجام شود.علاوه بر این، توسعه‌پذیری و انعطاف‌پذیری پورتو امکان ادغام آسان با ابزارها و تکنولوژی‌های دیگر را فراهم می‌کند. ساختار ماژولار آن افزودن قابلیت‌های جدید را بدون تأثیرگذاری بر روی کد موجود امکان‌پذیر می‌سازد و مقیاس‌پذیری پروژه را در صورت نیاز آسان می‌کند. این بدان معنی است که پورتو نه تنها یک انتخاب عالی برای پروژه‌های فعلی است، بلکه برای پروژه‌هایی که ممکن است در آینده به فیچرها یا ادغام‌های اضافی نیاز داشته باشند نیز انتخاب خوبی است. انعطاف پذیری ارائه شده توسط پورتو همچنین امکان سفارشی‌سازی آسان کدبیس را برای مطابقت با نیازهای خاص پروژه فراهم می‌کند. این باعث می‌شود آن را به یک انتخاب همه کاره برای طیف گسترده‌ای از نیازهای توسعه تبدیل کند.چابکی و قابلیت آپگریدپورتو حرکت سریع و آسان در فرآیند توسعه را امکان‌پذیر می‌کند.ارتقاء چارچوب به دلیل جدایی کامل بین اپلیکیشن و کد فریمورک از طریق لایه شیپ ساده است.علاوه بر این، رابط کاربری قابل اتصال پورتو، افزودن یا حذف اینترفیس‌ها را آسان می‌کند، و ساختار ماژولار آن، اضافه کردن ویژگی‌های جدید یا اصلاح فیچرهای موجود را بدون ایجاد تأثیر منفی بر سایر بخش‌های کدبیس امکان‌پذیر می‌سازد. این چابکی و قابلیت ارتقا، پورتو را به گزینه‌ای عالی برای پروژه‌هایی تبدیل می‌کند که نیاز به انعطاف‌پذیری و سازگاری با تغییرات آینده دارند.پیاده‌سازی‌ها (توسط پورتو)لیست پیاده‌سازی‌های معماری پورتو را در ادامه می‌توانید مشاهده کنید.برای زبان PHP در ۳ فریمورک لاراول، زند و سیمفونی پیاده‌سازی شده است:لاراول: اِپیاتو (توسط خالق پورتو) - یک فریمورک PHP برای ساخت APIهای مقیاس‌پذیر برو روی لاراولزند اکسپرسیو: اکسپرسیو پورتوسیمفونی: سیمفونی پورتوبرای زبان پایتون در حال حاضر تنها در فریمورک جنگو پیاده سازی شده است:جنگو: پایپورتو</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Thu, 05 Oct 2023 14:45:34 +0330</pubDate>
            </item>
                    <item>
                <title>مسیر ۱۰ ماهه توسعه پروژه</title>
                <link>https://virgool.io/@pakzad/development-journey-project-10-months-bdpsbokx3vyy</link>
                <description>وقتی سال گذشته به تیم Levannei پیوستم، با پروژه ای روبرو شدم که از لاراول و ووکامرس به عنوان هسته استفاده می‌کرد.با توجه به حجم پروژه، ما به یک چارچوب مدیریت پروژه نیاز داشتیم، معمولاً وقتی کسی را برای انجام کاری ندارم، سعی می‌کنم تا حد امکان کارها رو خودم هندل کنم، بنابراین به سرعت شروع به نصب جیرا و گیت لب کردم و تا مالک محصول، اسکرام مستر، دوآپس و QA به تیم ملحق شوند، من خودم کارهای مربوطه را انجام دادم و توسعه پروژه را بر اساس روش اسکرام ادامه دادیم.پروژه مستقیماً روی کنترل پنل cPanel و سیستم عامل CentOS بود، ما سیستم عامل را به اوبونتو تغییر دادیم. پروژه‌ها (لاراول و وردپرس) را داکرایز کردم و لاراول را از نسخه 5.7 به 10 ارتقا دادم و دیگر نیازی به cPanel نداشتیم.با توجه به جامعه هدف بزرگ ما، وردپرس گزینه مناسبی برای میزبانی پروژه نبود و حذف وردپرس کار آسانی نبود.با توجه به ددلاین مناسب و توانایی تیم فنی پروژه و تایید مدیرعامل، فروشگاه (که تقریباً تمام امکانات ارائه شده توسط ووکامرس و حتی بیشتر را شامل می‌شد و خودم قبلاً آن را توسعه داده بودم) جایگزین وردپرس شد و دو دیتابیس نیز با هم ادغام شدند.برای همه تیبل‌ها مایگریشن نوشتیم و بهینه سازی دیتابیس را شروع کردیم، بنابراین حدود ۲۰۰ تیبل دیتابیس به ۱۳۰ تیبل کاهش یافت و حجم پروژه از حدود ۲ گیگابایت به ۳۰۰ مگابایت کاهش یافت، اما همچنان مشکلات وجود داشت، مثلاً ما 6 پنل داریم. شامل دو پنل مدیریت، دو پنل کاربری، پنل کارمند و پنل شرکتی برای آژانس طراحی!پس از بررسی دقیق، متوجه شدم که پروژه اصلی توسعه یافته توسط شرکت طراح دارای مشکلاتی مانند عدم رعایت استانداردها بوده است، مثلا تمام HTTP Verbهای پروژه یا get یا post هستند. باگ‌های مختلفی که در سیستم وجود داشت و از همه بدتر یک کاربر مخفی (با استفاده از scope) وجود داشت که در کوئری‌ها نمایش داده نمی‌شد و از طریق پنل ویژه آژانس طراحی به اطلاعات کامل وب سایت دسترسی پیدا می‌کرد.ما پروژه فروشگاه را در پروژه لاراول آژانس طراحی ادغام کرده بودیم، اما تقریباً بخش بزرگی از ویژگی‌های ارائه شده توسط پروژه قبلی، از قبل در پروژه فروشگاه وجود داشتند و قسمت کوچکی باید منتقل می‌شد. بنابراین در فاز بعدی پروژه لاراول را که مشکلات زیادی داشت را در یک ریپازیتوری دیگر ادغام کردیم و تمامی ویژگی‌های آن را به پروژه جدیدمان منتقل کردیم. پروژه سبک‌تر و تیبل‌ها بهینه‌تر شدند.کل تیم فنی از اوبونتو به عنوان سیستم عامل استفاده می‌کردند. ما ۳ استیج dev و sit و prod را تعریف کردیم و  CI/CD را راه اندازی کردیم.بدهی‌های فنی زیادی بود که باید رفع می‌شد، مثلاً پروژه خیلی بزرگ بود و داکیومنت نداشتیم و گاهی تغییر یک قسمت روی قسمت دیگر تأثیر می‌گذاشت. بنابراین یک نفر به عنوان مسئول حل بدهی فنی انتخاب شد، اولین مسئولیت او تهیه داکیومنت برای دیتابیس، فرآیندها و ... بود.در همان زمان برای کل پروژه یونیت تست نوشت و ددلاین ۱ ماهه برای اینکار گذاشتم، بعد از نوشتن چندین نمونه یونیت تست برای وی و آموزش دادن، آن نمونه تست‌ها به وی کمک کرد تا بتواند تست نویسی را آغاز کند و ما به آنچه که قبل از آن در نظر داشتیم رسیدیم. اکثر اشکالات سیستم را با نوشتن تست یافته و رفع کردیم. همچنین در حال حاضر بیش از ۱۰۰ صفحه مدارک فنی داریم.اکنون همه توسعه دهندگان باید تست بنویسند و نوشتن فیچر تست‌های نیز شروع شده است و ما PhpDoc را تقریبا برای همه متدها نوشتیم. در حال حاضر، ما به TDD سوئیچ کرده‌ایم.حالا نوبت تغییر دیتابیس به PostgreSQL بود، همزمان دو پروژه پنل مدیریت و فروشگاه را با Next.js شروع کردیم. بنابراین ما مجبور شدیم معماری را تغییر دهیم و یک معماری جدید طراحی کردیم که از چندین لایه مختلف برای رسیدگی به ریکوئست‌های مربوط به تقسیم وظایف استفاده می‌کرد که ایده آن تا حدی از معماری پورتو الهام گرفته شده است. در پستی دیگر در مورد آن بیشتر خواهم نوشت.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Tue, 03 Oct 2023 23:56:13 +0330</pubDate>
            </item>
                    <item>
                <title>دختری که رهایش کردی</title>
                <link>https://virgool.io/@pakzad/the-girl-you-left-behind-rbgn6wzqjjrz</link>
                <description>جسارت، شجاعت و جنگیدن ارزش هایی هستند که نویسنده به زیبایی به تصویر کشیده است.انجام کار اشتباه فقط برای اولین‌بار سخته، بعدش دیگه عادی می‌شه.ادامه‌دادن خودش یه عمل قهرمانانه‌ست.کتاب دختری که رهایش کردی اثری از جوجو مویز است. داستان کتاب درباره دو نسل است که با یک نقاشی به هم ارتباط پیدا می‌کنند. داستان با زندگی زوجی در زمان جنگ جهانی اول شروع می‌شود، ادوارد لفیور نقاشی است که به جنگ اعزام شده و همسرش سوفی لفیور در زمان اشغال فرانسه به دست نازی‌ها باید از خانواده‌اش محافظت کند. ادوارد نقاشی سوفی را با نام دختری که رهایش کردی کشیده و از خود به جا گذاشته است.کتاب دختری که رهایش کردی اثر: جوجو مویزنوشته روی جلد به نقل از دیلی میل: &quot;کتابی که نمی توانید زمین بگذارید.&quot;روز و شب به تو فکر می‌کنم. تو ستاره راهنمای من در اين جهان ديوانه هستی.قبل از تو هيچ وقت خوشبختی واقعی را نمی‌شناختم.در این میان افسری به سوفی و نقاشی علاقمند می‌شود. این فرمانده آلمانی به سوفی و خواهرش می‌گوید که سربازان هر روز برای خوردن غذا به هتل خانوادگی آنها می‌آیند.در بخش دوم ماشین زمان را سوار شده و به سال 2006 می رویم جایی که لیو هالستون نقش اصلی است و این نقاشی را در ماه عسل از شوهرش هدیه گرفته است. لیو بعد از مرگ شوهرش با مردی به نام پل آشنا شده و وارد رابطه‌ای عاشقانه می‌شود.همیشه فکر می‌کنم توانایی پول درآوردن برای امرار معاش از طریق انجام کاری که آدم دوست داره و دلش می‌خواد، می‌تونه بزرگ‌ترین هدیه‌ی زندگی به آدم باشه.فضاسازی و حس نوستالژیک فصل اول برای ما چاره‌ای به جز امتیاز 5 از 5 باقی نمی‌گذارد، اما شروع فصل دوم شاید کمی شما را مجاب به کنار گذاشتن کتاب کند، اگر دوام بیاورید و چند صفحه مهمان کتاب باشید قطعا با گذر زمان با شخصیت‌ها آشنا شده و دوباره با همان جذابیت کتاب را دنبال خواهید کرد.تو ستاره‌ی منی تو این دنیای دیوونه.لیو باید برای نگهداشتن این تابلو و اثبات اینکه تابلوی دختری که رهایش کردی به سرقت نرفته تلاش بسیاری می‌کند، پل مسئولیت اثبات این ادعا را به عهده دارد ولی علاقه زیاد پل به لیو در دقایق پایانی نتیجه رای دادگاه را تغییر می‌دهد.تنها چیزی‌که توی این دنیا ارزش داره اینه که آدم عاشق کیه.لبخندش همون لبخنده و چشم‌هاش پُر از عشقه.خدایا! دارم شوخی می‌کنم. تو چقدر ساده‌ای! خیلی زود می‌شه گولت زد.نظر شما درباره کتاب دختری که رهایش کردی چیست؟</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Wed, 13 Jul 2022 22:06:02 +0430</pubDate>
            </item>
                    <item>
                <title>چگونه دوره آموزشی ضبط کنیم؟</title>
                <link>https://virgool.io/@pakzad/record-course-icyzsdqqsduz</link>
                <description>در هنگام ضبط دوره‌های آموزشی برای وب سایت باورژن، به نکاتی برخوردیم که بر خود لازم دیدیم به اشتراک بگذاریم. در آخرین دوره‌ای که زمان نگارش این مطلب ضبط کردیم یعنی دوره آموزشی رایگان لاراول سعی کردیم تمامی موارد را رعایت کنیم.نرم افزارمحیط نرم افزار Camtasiaنرم افزار Camtasia یکی از بهترین نرم افزارهای ضبط صدا و تصویر است. این نرم افزار امکانات بسیار زیادی دارد و برای کارهای مبتدی تا حرفه ای بسیار مناسب است. امکان حذف بخش‌هایی از صدا و تصویر، افزودن انواع افکت و نوشته بر روی متن و ضبط صدا بر روی تصویر پس از اتمام فیلمبرداری و حتی ترکیب چند فیلم و صدا، تنها بخشی از امکانات این نرم افزار هستند.سخت افزارمیکروفن یقه‌اینیاز به یک سیستم PC یا لپ تاپ دارید. همچنین یک میکروفن خوب حذف نویز نیز می‌تواند کیفیت بیشتری نسبت به میکروفن معمولی یا میکروفن ارائه می‌کند. مدل میکروفن به بودجه ارتباط مستقیمی دارد، میکرون می‌تواند از رنج پایین چند صد هزار تومان تا چند میلیون و بستگی به جدیت کار فراهم شود. البته توصیه می‌شود میکروفن خیلی گران تهیه نشود. یک میکروفن یقه‌ای با قیمت متوسط بهترین گزینه برای شروع کار است.اخلاق حرفه‌ایدر هنگام ضبط آموزش رعایت اصول اخلاقی، کنترل هیجان و استرس بسیار اهمیت دارد. اگر قسمتی از فیلم به هر دلیلی مشکلی وجود داشت، آن قسمت را حذف کرده و مجددا ضبط کنید. اگر در حین ضبط متوجه شدید که اشتباهی رخ داد، آن قسمت را دوباره تکرار کرده  و بخشی که مشکل دارد را حذف کنید.سعی کنید از تخریب همکاران و سایر مدرسین آن حوزه جدا خودداری کنید و صرفا تمرکز خود را بر تهیه آموزشی با کیفیت بالا بگذارید.مواردی که نیاز به آموزش دادن ندارندبسیاری از موارد واقعا نیازی به مطرح کردن آنها نیست و فقط باعث افزایش حجم و زمان دوره می‌شوند. بهترین روش از دید ما حذف اطلاعات اضافه و غیرضروری هستند، حتی اطلاعات با ارزش پایین را ارائه نکنید. مثلا در خیلی از موارد تاریخچه کاربردی ندارند، در مسائل درسی شاید همیشه نیازی به آموزش روش اثبات نباشد، حتی اگر کاری به چند روش انجام می‌شوند و 1 یا 2 روش بیش از 70% استفاده دارند، فقط همان دو روش را توضیح دهید و به روش‌های باقی مانده اشاره‌ای گذرا داشته باشید.بیان با صدایی رسا و شفافاین مورد از مهمترین نکات است که در حین ضبط باید به آن توجه شود. کیفیت صدا تا حد زیادی به میکروفن بستگی دارد ولی عدم خوردن و نوشیدن، سرفه نکردن نکات مهم دیگری هستند که باید به آنها توجه کنید. فراموش نکنید که اگر سرما خورده‌اید و صدایتان گرفته، زمان دیگری را برای ضبط انتخاب کنید. تن صدا و شفاف صحبت کردن نیز فراموش نشود.بخش بندی و فهرست گذاری مطالبتا حد امکان مطالب را با زبان ساده و حتی الامکان عامیانه بیان کنید. رسمی بودن و اتوکشیده بودن دوره‌های آموزشی تصویری باعث ایجاد شکاف بین بیننده و بیان کننده می‌شود و این شکاف باعث عدم ادامه تماشای دوره خواهد شد.موفق باشید.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Mon, 10 Aug 2020 21:03:01 +0430</pubDate>
            </item>
                    <item>
                <title>نظرسنجی: داکیومنت یا مستندات فنی می‌خوانید؟</title>
                <link>https://virgool.io/@pakzad/%D9%86%D8%B8%D8%B1%D8%B3%D9%86%D8%AC%DB%8C-%D8%AF%D8%A7%DA%A9%DB%8C%D9%88%D9%85%D9%86%D8%AA-%DB%8C%D8%A7-%D9%85%D8%B3%D8%AA%D9%86%D8%AF%D8%A7%D8%AA-%D9%81%D9%86%DB%8C-%D9%85%DB%8C%D8%AE%D9%88%D8%A7%D9%86%DB%8C%D8%AF-eqfnnw2m9typ</link>
                <description>قصد داریم به صورت جدی داکیومنت‌ها (مستندات) فریمورک‌ها و زبان‌های برنامه‌نویسی مختلف را به صورت فارسی روان ترجمه کنیم.با توجه به هزینه/زمان بالای ترجمه داکیومنت، لطفا نظرتان راجع به این موضوع را به صورت کامنت در همین پست یا به ایمیل baversion.com@gmail.com بنویسید.از همکاری شما صمیمانه سپاسگذارم. </description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Sat, 28 Dec 2019 22:58:37 +0330</pubDate>
            </item>
                    <item>
                <title>عبور از سد بی‌پولی</title>
                <link>https://virgool.io/@pakzad/%D8%B9%D8%A8%D9%88%D8%B1-%D8%A7%D8%B2-%D8%B3%D8%AF-%D8%A8%DB%8C-%D9%BE%D9%88%D9%84%DB%8C-t0rkxcrottzf</link>
                <description>آیا تا به حال به این فکر کرده‌اید که چرا حقوق کارمند به اواسط ماه نرسیده تمام می‌شود؟غذا، پوشاک، مسکن و غیره و غیره، دغدغه‌های خانواده‌های بسیاری است. خانواده‌هایی که همیشه در روزها یا هفته‌های اول ماه کفگیر حقوق‌شان به تهِ دیگ می‌خورد. اما چرا این افراد هیچگاه برای ماه بعد نیز به فکر تغییر نمی‌افتند و چاره‌ای نمی‌یابند؟Photo by Artem Beliaikin from Pexelsضرب المثلی لاتین برای رفع ناامیدی و به فکر افتادن این افراد وجود دارد که معمولا به هانیبال (Hannibal) فرمانده نظامی و سیاست‌مدار اهل کرتاژ نسبت داده می‌شود، این ضرب‌المثل در صفحه 27 کتاب هنر فروشندگی و بهره‌وری کسب‌وکار (Salesmanship and Business Efficiency) اثر جیمز سموئل (James Samuel) به انگلیسی ترجمه شده است که داستانی را بدین شکل روایت می‌کند؛ زمانی که ژنرال‌های هانیبال به او گفتند که امکان عبور از کوه‌های آلپ با فیل وجود ندارد، او پاسخ داد:یا راهی خواهم یافت، یا راهی خواهم ساخت.ﺑﺎﻳﺪ ﻗﺎﺩﺭ ﺑﺎﺷﻴﺪ ﺗﺼﻤﻴﻤﺎﺕ ﻣﻬﻢ ﺍﻗﺘﺼﺎﺩﯼ ﺯﻧﺪﮔﯽ‌ﺗﺎﻥ ﺭﺍ با چشمانی باز و به دور از ریسک بگیرید. ممکن است از خودتان بپرسید که چگونه باید بر مشکلات اقتصادی و بدهی‌ها غلبه کنم؟ آیا فروش منزل یا ماشین شخصی می‌تواند به من کمک کند؟ آیا باید به بورس وارد شوم و سهام بخرم یا به خرید و فروش ارز و طلا بپردازم؟ آیا باید شغلم را عوض کنم؟ﺗﻤﺎﻡ ﺍﻳﻦ ﺗﺼﻤﻴﻤﺎﺕ ﺭﺍ ﻣﯽ‌ﺗﻮﺍﻥ ﺑﺎ ﺩﺍﺷﺘﻦ ﻳﮏ ﺗﺤﻠﻴﻞ ﺍﻗﺘﺼﺎﺩﯼ ﺍﺯ ﺍﻭﺿﺎﻉ ﺑﻪ ﺷﮑﻞ ﺑﻬﺘﺮﯼ ﺍﺗﺨﺎﺫ ﮐﺮﺩ. هیچ تضمینی وجود ندارد که تحلیل شما درست باشد و موفق شوید اما با انجام برخی کارها و رعایت برخی اصول می‌توانید شانس موفقیت خود را افزایش دهید. شما با تصمیماتی هر چند کوچک می‌توانید زندگی خود و دیگران را تغییر دهید.سال‌ها پیش پدرم قصد داشت کارخانه‌ای را  تاسیس کند، البته میزان نقدینگی لازم برای خرید دستگاه‌ها کافی نبود، پدرم قصد داشت ملکی را بفروشد تا میزان سرمایه‌ای که برای اینکار کم داشت را تامین کند. از او پرسیدم: پدر چرا می‌خواهی ملک به این خوبی را بفروشی؟ پدرم پاسخ داد: هیچ چیز مجانی نیست، گاهی برای بدست آوردن یک چیز عالی، باید یک چیز خوب را از دست بدهی.الان که دارید این مطلب را می‌خوانید فرصت انجام کار دیگری را از دست داده‌اید، آن کار می‌تواند کاری با اهمیت کم مانند تماشای فیلم باشد یا کارهایی با ارزش مانند بودن در کنار خانواده. در بقیه موارد نیز همین مورد صادق است خود شما تصمیم می‌گیرید وقت خود را صرف انجام چه کاری کنید.به جای تماشای سریال و فیلم، وقت خود را صرف کارهای مهمتری از جمله خواندن کنید. فراموش نکنید که همیشه اولویت انجام کارها، با کارهای مهم و ضروری است با هدر دادن وقت خود برای انجام کارهای غیرمهم و غیرضروری، فرصت انجام کارهای با اولویت بالاتر را از دست خواهید داد. به عنوان مثال تماشای اخبار وقت شما را گرفته و ذهن شما را درگیر می‌کند، به جای آن تنها اخبار مرتبط با کار خود را بخوانید.Photo by qimono from Pixabayهزینه فرصتهزینه فرصت (Opportunity Cost) هزینه‌ای است که برای انتخاب خود باید بپردازید. همه ما زمانی که تصمیمی می‌گیریم، مطمئن هستیم که آن تصمیم ما بهترین انتخاب است هر چند که در آینده حتی شاید افسوس خورده و در صورت بازگشت انتخاب دیگری داشته باشیم.مثلا عده‌ای در 18 سالگی دانشگاه را انتخاب می‌کنند و عده‌ای کار آزاد را. دسته اول باید در دانشگاه هزینه خوابگاه و کتاب و غیره بدهند و دسته دوم در مدت زمان مشابهی که دسته اول به تحصیل مشغول هستند، میلیون‌ها تومان به جیب می‌زنند. در این مثال هزینه صرف شده برای تحصیل به علاوه پولی که فرد می‌توانست در مدت مشابه بدست آورد، هزینه‌فرصت است. البته محاسبه هزینه‌فرصت کمی پیچیده‌تر است. هر کدام از این افراد بسته به شرایط و موقعیت‌های مختلف ممکن است در این هزینه تغییرات بیشتری بدهند که محاسبه هزینه فرصت را پیچیده‌تر کند.مثلث ثروت، دانش و قدرتثروت، دانش و قدرت سه راس مثلثی هستند که با داشتن هر کدام می‌توان دو راس دیگر این مثلث را نیز بدست آورد. شما با داشتن ثروت قادر به کسب دانش هستید و قدرت انجام کارهایی را دارید که افراد معمولی ندارند و به طور مشابه این الگو برای دو مورد دیگر نیز پابرجا است.جرج کلاسون (George Samuel Clason) در کتاب ثروتمندترین مرد بابل (The Richest Man in Babylon) به زیبایی راهی را برای هموار شدن بدهی‌ها و مشکلات در قالب داستان بیان کرده است. آرکاد (Arkad) در این کتاب نحوه دستیابی به این موقعیت را برای دوستانش شرح می‌دهد. الگامیش (Algamish) مرد ثروتمندی که به وی راه ثروتمند شدن را نشان داد، چنین گفته بود:راز پولدار شدن این است که بخشی از درآمدت را برای خودت برداری و آن سهم تو است و حق داری که آن را نگهداری. باید کاری کنی که سکه‌ها و بچه‌های سکه‌هایت برایت کار کنند. سهم تو نباید کمتر از 10 درصد باشد، البته اگر بخواهی می‌توانی درصد بیشتری برداری، ولی کمتر نه! پس انداز مثل درخت است و سکه‌ها بذر آن، هرچه زودتر پس انداز کنی بیشتر در آسایش خواهی بود.من به عدد روز تولدم 13 درصد از درآمدم را برای خودم برمی‌دارم. اینکار باعث می‌شود حساب خرج‌و‌دخل خود را دقیق‌تر داشته باشید. بهتر است کلیه خرج‌های خود را از هم‌اکنون یادداشت کرده و ببینید خرج‌های غیرضروری شما چیست و آن‌ها را حذف کنید. خوشی‌های زودگذر را فراموش کنید به فکر تفریحات ارزشمندتری باشید.Photo by Lukas from Pexelsآرکاد در ادامه داستان گفته است که وقتی سکه‌ها زیاد شدند آن‌ها را به خشت فروشی داده است تا به شهری دیگر برود و تجارت سکه انجام دهد، اما اهالی آن شهر به وی کلک زده و سکه تقلبی داده‌اند. پس از یکسال که الگامیش دوباره آرکاد را دیده از او پرسیده که با پولش چه کرده است و آیا سهم خود را برداشته است. آرکاد در پاسخ او، داستان را برایش تعریف می‌کند. الگامیش عصبانی شده و فریاد می‌زند: ای احمق، سپس به وی نصیحتی می‌کند که در زندگی ما بسیار می‌تواند به ما کمک کند:بر چه اساس به دانش خشت فروش اعتماد کردی؟ مگر از نانوا درباره ستاره‌ها می‌پرسی؟ مقصر نابودی ثروتت فقط و فقط خودت هستی. از کسانی مشورت بگیر که شایستگی دارند و متخصص آن رشته هستند.از این نصیحت الگامیش نتیجه می‌گیریم در هر زمینه‌ای که قصد داریم کسب‌وکاری را شروع کنیم، باید با تحقیق و مشورت کردن با متخصصان آن کسب‌وکار وارد شویم، نه بر اساس تحلیل‌های نادرست و به اصلاح آبکی دیگران. در همین زمینه قبلا پست زیر را منتشر کرده‌ام. https://virgool.io/@pakzad/%D8%AA%D9%82%D9%84%DB%8C%D8%AF-%DA%A9%D8%B3%D8%A8-%D9%88-%DA%A9%D8%A7%D8%B1-ik2rk6ijol81 و اما ادامه داستان؛ دو سال بعد که الگامیش به دیدن آرکاد می‌آید از وی می‌پرسد که با سود پس‌انداز خود چه کرده که آرکاد پاسخ می‌دهد که آن را خرج کرده است. الگامیش می‌خندد و دوباره به او نصیحتی می‌کند:باید با سکه‌هایت برای خودت لشکری از برده‌ها درست کنی تا برایت کار کنند. بچه‌های سکه‌هایت را نیز باید به این لشکر اضافه کنی. تنها زمانی از انباشته‌هایت استفاده کن که به اندازه کافی زیاد شده باشند.منظور الگامیس از اصلاح بچه‌های سکه‌ها، سکه‌هایی بوده که از سکه‌های اولیه بدست می‌آید. در این کتاب مطالب بسیار ارزشمندی وجود دارد. نباید بدهکاری ایجاد کنید. سعی کنید هر ماه که حقوق خود را دریافت کردید 20 درصد آن را برای پرداخت بدهی‌ها و 10 درصد را برای پس‌انداز بردارید. فراموش نکنید که پول خوش‌بختی نمی‌آورد، اما بی‌پولی بدبدختی را به همراه دارد. باید با پس‌انداز آینده خود را تضمین کنید. به قول وارن بافِت (Warren Edward Buffett) کارآفرین و سرمایه‌گذار معروف آمریکایی:اگر فردی امروز در سایه نشسته است؛ به دلیل این است که یک فرد مدت‌ها پیش درختی کاشته است.زندگی‌نامه افراد ثروتمند و موفق را مطالعه کنید و عادت‌های آن‌ها را یاد بگیرید. یکی از عادت‌های افراد ثروتمند این است که صبح زود بیدار می‌شوند.Photo by imagesthai.com from Pexelsتمرکزوقتی بیل گیتس برای اولین بار وارن بافت را ملاقات کرد، میزبان شام آن‌ها، مادر بیل گیتس بود، او از همه افرادی که دورمیز شام پرسید که مهم‌ترین عامل موفقیت در زندگی خود را بر روی یک تکه کاغذ بنویسند. گیتس و بافت هر دو با یک کلمه پاسخ داده بودند: تمرکز.اما تمرکز در کار یعنی از این شاخه به آن شاخه پریدن ممنوع! اگر کاری را شروع کردید تا آن کار را به پایان نرسانیده‌اید، سراغ کار دیگری نروید.اصلی که اکثر میلیونرهای آمریکایی همیشه در خرید و فروش رعایت می‌کنند این است که می‌گویند؛ سود در زمان خرید است نه فروش و سعی می‌کنند خرید را با قیمت بسیار پایین‌تری نسبت به قسمت اولیه نهایی کنند.7 راز پولدار شدن از کتاب ثروتمندترین مرد بابلجرج کلاسون در کتاب ثروتمندترین مرد بابل، موارد زیر را به عنوان 7 راز پولدار شدن بیان کرده است:برای رسیدن به اوج، قدم اول را (با چشمان باز و عاقلانه) بردارید.هزینه‌های خود را کنترل کنید.پس‌انداز خود را سرمایه‌گذاری کنید.از سرمایه‌گذاری‌های پرریسک دوری کنید زیرا امنیت سرمایه شما را کاهش می‌دهند. دنبال یک شبه پولدار شدن نباشید.مسکن سرمایه است، اگر خانه‌ای از خود داشته باشید. دیگر نگران پرداخت اجازه نخواهید بود.درآمدی تضمین شده برای آینده خود بسازید.اگر به دنبال یادگیری باشید و مطالعه کنید، سخاوت زمین از آن شما خواهد بود.سخن پایانیسعی کنید همه بدهی‌های خود را از بین ببرید. با ضمانت کردن برای دیگران، برای خود دردسر ایجاد نکنید. هرگز چیزی را که توان پرداخت بهای آن را ندارید نخرید. به هرکس به اندازه شناختی که از او دارید اعتماد کنید. کسب‌وکار و سرمایه‌گذاری مانند تست‌های کنکور هستند، اگر در درست بود گزینه‌ای شک داشتید، آن کار را شروع نکنید. هیچ‌گاه تسلیم نشوید و فراموش نکنید که رنگین کمان پاداش کسانی هست که تا آخرین قطره زیر باران می‌مانند.دست نیازمندان را بگیرید و به آن‌ها کمک کنید تا بتوانند در زندگی خود تغییراتی مثبت ایجاد کنند.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Sun, 18 Mar 2018 12:07:58 +0330</pubDate>
            </item>
                    <item>
                <title>شروع یک کسب‌وکار به دلیل موفقیت دیگران</title>
                <link>https://virgool.io/@pakzad/%D8%AA%D9%82%D9%84%DB%8C%D8%AF-%DA%A9%D8%B3%D8%A8-%D9%88-%DA%A9%D8%A7%D8%B1-ik2rk6ijol81</link>
                <description>یکی از استدلال‌های اشتباه افرادی که هیچ‌گاه موفق نمی‌شوند، این است که فکر/ادعا می‌کنند تا زمانی که منابع لازم وجود نداشته باشد، هیچ موفقیتی محقق نمی‌شود. تاکنون با افراد زیادی برخورد داشته‌ام که ایده‌های خود را طلایی می‌دانند و نبود سرمایه‌گذار، منابع و موقعیت‌های بد را دلیل عدم موفقیت خود و ایده‌هایشان می‌دانند.Photo by Rawpixel زمینه‌های بسیار زیادی برای راه‌اندازی یک کسب‌وکار وجود دارد. فروشگاه محصولات غذایی، کارگاه تولیدی پوشاک، کارخانجات صنعتی، تنها سه مثال از دنیای کسب‌وکار است.برخی افراد همیشه در حال حساب کردن درآمد دیگران هستند. به سوپرمارکت می‌روند تعداد افراد حاضر در فروشگاه را ضرب در عوامل مختلفی مانند 24 ساعته باز بودن، مبلغ فاکتور خرید خودشان یا سایرین می‌کنند و نتیجه می‌گیرند که پول در شکمی‌جات است. افراد زیادی را می‌شناسم که دائما در مراسم‌ها و دید و بازدیدها، این جمله یا جملاتی مشابه را تکرار می‌کنند.این افراد حتی درآمد پزشک‌ها را ضرب در زمان عمل خود یا نزدیکان‌شان کرده و به عدد بسیار بالایی می‌رسند. مثلا اگر برداشتن کیسه صفرا 20 دقیقه طول کشیده باشد و هزینه 2 میلیون پرداخت شده باشد. نتیجه می‌گیرند که دکتر هر ساعت 3 عمل انجام می‌دهد که 6 میلیون سود می‌کند و این عدد را ضرب در تعداد ساعت مشخصی در روز می‌کنند و با حقوق دانشگاه و مطب شخصی پزشک جمع می‌کنند و به عدد بالایی می‌رسند و به حقوق سایر پرسنل اتاق عمل، بیمارستان، لوازم مصرفی و هزینه‌های دیگر توجهی ندارند.حال اینکه این افراد هرگز حاضر به تجربه این‌کارها نیستند و شاید همیشه تصمیم دارند در آینده این کارها را انجام دهند. به هر حال هر کسب‌وکاری نیاز به شروع دارد. پیتر دراکر گفته است:Whenever you see a successful business, someone once made a courageous decision. به هر حال تا وقتی همان کاری را انجام دهید که همیشه انجام می‌دهید، همان چیزی را به دست خواهید آورد که همیشه به دست می‌آورید. به قول پیتر دراکر: If you want something new, you have to stop doing something old. ایده تنها چیز لازم و کافی برای موفقیت نیست، کسب‌وکارهای موفق زیادی وجود دارند که موسس یا موسس‌های آن کسب‌وکار تا مدت‌ها بعد از تاسیس آن، به کار دیگری مشغول بوده و منبع درآمد دیگری برای گذران زندگی داشته‌اند.اینکه از کارمندی خسته شده‌اید یا از مدیرها و مسئول‌های شرکت رضایت ندارید یا به دنبال افزایش درآمد هستید، دلایل قانع‌کننده و خوبی برای استعفا دادن از شرکتی که در آن مشغول هستید و شروع یک کسب‌وکار نیست.راه‌اندازی کسب‌وکار اصلا بد نیست و نباید به آن با عینک منفی‌بینی نگاه کنیم ولی تنها به صرف تخصص داشتن در زمینه‌ای نمی‌توان به موفقیت رسید. با راه‌اندازی یک کسب‌وکار، بازاریابی و ارتباط با مشتری، مسائل مالی، مدیریت نیروی انسانی و موارد بسیار زیاد دیگری وجود دارد که باید به آن‌ها توجه کرد.به طور کلی اگر در کاری مهارت و تخصص دارید و به بازار آن تسلط کافی دارید، احتمال موفقیت شما بسیار بیشتر خواهد بود تا با ضرب و تقسیم درآمد دیگران، شغل خود را تغییر دهید.</description>
                <category>مجتبی پاکزاد</category>
                <author>مجتبی پاکزاد</author>
                <pubDate>Thu, 15 Mar 2018 19:59:54 +0330</pubDate>
            </item>
            </channel>
</rss>