<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های امیررضا یگانگی</title>
        <link>https://virgool.io/feed/@samirreza</link>
        <description>بیاید با شریک کردن دیگران در تجربیات و دانش خود، دنیا را به مکانی بهتر تبدیل کنیم</description>
        <language>fa</language>
        <pubDate>2026-06-10 12:53:55</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/8983/avatar/RzKMR8.png?height=120&amp;width=120</url>
            <title>امیررضا یگانگی</title>
            <link>https://virgool.io/@samirreza</link>
        </image>

                    <item>
                <title>راه‌کار‌هایی برای داشتن یک رابطه موفق</title>
                <link>https://virgool.io/@samirreza/%D8%B1%D8%A7%D9%87-%DA%A9%D8%A7%D8%B1-%D9%87%D8%A7%DB%8C%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B4%D8%AA%D9%86-%DB%8C%DA%A9-%D8%B1%D8%A7%D8%A8%D8%B7%D9%87-%D9%85%D9%88%D9%81%D9%82-qrykin2g14yf</link>
                <description>ازدواج و زندگی مشترک رویدادی است که همه ما بعد از یک دوره در زندگی شخصی و رسیدن به شرایط مشخصی، به آن فکر می‌کنیم. اما در کنار مزایای و شیرینی‌های بیشماری که در این رویداد نهفته‌ است نقاط تاریک و ترسناکی نیز وجود دارد. برای داشتن یک شروع، ادامه و پایان زیبا و آرامش بخش در این مسیر، نیاز است تا عاقلانه فکر کنیم و منطقی تصمیم بگیرم. هدف من در این مقاله این است تا مطالعات خودم رو در این حوزه با شما به اشتراک بزارم تا به این ترتیب به خودم و شما کمک کنم تا یک زندگی سالم‌تر داشته باشیم.به دلایل درست کنار هم باشیدقبل از این که بخواهیم درباره کارهایی که باید برای داشتن یک رابطه موفق انجام داد، صحبت کنیم بهتر است در مورد کارهایی که نباید انجام داد صحبت کنیم. هیچگاه به خاطر فشار دیگران و یا احساس تنهایی و بدبختی، تن به ازدواج ندهید. یادتان باشد تنها دلیل برای بودن درکنار کسی این است که از بودن در کنار او، احساس آرامش و حال خوب داشته باشید. به همین سادگی !. اگر غیر از این باشد به احتمال زیاد رابطه بعد از مدتی با شکست رو‌به‌رو می‌شود. دلایل زیر نیز همگی از مواردی است که نباید تنها به خاطر وجود آن تن به ازدواج بدهید :فشار خانواده و دوستاناحساس تنهایی و شکست داشتن و چشم انتطار بودن برای آمدن فردی که شما رو از این منجلاب نجات دهدبا هم بودن به خاطر عکس !!! چرا که عشق و رابطه همیشه در عکس‌ها زیبا و جذاب استداشتن یک رابطه شاد و پایدار برای هر دو طرف نیازمند تحسین عمیق و خالص هر یک از طرف مقابل است. عشق به تنهایی خنثی است چرا که هم می‌تواند سالم و هم ناسالم باشد، هم می‌تواند کمک‌کننده و مضر باشد. بنابراین کاملا به این بستگی دارد که هر یک از دو طرف چرا و چگونه به دیگری عشق می‌ورزند و از او از عشق می‌گیرنددرباره رابطه و عشق انتظارات واقع بینانه داشته باشیدهر روز زندگی مشترک سرشار از عشق و احساسات نیست و نخواهد بود این‌ها خرافاتی است که تنها سبب شکست می شود. اگر دو فرد با این دیدگاه وارد رابطه شوند، در اولین روزی که سختی‌ها و مشکلات به سراغشان بیاید و آن عشق و احساس سرشار اولیه دیگر نمایان نباشد، دو نفر به این نتیجه می‌رسند که رابطه تمام شده‌است و باید از آن خارج شوند. واقعیت این است که روز‌ها و هفته‌های زیادی در مسیر زندگی مشترک وجود دارد که ممکن است به خاطر مشکلات و گرفتاری‌های گوناگون، آن فضای رمانتیک اولیه وجود نداشته باشد. حتی ممکن است یک روز صبح روی تخت کنار همسرتان بیدار شوید و به خود بگویید اهههه باز من که اینجام !!!. اما این کاملا طبیعی است و بعد از عبور از مشکلات با کمک هم و در کنار هم دوباره همان عشق سرشار اولیه شما را دربر می‌گیرد و چنان همسرتان را دوست خواهید داشت که فکر می‌کنید قلبتان گنجایش این حجم از احساس را نداشته باشد. عشق به تنهایی تله‌ای است که سبب می‌شود تا دو نفر از اشتباهات و تفاوت‌های هم غافل شده و وارد یک زندگی مشترک شوند. این عشق سرشار و کودکانه اولیه، تنها برای چند سال باقی می‌ماند و این احساس که چشمان معشوقتان همچون ستاره‌ای است که به بهشت نور می‌دهد بعد از مدتی کنار می‌رود !!! و این موضوع برای همه رخ می‌دهد بدون استثنا. بنابراین ، پس از این زمان، باید بدانید که خود را با انسانی که واقعاً به او احترام می‌گذارید و از بودن در کنار او لذت می‌برید ، متصل کرده‌اید، در غیر این صورت اوضاع تاریک و سیاه خواهد شد. عشق واقعی تعهد به یک فرد بدون در نظر گرفتن شرایط کنونی، است. این تعهد به فردی است که شما می‌دانید قرار نیست همیشه شما را شاد کند و یا همواره تکیه‌گاه شما باشد چرا که نیاز است در زمان‌های مختلف شما او را شاد کنید و تکیه‌گاه محکمی برای او باشید. این نوع عشق بسیار محکم‌تر است. خوشبختی یعنی هر روز که از خواب بیدار می شوید تصمیم بگیرد شریک زندگیتان را دوست داشته باشید با همه خوبی‌ها، بدی‌ها و زشتی‌ها. بعضی روز‌ها نیاز است تا برای این حس مبارزه کنید اما بعضی روز‌ها شما احساس می‌کنید خوشبخت‌ترین فرد روی کره زمین هستید. اگر تنها به این دلیل وارد رابطه می‌شوید که هر روز به شما عشق بورزد و محبت کند بدانید که این یک بلیط یک طرفه به سمت یک زندگی سمی خواهد بود چرا که این امر عشق شما را شرطی می‌کند. شما همسرتان را دوست خواهید داشت به شرطی که به شما کمک کند. تا وقتی که به شما عشق بورزد به او عشق خواهید ورزید و تا وقتی که شما را خوشحال کند، او را خوشحال خواهید کرد.مهم‌ترین فاکتور در یک رابطه احترام متقابل استمهم‌ترین فاکتور برای یک رابطه موفق  نه جذابیت‌های جنسی، نه ظاهر و نه حتی اهداف و اعتقادات مشترک است. ممکن است زمان‌هایی باشد که شما حس عاشقانه‌ای به شریک خود نداشته باشید و این یک واقعیت است اما هرگز نمی‌خواهید احترام متقابل نسبت به شریک خود را از دست بدهید. اگر این احترام از دست برود دیگر باز نخواهد گشت. هر چند گفت‌و‌گو منظم، باز و صادقانه بسیار مهم است اما به یقین طرفین ممکن است زمانی با تضاد و تعارض رو‌به‌رو شوند که کاملا اجتناب‌ناپذیر است. در این زمان تنها چیزی که می‌تواند شما و شریک زندگیتان را حفظ کند احترام متقابل، اعتماد کامل به هم(گاه بیش از اعتماد به خودتان) و ایمان به این که همسرتان بهترین کاری را که از دستش برمیاید انجام می‌دهد، است. البته باید توجه داشت که شرط لازم برای رسیدن به این احترام متقابل در درجه اول احترام به خود است. اما این احترام چه مصادیقی دارد :هیچگاه درباره همسرتان پیش دوستان و خانواده بد صحبت نکنید. اگر با او مشکل دارید باید با خود او و تنها صحبت کنید نه با خانواده و دوستانباید به این مهم که شریکتان سرگرمی‌ها، علایق و چشم‌انداز‌های متفاوتی نسبت به شما دارد احترام بگذارید(ادامه دارد ...)منابعhttps://qz.com/884448/every-successful-relationship-is-successful-for-the-same-exact-reasons/https://markmanson.net/love</description>
                <category>امیررضا یگانگی</category>
                <author>امیررضا یگانگی</author>
                <pubDate>Fri, 16 Apr 2021 18:10:18 +0430</pubDate>
            </item>
                    <item>
                <title>چالش‌های معماری میکروسرویس - قسمت دوم</title>
                <link>https://virgool.io/apieco/%DA%86%D8%A7%D9%84%D8%B4%D9%87%D8%A7%DB%8C-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%85%DB%8C%DA%A9%D8%B1%D9%88%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D9%82%D8%B3%D9%85%D8%AA-%D8%AF%D9%88%D9%85-bdn0nfs32rr4</link>
                <description>در قسمت اول درباره انواع روش‌های ارتباط و تعامل میان سرویس‌ها و چالش‌های روش هم‌زمان صحبت کردیم. در این قیمت میخوایم بریم سراغ روش غیر هم‌زمان یا asynchronous.در روش غیر هم‌زمان دو سرویس برای ارتباط، نیازمند تبادل پیام با یکدیگر هستند درست مانند ارتباط شما با دوستتان از طریق نامه.ساختار کلی ارتباط از طریق پیامیک پیام به طور کلی به دو قسمت header و body تقسیم می‌شود. در قسمت header می‌توان فراداده‌های گوناگونی درباره‌ی این پیام قرار داد و در قسمت body محتوی اصلی پیام با یک چهارچوب مشخص قرار می‌گیرد که می‌تواند به فرمت متنی یا باینری باشد.پیام‌ها به سه دسته تقسیم می شوند :دستور :  سرویس A به سرویس B از طریق پیام دستور انجام کاری را می‌دهد. مانند ایجاد یک سفارش جدید یا دریافت اطلاعات یک سفارش موجود. دقت کنید که این نوع پیام ممکن است نیازمند پاسخ، توسط دریافت کننده باشد.پاسخ به دستور : پاسخ به دستور نیز می‌تواند یک پیام باشد که برحسب مورد، دریافت کننده می‌تواند عمل خاصی را انجام دهد.رویداد : این پیام گویا این است که در سمت فرستنده اتفاقی رخ داده است (مثلا تغییر در مدل‌ها).سرویس‌ها پیام‌های خود را از طریق کانال تبادل می‌کنند که درست مانند صندوق پستی خانه عمل می‌کند. کانال‌ها به دو دسته تقسیم می‌شوند :یک به یک : که یک فرستنده و تنها یک گیرنده وجود دارد. این نوع کانال برای پیاده سازی ارتباط یک به یک استفاده می‌شود.انتشار / شنود : فرستنده یک پیام را ارسال کرده و چندیدن دریافت کننده آن را دریافت می‌کنند. به طور معمول رویداد‌ها از این نوع چنل ارسال می‌شوند.دو معماری کلی برای پیاده سازی تبادل پیامبرای پیاده سازی تبادل پیام دو معماری وجود دارد : سرویس‌ها به طور مسقیم با هم پیام تبادل کنند.سرویس‌ها از طریق یک واسط یا دلال (broker) با هم به تبادل پیام بپردازند.دو معماری کلی برای پیاده سازی تبادل پیامامروزه به طور کلی معماری با واسط یا دلال ترجیه داده می‌شود اما بییاد نگاهی به معایب معماری مستقیم و بی واسط داشته‌ باشیم :مانند روش هم‌زمان، دو سرویس باید از آدرس یک‌دیگر باخبر باشند که در این صورت چالش پیدا کردن آدرس سرویس مقصد که در قسمت قبل توضیح داده شد، به‌وجود می‌آید.برای انتقال باید هر دو سرویس در دسترس باشند. که این موضوع دردسترس پذیری سیستم را کاهش می‌دهد.تضمین دریافت پیام توسط مقصد پیچیده شده و بر دوش برنامه نویس قرار می‌گیرید (معمولا broker‌ها این تضمین را به ما می‌دهند که تحت هر شرایطی پیام‌ها را به مقصد می‌رسانند)امروزه انواع گوناگونی از brokerها با ساختار‌ها و ویژگی‌های مختلف وجود دارند. همانند هر تکنولوژی دیگر، فرمول مشخصی برای انتخاب وجود ندارد و باید با توجه به نیازمندی‌ها و شناخت از broker‌ها، گزینه درست را انتخاب کرد. اما آن چه مهم است این است که می‌بایست موارد زیر را برای انتخاب در نظر گرفت.فاکتور‌های انتخاب Message Brokerزبان‌های برنامه نویس که تعامل با broker را پشتیبانی می‌کنند - استاندارد مورد استفاده (AMQP یا STOMP) - تضمین مرتب سازی پیام‌ها - ماندگاری (در صورت از کار افتادن broker پیام‌ها به شکل قابل اعتماد ذخیره می‌شوند و بعدا به طور کامل بازیابی می‌شوند یا خیر) - آیا در صورتی که دریافت کننده برای مدتی از کار بیفتد و دوباره به شبکه متصل شود، پیام‌هایی که در این مدت برای او ارسال شده به دستش می‌رسد - مقیاس پذیریچالش‌هاتضمین مرتب سازی پیام‌هافرض کنید سرویس B یک پیام برای ایحاد یک سفارش جدید به سرویس A می‌دهد. بعد از آن کاربر سفارش خود را ویرایش کرده و مجددا سرویس B پیامی برای ویرایش این سفارش به سرویس A میفرستد. بدیهی است که پیام دوم باید بعد از پیام اول پردازش شود. حال فرض کنید به منظور افزایش دسترس پذیری اپلیکیشن، چندیدن نمونه (instance) از سوریس A وجود دارد که هر کدام پیام‌ها مربوط به سفارش را از broker دریافت کرده و آن‌ها را پردازش می‌کنند. اگر فرض کنید پیام اول سرویس B به سمت نمونه شماره یک از سرویس A ارسال شود و آن نمونه به شدت سرش شلوغ باشد یا برای مدتی از کار بیفتد و پیام دوم سرویس B به نمونه دوم از سرویس A ارسال شود که اتفاقا فعلا بیکار هست، سبب می‌شود تا پیام دوم زودتر از پیام اول پردازش شود که خب با مشکل رو به‌رو می‌شویم چرا که سفارشی را می‌خواهد ویرایش کند که وجود ندارد !!!راه حلبرای حل این مشکل broker‌ها از روش تکه کردن کانال استفاده می‌کنند. به این شکل که کانال را تکه کرده و به هر نمونه از سرویس، یک تکه خاص را منتسب می‌کنند. در صورت اضافه شدن و یا حذف یک نمونه این فرایند تکه کردن بازیابی می‌شود. حال broker برای قرار دادن پیام در هر تکه از کانال از چیزی به نام shard-key استفاده می‌کند که توسط فرستنده پیام مشخص می‌شود. در مثال بالا می‌تواند شناسه سفارش به عنوان shard-key در نظر گرفت. اتفاقی که میافتد این است که broker تمامی پیام‌هایی که shard-key یکسان دارند را به سمت تنها یک تکه از کانال ارسال می‌کنند. در واقعا پیام‌هایی که shard-key یکسان دارند تنها توسط یک نمونه از سرویس پردازش می‌شوند.اداره‌ی پیام‌های تکراریدلال به طور ایده‌آل هر پیام را باید دقیقا یک بار به مقصد برساند. اما تضمین این دقیقا یک بار بسیار هزینه بر است و همین امر سبب می شود تا brokerها تضمین کنند که پیام حداقل یک بار به مقصد می‌رسد. پس این امکان وجود دارد که پیام تکراری به دست گیرنده برسد. برای حل این مشکل دو روش وجود دارد که روش اول تنها در بعضی موارد و روش دوم در همه موارد کاربرد دارد :نوشتن برنامه‌های بیخیال شونده !!!یعنی برنامه ای که هر چندبار که آن را با مقادیر مشخص فراخوانی کنیم هیچ واکنش عجیب و غریبی نمی‌دهد.پاک کردن یک پست را در نظر بگیرید اگر برنامه به نحوی نوشته شده باشد که درصورت عدم وجود پست کلا بیخیال شود و اکسپشنی ندهد این برنامه بیخیال شونده است. بدیهی است که نمی‌توان همه برنامه‌ها را به این شکل نوشت. مثلا اگر پیام ایجاد یک سفارش دوبار ارسال شود تحت هر شرایطی دو سفارش کاملا یکسان ساخته می شود.پیگیری پیام‌ها و دور انداختن پیام‌های تکراریهمان طور که قبلا گفته شد نمی‌توان همه برنامه‌ها را به نحوی نوشتن تا در صورت تکرار پیام به صورت بیخیال عمل کنند. یک روش صد درصد کارا این است که سرویس، شناسه تمامی پیام‌هایی را که پردازش می‌کند ذخیره کرده تا در صورت تکراری بودن، آن پیام را دور بیاندازد. برای این کار سرویس می‌توان از یک جدول در لایه ذخیره سازی خود استفاده نماید.ارسال تراکنشی پیام‌هاحالتی را در نظر بگیرید که سرویس دستوری را انجام می‌دهد و در اثر آن تغییراتی در مدل‌های آن صورت می‌گیرید و سرویس با انتشار یک رویداد، این تغییرات را به دیگر سرویس‌ها اعلام می‌کند. بدیهی است که عمل تغییر در مدل‌ها و انتشار پیام باید به صورت ATOMIC صورت بگیرد و اگر مدل‌ها تغییر کنند ولی پیامی ارسال نشود و یا برعکس پیام ارسال شود اما تغییر مدل‌ها با مشکل رو‌به‌رو شود، سبب ایجاد ناپایداری در اپلیکیشن خواهد شد. مثلا در فرایند ثبت سفارش، این عمل و انتشار رویداد ثبت شدن سفارش باید ATOMIC باشد چرا که در غیر این صورت ممکن است به هر دلیلی ثبت سفارش با مشکل رو‌به‌رو شود ولی چون پیام ارسال شده سرویس انبار داری این پیام را شنود کرده و از موجودی محصول به میزان موجود در سفارش کم نماید درحالی که سفارش موفق نبوده است. راه حل‌هااولین راه حل این است که از یک جدول در لایه ذخیره سازی به عنوان صف موقتی پیام‌ها استفاده نماییم و بیایم عمل تغییر در مدل‌ها و افزودن پیام در این جدول خاص را به صورت یک تراکنش دربیاوریم. اگر لایه ذخیره سازی به ما تضمین دهد که تراکنش‌ها به صورت ATOMIC اجرا می‌شود، خیال ما دیگر راحت خواهد بود و کار را به دوش او خواهیم سپرد. پس تنها کافی است برنامه‌ای بنویسیم تا این صف موقتی را به صورت دوره‌ای خوانده و پیام‌ها آن را به broker تحویل دهد.راه حل اول را امکانات لایه ذخیره سازی محدود می‌کند. همچنین خواندن دوره‌ای صف موقتی پیام تاثیرات منفی در کارایی لایه ذخیره سازی، در مقیاس‌های بزرگ خواهد داشت. یک راه حال پیچیده ولی ماهرانه استفاده از لاگ‌های لایه ذخیره سازی است. هر عملیات موفق توسط لایه ذخیره سازی، منجر به ثبت یک رکورد در فایل لاگ مربوط به آن می‌شود. و درنتیجه شما با خواندن این فایل می‌توانید فرایند ارسال پیام را انجام دهید. این روش به دلیل نیازمندیی به کار با APIهای سطح پایین لایه ذخیره سازی، کاری نسبتا سخت است به همین دلیل چهارچوب‌های آماده ای برای این کار وجود دارد به طور مثال می‌توان از Debezium نام برد.افزایش دسترس پذیرییک نکته بسایر مهم در معماری میکروسرویس این است که شیوه ارتباط سرویس‌ها نباید دسترس پذیری اپلیکیشن را کاهش دهد. دسترس پذیری در صورتی کاهش پیدا می‌کند که یک سرویس تنها در صورتی بتواند به کلاینت خود پاسخ دهد که پاسخی از سرویس یا سرویس‌های دیگر دریافت کند. همان طور که میبینید این امر هم در ارتباط هم‌زمان و هم در ارتباط غیر هم‌زمان می‌تواند رخ دهد. برای مثال سرویس سفارش در عملیات ثبت سفارش اگر منتظر اعتبار سنجی مشتری توسط سرویس دیگری بماند این امر دسترس پذیری را تحت تاثیر قرار می‌دهد حال ارتباط این دو سرویس هم‌زمان و یا غیر هم‌زمان باشد.راه حالیک راه حل این است که سرویس یک کپی از داده‌های دیگر سرویس‌ها داشته باشد و آن را بررسی نماید و دیگر منتظر سرویس دیگری نباشد. مثلا در مثال بالا سرویس سفارش یک کپی از داده‌های مشتریان داشته باشد و برای ثبت سفارش آن را بررسی نماید. چالشی که به وجود می‌آید به روزرسانی این داده‌های کپی است که برای این کار سرویس می‌تواند به رویداد‌های منتشر شده توسط سرویس‌ای که داده کپی آن را دارد، گوش فرادهد و در صورت اتشار یک پیام مثلا درج یک مشتری جدید، داده‌ کپی خود را بروزرسانی نماید. مشکلی که ایجاد می‌شود این است که اگر حجم این داده‌های کپی افزایش یابد و یا نرخ تغییرات آن زیاد شود آنگاه نگه داری آن برای سرویس بسیار هزینه‌بر خواهد بود و صرفه‌ای نخواهد داشت.راه حل دیگری که وجود دارد این است که سرویس صرفا با استفاده از داده‌های خود درخواست را اعتبار سنجی نماید و اگر موفق بود عملیات مروبط به خود را انجام دهد و پاسخ را به کلاینت بفرستد یعنی قبل از پردازش کامل، پاسخ به کلاینت ارسال می‌شود بدیهی است که در این صورت پاسخ ۱۰۰ درصد نهایی و قابل اعتماد نخواهد بود. شاید گنگ به نظر برسد بیاید با یک مثال آن را بررسی نماییم. در مورد مثال بالا فرض کنید سرویس سفارش بعد از اعتبار سنجی سفارش توسط داده های خود سفارش را در وضعیت منتظر تایید ثبت نماید و اطلاعات سفارش را برای کلاینت ارسال نماید و همچنین با انتشار رویدادی ثبت سفارش را به سرویس مشتریان اعلام نماید تا آن هم کار خود را انجام دهد و هرگاه پیامی از سرویس مشتریان مبنی بر اعتبار سنجی مشتری برای این سفارش خاص دریافت کرد، وضعیت سفارش را به روز نماید. این کار سبب می‌شود که درصورتی که حتی سرویس مشتریان در دسترس نباشد نیز فرایند ثبت سفارش انجام شود. اما پیچیدگی‌ای در سمت کلاینت ایجاد می‌شود چرا که مشخص نیست که هنوز سفارش ۱۰۰ درصد تایید شده است یا نه و حال یا باید کلاینت به صورت دوره‌ای از سرویس سفارش بپرسد که تکلیف این سفارش چه شد و یا در صورت تعیین تکلیف سفارش، خود سرویس سفارش اعلانی به کلاینت ارسال کند.</description>
                <category>امیررضا یگانگی</category>
                <author>امیررضا یگانگی</author>
                <pubDate>Sat, 28 Mar 2020 18:05:50 +0430</pubDate>
            </item>
                    <item>
                <title>چالش‌های معماری میکروسرویس - قسمت اول</title>
                <link>https://virgool.io/@samirreza/%DA%86%D8%A7%D9%84%D8%B4%D9%87%D8%A7%DB%8C-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%85%DB%8C%DA%A9%D8%B1%D9%88%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-nju9hxzvdrqb</link>
                <description>مقدمهامروزه معماری میکروسرویس به یک معماری پرطرف‌دار برای اپلیکیش‌های بزرگ تبدیل شده و خیلی از شرکت‌ها در حال مهاجرت به سمت این معماری هستند. هدف از این سری پست‌ها بررسی چالش‌های پیاده سازی این معماری است با فرض اینکه شما تا حدودی با مفاهیم اولیه این معماری آشنا هستید و از همه مهم‌تر با تحلیل و بررسی به این نتیجه رسیدید که این معماری می‌تواند گزینه مناسبی برای اپلیکشن شما باشد.یک تعریف بچگانه !!!اگر بخوایم یک تعریف بسیار ابتدایی از این معماری داشته باشیم، باید بگیم که در این معماری یک سری سرویس با ارتباط و تعامل با‌هم به نیازمندی‌های شما پاسخ می‌دهند شاید این تعریف اصلا تعریف خوبی نباشه مخصوصا از زاویه طراحی و معماری، اما در این تعریف یک نکته‌ وجود داره و اون هم ارتباط میان سرویس‌ها است. خب برای شروع می‌خوایم بریم سراغ چالش‌های موجود برای ارتباط و تعامل سرویس‌ها.انواع ارتباطبه طور کلی ارتباط میان سرویس‌ها رو میشه از دو زاویه مختلفی بررسی کرد. یکی از زاویه هم‌زمانی و دیگری از زاویه تعداد مخاطبین.انواع ارتباط از زاویه هم‌زمانیانواع ارتباط از زاویه هم‌زمانیارتباط میان سرویس‌ها میتونه به دو صورت هم‌زمان (Synchronous) و غیر هم‌زمان (Asynchronous) صورت بگیره. مثلا ارتباط میان دو نفر میتونه به صورت هم‌زمان و مثلا از طریق تلفن و یا به صورت غیر هم‌زمان و مثلا از طریق نامه صورت بگیره. نکته بسیار مهم در ارتباط هم‌زمان میان کلاینت و سرویس در اینجا است که کلاینت بعد از ارسال درخواست برای مدت زمانی منتظر پاسخ از طرف سرویس میمونه و حتی ممکن هست در این زمان کلاینت بلاک بشه. شاید بهترین مثال برای این نوع ارتباط همین ارتباط میان مرورگر شما با سرور ویرگول برای نمایش این پست باشه.انواع ارتباط از زاویه تعداد مخاطبینانواع ارتباط از زاویه تعداد مخاطبیناز زاویه دیگه میشه گفت درخواست میتونه توسط دقیقا یک سرویس (یک به یک) و یا توسط چندیدن سرویس (یک به چند) پردازش بشه. انتخاب نوع ارتباطشاید به نظر نرسه ولی انتخاب نوع ارتباط میان سرویس‌ها یکی از تصمیم‌های مهم هنگام طراحی و معماری است و فاکتور‌های مختلفی در این انتخاب تاثیر گذار خواهند بود. همچنین باید توجه داشت که این انتخاب میتونه طبعات مختلفی در بخش‌های دیگه داشته باشه. هدف این پست اینه که با بررسی چالش‌ها، مزایا و معایب هر کدوم از این روش‌ها، به شما در این انتخاب کمک کنه.ارتباط هم‌زمانهمین الان که شما دارید این پست رو میخونید مرروگر شما از طریق یک ارتباط هم‌زمان با سرور ویرگول، تونسته این متن رو به شما نشون بده. در این ارتباط هم‌زمان از HTTP به عنوان استاندارد و پروتکل گفت‌و‌گو استفاده شده. دقیقا همین داستان برای ارتباط سرویس‌ها هم وجود داره و اون‌ها میتونن از طریق یک ارتباط هم‌زمان مثل همین HTTP با هم صحبت کنند. البته که میشه به انواع گوناگونی و با استاندارد‌ها و پروتکل‌های مختلفی این ارتباط رو برقرار کرد مثل HTTP، gRPC و ... که هر کدوم از این استاندارد‌ها و پرتوکل‌ها مزایا و معایب خودشون رو دارند که شاید تو یه پست دیگه به تقضیل درباره اون صحبت کنیم. خب حالا بریم ببینیم ارتباط هم‌زمان چه چالش‌هایی رو میتونه برای ما داشته باشه و چه طور میشه با این چالش‌ها رو‌به‌رو شد. به طور کلی ارتباط هم‌زمان دو مشکل اساسی ایجاد میکنه : یکی از دسترس خارج شدن موقتی سوریس و دیگری پیدا کردن آدرس سرویس برای ارتباط.از دسترس خارج شدن موقتی سوریسفرض کنید سرور ویرگول خاموش شه آیا شما میتونید این پست رو بخونید ؟؟؟ مسلما نه چون کسی نیست به شما جواب بده و سرور از دسترس خارج شده. همین اتفاق میتونه برای یک سرویس به دلایل مختلفی رخ بده. فرض کنید سرویس B برای انجام کاری نیاز به ارتباط با سرویس A داره و این ارتباط به شکل هم‌زمان پیاده سازی شده. تو یه مقطعی سرویس A از دسترس خارج میشه. ای داد بی‌داد حالا چه باید کرد !!!راه حلی که برای این موضوع پیشنهاد میشه دو بخش داره، بخش اول به ما کمک میکنه تا متوجه شیم کی سرویس A دیگه جواب‌گو نیست و داره بازی درمیاره و بخش دوم به این موضوع میپردازه که حالا که سرویس A در دسترس نیست چه باید کرد.بخش اولاولا باید بگم که ممکن هست یک سرویس ۱۰۰ درصد از دسترس خارج نشده باشه ولی انقدر سرش شلوغ هست و درگیره که بهتر بیخیالش بشیم و کار بیشتر سرش نریزیم. در اینجا از دستور العمل شرکت نتفلیکس استفاده می‌کنیم :همیشه برای درخواست هامون یک time out در نظر بگریم و هیچ وقت برای همیشه منتظر پاسخ سرویس نباشیم. تا اینجوری اگر این time out به سر رسید دیگه منتظر نمونیم و بریم سراغ بخش دوم کاربرای هر سرویس که میخواد با سرویس A ارتباط داشته باشه یک حد در یک بازه زمانی برای درخواست درنظر بگیرم تا وقتی به این حد رسیدیم دیگه به سرویس A درخواست ندیم و بریم سراغ بخش دوماز روش قطع کننده استفاده کنیم. به این شکل که تعداد درخواست‌های موفق و ناموفق به سرویس A را رصد کنیم و اگر این نسبت از یک آستانه‌ی مشخص بیشتر شد، بلافاصله جلوی ارسال درخواست به سمت سرویس A رو بگیریم و به سراغ بخش دوم بریم. بدیهی است در این صورت بعد یک زمان مشخص باید این قطع کننده رو برداریم و رصد رو دوباره شروع کنیمبخش دومحالا که جوابی از سرویس نمیاد میشه کار‌های مختلفی کرد که کاملا بستگی به سناریو موجود داره. ساده‌ترین راه اینه که به کاربر بگیم موقتا سیستم از دسترس خارج شده !!!. البته میشه از روش‌هایی مثل کش کردن، استفاده از مقدار پیش فرض و یا حتی نادیده گرفتن استفاده کرد. فرض کنید میخواید اطلاعات یک سفارش رو به مشتری نشون بدید و سرویسی که مدیریت ارسال رو بر عهده داره از دسترس خارج شده خب قاعدتا میشه گفت با درصد زیادی هدف این کاربر دیدن آیتم‌های سفارش خودش و یا قیمتشون بوده و میشه اصلا قسمت وضعیت ارسال رو بش نشون نداد. همون طور که گفتم این بخش واقعا به سناریو جاری بستگی داره و نمیشه یک فرمول مشخصی برای اون داد.پیدا کردن آدرس سرویس برای ارتباطشما وقتی میخواید به دوستتون زنگ بزنید باید شمارش رو داشته باشید وگرنه بدیهی هستش که نمیتونید زنگ بزنید. دو سرویس هم که میخوان با هم ارتباط داشته باشند باید آدرس IP همدیگر رو داشته باشند تا بتونند با هم حرف بزنند. برای حل این مشکل از یک روش که مثل ۱۱۸ عمل میکنه استفاده میشه که خب جلوتر میبینید که میشه در دو لایه مختلف اون رو پیاده کرد.پیاده سازی Service Registry در لایه اپلیکیشندر این روش ما چیزی داریم به نام Service Registry که شاید بشه گفت صرفا یک جدول از آدرس IP سرویس‌های فعال در اپلیکیشن توش وجود داره. حالا سرویس B وقتی میخواد به سرویس A درخواست بده، نخست از این registry آدرس سرویس A رو میپرسه و اگر اون چیزی بش برگردوند با سرویس A ارتباط میگیره. از طرف دیگه هر سرویس که به اپلیکیشن اضافه میشه باید از طریق یک APIخودش رو به این registry معرفی کنه تا اون مشخصاتش رو ثبت کنه. registry میتونه به صورت دوره‌ای از سلامت سرویس‌ها با خبر بشه و ببینه زنده هستند یا نه !!! و اگر خدایی نکرده مرده باشند اون رو از لیست خودش پاک کنه.پیاده سازی ۱۱۸ در لایه اپلیکیشن پیاده سازی Service Registry در لایه زیرساختدر اینجا بستری که سرویس‌ها روی اون درحال اجرا هستند میتونه به ما کمک کنه. مثلا در kubernetes هنگامی که کانتینر هر کدوم از سرویس‌ها اجرا میشه اون میاد و IP سرویس رو به فهرست خودش اضافه میکنه (میبینید که دیگه نیاز نیست سرویس خودش بیاد و اینکار رو دستی انجام بده). حالا سرویس B به جای گرفتن آدرس سرویس A و ارتباط با اون میاد و درخواست خودش رو به این زیرساخت میفرسته و این زیرساخت هستش که با اطلاعاتی که داره میاد و درخواست رو به سرویس A میرسونه پس دیگه برخلاف روش قبلی سرویس‌ها با واسطه که همون زیرساخت هست با‌هم صحبت میکنند.پیاده سازی ۱۱۸ در لایه زیرساختچالش‌های معماری میکروسرویس - قسمت دوم</description>
                <category>امیررضا یگانگی</category>
                <author>امیررضا یگانگی</author>
                <pubDate>Mon, 23 Mar 2020 22:37:23 +0430</pubDate>
            </item>
                    <item>
                <title>اصول برنامه نویسی شی گرا</title>
                <link>https://virgool.io/coderlife/%D8%A7%D8%B5%D9%88%D9%84-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%B4%DB%8C-%DA%AF%D8%B1%D8%A7-idqqps2xmqjj</link>
                <description>شما هم حتما مثل من زیاد شنیدین که کد هایی که می نویسید باید مطابق اصول شی گرایی باشه و اندر مزایای شی گرایی به اندازه موهای سر من نکته و مطلب خوندید. اما شاید شما هم مثل من به محض این که تسکی رو برای انجام برمی دارید انقدر درگیر جزئیات، چگونگی پیاده سازی و … تسک می شید که به کل یادتون میره چیزی به اسم شی گرایی هم وجود داره !!!خوب حالا باید چی کار کرد : این رو اول بگم که من هم تازه اول کارم و دارم تلاش می کنم تا کد های بهتری بنویسم. با خودم فکر کردم چیکار کنم که این اصول یادم نره، به این نتیجه رسیدم که اون ها رو بنویسم تا اولا با شما به اشترک بذارم و ثانیا همیشه جلو چشمم باشه تا یادم نره و مدام این اصول رو برای خودم تکرار کنم. یادتون هم نره که شما هم می تونید تجربه های خودتون رو با ما به اشتراک بذارید تا همه ی ما به برنامه نویسان خوبی تبدیل شیم. خب مقدمه چینی بسه بریم سراغ اصل مطلب.سوالاتی که در طراحی شی گرا باید به آن ها پاسخ دهیم : سیستم باید چه کاری انجام دهد، سیستم برای چه کاربرانیتوسعه پیدا می کند و چه موجودیت هایی با آن کار می کنند، خروجی سیستم چه باید باشد و آیا سیستم نیاز هایمشخص شده در سند نیازمندی ها را تامیین می کند یا نهمقصود ما از طراحی شی گرا، تعریف و نحوه ارتباط و قرارگیری کلاس ها و اشیا می باشددر بحث ارتباط کلاس ها با هم یکی از روش ها ارث بری می باشد درحالی که کلاس ها می توانند بدون ارث بردناز هم و صرفا با ترکیب اشیا با هم در زمان اجرا به سطح انعطاف پذیر تری از ارتباط دست پیدا کنندیک دو راهی که همواره در برابر آن قرار داریم این است که یک عملیات خاص باید در قالب یک متد در کلاس قراربگیرید و یا آن عملیات بر عهده استفاده کننده از کلاس قرار داردبرنامه نویسی شی گرا و رویه ای و تقسیم مسئولیتیکی از مهم ترین تفاوت های برنامه نویسی شی گرا با برنامه نویسی رویه ای این است که در شی گرایی ما تلاشمی کنیم مسئولیت انجام تسک های گوناگون را به درون کلاس برده تا به این ترتیب هم از تکرار کد جلوگیری نماییمو هم به کلاس این اجازه را دهیم تا خود بر روی رفتارش کنترل داشته باشد و تصمیم گیری در سمت استفاده کننده ازکلاس به حداقل برسد. در مثال زیر ما می خواهیم یک سیستم برای نوشتن و خواندن از یک فایل کانفیگ را که درآن داده ها به صورت key:value قرار دارد شبیه سازی کنیم :روش رویه ای :function readParams(string $source): array
{
    $params = [];
    // read text parameters from $source
    // require the name of a source file
    // it attempts to open it, and reads each line, and looking for key/value pairs
    // it builds up an associative array as it goes
    return $params;
}

function writeParams(array $params, string $source)
{
    // write text parameters to $source
    // accepts an associative array and the path to a source file
    // it loops through the associative array, writing each key/value pair to the file 
}حال فرض کنید یک نیازمندی جدید به سیستم اضافه شده است و از این به بعد سیستم باید بتواند ساختار XML شبیه زیر را نیز پشتیبانی کند :&lt;params&gt;
    &lt;param&gt;
        &lt;key&gt;my key&lt;/key&gt;
        &lt;val&gt;my val&lt;/val&gt;
    &lt;/param&gt;
&lt;/params&gt;برای تشخیص هم باید از پسوند فایل استفاده کرد و اگر xml بود از فرمت بالا استفاده نمود. حال اینجا در دو راهیای که قبلا گفته شد قرار می گیریم، این که چک کردن پسوند در خود کلاس صورت بگیرد و یا این کار در سمت استفاده کننده از کلاس. ابتدا روش دوم را انتخاب می کنیم و توابع را به صورت زیر بازنویسی می کنیم :function readParams(string $source): array
{
    $params = [];
    if (preg_match(&quot;/\.xml$/i&quot;, $source)) {
        // read XML parameters from $source
    } else {
        // read text parameters from $source
    }
    return $params;
}
function writeParams(array $params, string $source)
{
    if (preg_match(&quot;/\.xml$/i&quot;, $source)) {
        // write XML parameters to $source
    } else {
        // write text parameters to $source
    }
}مشکلی که در این جا ایجاد می شود این است که چک کردن پسوند در دو تابع تکرار شده است و برای مثال اگرفرمت جدیدی به نیازمندی ها اضافه شود باید حواسمان باشد تا کد های مربوط به چک کردن آن فرمت جدید را درهر دو تابع اعمال کنیم (دو تابع باید با هم سینک باشند)روش شی گرا :در ابتدا یک کلاس abstract برای این کار می نویسیم :abstract class ParamHandler
{
    protected $source;
    protected $params = [];
    public function __construct(string $source)
    {
        $this-&gt;source = $source;
    }
    public function addParam(string $key, string $val)
    {
        $this-&gt;params[$key] = $val;
    }
    public function getAllParams(): array
    {
        return $this-&gt;params;
    }
    public static function getInstance(string $filename): ParamHandler
    {
        if (preg_match(&quot;/\.xml$/i&quot;, $filename)) {
            return new XmlParamHandler($filename);
        } 
        return new TextParamHandler($filename);
    }
    abstract public function write(): bool;
    abstract public function read(): bool;
}همان طور که مشاهده می کنید آرایه ای در نظر گرفته شده است که صرف نظر از فرمت نهایی، کلاس با آن کار میکند. نکته بسیار بسیار مهمی که در این کلاس وجود دارد این است که متد استاتیک getInstance درباره فرزنداناین کلاس اطلاع دارد و مشکل از جایی شروع می شود که شما بخواهید فرمت جدید دیگری را پستیبانی کنید کهبرای این منظور باید به سراغ دستکاری کلاس پدر بروید که این کار خود نقض کننده یکی از اصول مهم شی گراییبه نام Open/Close Principle هست. و در بدترین حالت اگر شما مالک این کلاس پدر نباشید و در قالب یکthird party از آن استفاده می کنید که دیگر اوضاع بسیار خراب می شود.حال به سراغ کلاس های فرزند می رویم :class XmlParamHandler extends ParamHandler
{
    public function write(): bool
    {
        // write XML
        // using $this-&gt;params
    }
    public function read(): bool
    {
        // read XML 
        // and populate $this-&gt;params
    }
}
class TextParamHandler extends ParamHandler
{
    public function write(): bool
    {
        // write text 
        // using $this-&gt;params
    }
    public function read(): bool
    {
        // read text 
        // and populate $this-&gt;params
    }
}حال استفاده کننده از کلاس می تواند با خیال راحت و بدون هیچ مسئولیت و دانش خاصی از این دو فرمت استفاده کند :$test = ParamHandler::getInstance(__DIR__ . &quot;/params.xml&quot;);
$test-&gt;addParam(&quot;key1&quot;, &quot;val1&quot;);
$test-&gt;addParam(&quot;key2&quot;, &quot;val2&quot;);
$test-&gt;addParam(&quot;key3&quot;, &quot;val3&quot;);
$test-&gt;write(); // writing in XML format
 
$test = ParamHandler::getInstance(__DIR__ . &quot;/params.txt&quot;);
$test-&gt;read(); // reading in text format
$params = $test-&gt;getAllParams();
print_r($params);نتایج برنامه نویسی شی گرا :مسئولیت : دقت داشته باشید که در روش شی گرا بر خلاف روش رویه ای تصمیم گیری برای فرمت فقط یک جاصورت می گیرد و آن هم در کلاس پدر است (Factory). استفاده فقط می داند که دارد با کلاسی از نوعParamHandler کار می کند و از بابت وجود متد هایی مانند addParam مطمئن است پس در کد شی گرا اینمسئولیت تشخیص به عهده خود کلاس قرار گرفته شده است و کاربر صرفا با یک واسط مشخص کار می کند. درروش شی گرا اضافه کردن فرمت جدید تقریبا مثل آب خوردن است.انسجام : این انتقال تصمیم گیری برای فرمت در یکجا سبب ایجاد پیوستگی شده و علاوه بر حذف تکرار کد و ایجادوابستگی در کد، اضافه کردن فرمت جدید را نیز آسان کرده و باعث می شود با کمترین میزان تغییر این اضافه کردن انجام شود.جفت شدگی : جفت شدگی در کد سبب می شود تغییر در یک قسمت از برنامه نیازمند ایجاد تغییر در دیگر قسمت هابه صورت آبشاری شود قسمت هایی که حتی ممکن است کاملا از هم مجزا باشند. در روش رویه ای ما شاهد اینجفت شدگی در تابع های writeParams و readParams بودیم چرا که هر دو یک تست واحد را بر رویپسوند فایل انجام می دادند حال اگر قرار باشد این تست تغییر کند باید در هر دو تابع این تغییر اعمال شود. حال درمثال شی گرا دیگر این جفت شدگی وجود ندارد و اگر فرمت جدید اضافه شد علاوه بر نوشتن کلاس جدیدی برای آنو ارث بردن از ParamHandler باید تنها متد getInstance نیز عوض شود و دیگر به کلاس های موجودبرای xml و text دست زده نمی شود (close for modification)در پایان دقت کنید که آن چه که ما از آن به عنوان روش رویه ای نام بردیم می تواندخیلی شیک و مجلسی در قالب یک کلاس قرار بگیرد و با افتخار بگوییم که ماطراحی شی گرا کرده ایم. پس وجود کلاس دلیلی برای طراحی شی گرا نیست.یافتن کلاس ها در سیستمیکی از روش های یافتن کلاس ها در سیستم می تواند این باشد که ما به دنبال موجودیت هایی که مابه ازای خارجیدارند گشته و بر هر کدام از آن ها یک کلاس تعریف کرده و از طریق متد ها به آن کلاس ها، کاربری اختصاصدهیم. اما اگر با این دیدگاه جلو رویم به تدریج به کلاس هایی خواهیم رسید که تعداد زیادی متد داشته و وظایف زیادیرا انجام می دهند (Single Responsibility Principle).برای مثال فرض کنید در یک سیستم فروشگاهی ما کلاسی برای محصولات داریم حال می خواهیم مکانیزمی داشتهباشیم تا اطلاعات یک محصول را به صورت خلاصه در اختیار ما قرار دهد. اولین ایده ای که به ذهن می رسد ایناست که خب متدی به نام writeSummary به کلاس اضافه کنیم. حال فرض کنید با گذشت زمان این نیاز ایجاد شدکه ما این خلاصه را در فرمت های HTML و XML ارائه دهیم خب حالا چه باید کرد !!! شاید دو راه به ذهن برسدیکی نوشتن دو متد برای این کار writeHtmlSummary و writeXmlSummary. خب ناگفته پیدا است که دراین دو متد شاهد یک عالمه تکرار کد خواهیم بود. خب به سراغ راه حل دوم برویم که این است که همان متدwriteSummary را با گذاشتن یک ساختار شرطی طوری تغییر دهیم تا بسته به شرایط یا XML بنویسد و یاHTML بنویسد (Single Responsibility Principle کجا رفت !!!). پس هر دو راه بد است و اگر قرار باشد فرمت جدید دیگری نیز اضافه شود که اوضاع بدتر هم می شود.مشکل کار اینجا است که خانه از پای بست ویران است و ما با قرار دادن writeSummmary در کلاس محصولباعث شدیم این کلاس بیش از حد کار انجام دهد. این نوشتن خلاصه خود یک وظیفه جدید است و باید برای آن کلاسجدیدی نوشته شود. پس در نوشتن کلاس ها دقت کنیم قرار نیست تمام موجودیت های قابل لمس در سیستم فقط کلاسباشند.پس همان طور که گفتیم کلاس باید یک وظیفه واحد داشته باشد به نحوی که این وظیفه تا جای ممکن یکتا و متمرکزشده باشد. می توان برای تست کردن این اصل وظایف کلاس را در قالب یک پاراگراف نوشت اگر طول اینپاراگراف بیش از ۲۵ کلمه شد، کلی اما و اگر در آن بود و جملات طولانی داشت پس می توان نتیجه گرفت کهکلاس بیش از یک وظیفه و مسئولیت داشته و باید به فکر کلاس و یا کلاس های جدیدی بود.در مثال بالا این جدا کردن ها مثل یک شمشیر دو لبه است چرا که وقتی ما کلاسیبرای WriteSummary داشته باشیم باید شی ای از کلاس Product را به آن پاسدهیم این کار اولا سبب می شود که جفت شدگی و وابستگی در سیستم افزایشیابد ثانیا دیگر در کلاس WriteSummary ما دسترسی کامل به تمامی متد ها و فیلدهای کلاس Product نداریم (اگر متد writeSummary در خود کلاس Product بود ماآنجا دسترسی کامل به همه چی داشتیم مثلا متد ها و فیلد هایprivate/protected)ارث بریهمه ما با تعریف و چگونگی کار با ارث بری آشنایی کامل داریم. در این جا قصد دارم نکات ظریفی در باره ارثبری را مطرح کنم :یکی از نشانه های نیاز به ارث بری وجود ساختار های شرطی یکسان در متد ها می باشد. مانند آن چه که در روشرویه ای نوشتن در فایل کانفیگ مشاهده کردید. اما باید توجه داشت هر ساختار شرطی دلیل بر ارث بری نیست مثلاساختار شرطی متد getInstance در کلاس ParamHandler کاملا به جا بوده و سبب ایجاد مرکزیت درتصمیم گیری می شود. ولی می توان گفت که اگر یک ساختار شرطی در دو یا چند متد عینا تکرار شد احتمال بسیارزیاد نیاز به ارث بری است.برای شروع طراحی شی گرا همیشه نگاه از بالا به پایین داشته، نخست از interface و کلاس های abstractشروع کرده و تنها به فکر نوشتن یک واسط گویا و کاربردی باشید. در این مرحله به هیچ وجه درگیر جزيیات پیادهسازی نشوید خواهید دید که اگر واسط گویا برای کلاس ها طراحی کنید می توانید به راحتی آن ها را پیاده سازیکرده و به سادگی آن ها را گسترش داده و یا با کم ترین هزینه تغییر دهید.Gang of Four : Program to an interface, not an implementationچهار نشانه برای اصلاح و تفکر بیشتر در طراحی و کد نویسیتکرار : تکرار در کد که خود سبب ایجاد جفت شدگی در کد می شود.کلاسی که بیش از حد می داند : در این صورت کلاس شما وابسته می شود به اطلاعاتی خارج از محدوده و کنترلخودش و همین امر قابلیت استفاده مجدد را از کلاس می گیرد و سبب وابستگی کلاس می شود.نقض Single Responsibility Principleوجود ساختار های شرطی یکسان که قبلا در باره آن ها صحبت کردیم.اصول SOLIDتنها یک مسئولیت : همان طور که قبلا صحبت شد هر کلاس باید یک و فقط یک مسئولیتداشته باشد. می توان این طور نیز به این اصل نگاه کرد که تنها باید یک دلیل برای تغییر کلاس وجود داشته باشد نهبیشتر. برای یافتن منشا آن دلیل می توان به استفاده کنندگان آن کلاس فکر کرد چرا که آن ها هستند که درخواستتغییر را خواهند داد. به جای غرق شدن در تعداد زیادی مخاطب و استفاده کننده، بهتر است به دنبال نقش هایی باشیمکه با کلاس کار می کنند چرا که همین نقش ها هستند که درخواست تغییر می دهند. برای فهم بیشتر می توانید بهقسمت Classic Examples در لینک Single Responsibility Principle مراجعه کنید. رعایت این اصلسبب می شود تا میزان وابستگی و جفت شدگی کلاس ها به هم کمتر و سبک تر شود. در پایان باید اشاره کرد کههیچ اصل ای ۱۰۰ درصد درست نیست بلکه باید با توجه به نیازمندی ها و سیستمی که با آن کار می کنید بهترینگزینه را انتخاب کنید و همچنین مواظب باشید تا از اون ور بوم نیفتید.بسته برای تغییر و باز برای گسترش : تمامی موجودیت های برنامه نویسی نظیر کلاس ها، متد ها و … کدشان می تواندبرای توسعه باز باشد اما باید برای اعمال تغییرات بسته بماند. آن چه که در این اصل می خواهیم به آن برسیم ایناست که در صورت ایجاد یک نیازمندی جدید در سیستم کد های موجود را تغییر نداده و صرفا با نوشتن کد های جدیدکه از کد های قدیم استفاده می کنند به آن نیاز پاسخ دهیم. این اصل ارتباط بسیار خوبی با SRP داشته و در صورترعایت هر کدام از آن ها رسیدن به دیگری بسیار ساده می باشد. در سخت ترین حالت ممکن می توان گفت هرکلاسی که با کلاس دیگر ارتباط داشته باشد و از شی ای از آن استفاده کند این اصل را نقض می کند اما باید توجهداشت که در صورتی می توان گفت که این ارتباط نقض کننده OCP است که دو کلاسی که با هم در ارتباط هستند در یک سطح از abstraction قرار نداشته باشند مثلا یک کلاس بسیار کلی و دیگری جزئی باشد. یکی از طراحیهای مناسب برای برقراری این اصل، الگو طراحی Strategy می باشد که در آن صورت می توانیم یک interface را به کلاس استفاده کننده، وابسته کنیم و دیگر خود را به کلاس های جزئی و جزئیات وابسته نکنیم وهمچنین با این کار می توانیم به راحتی سیستم را گسترش دهیم (چرا که با ایجاد یک نیاز جدید صرفا کافی است برایآن یک کلاس نوشته شود که از آن interface ارث ببرد و با این کار کلاس استفاده کننده اولیه هیچ نیازی به تغییرندارد). بار دیگر باید تاکید کرد که در استفاده از این اصل زیاده روی نکنید وگرنه در همان ابتدا کار با تعداد زیادیinterface برای هر کلاس مواجه خواهید شد.اصل جایگزینی Liskov : این اصل می گوید که اگر کاربر یک کلاس بتواند با کلاسی کار کند بایدبتواند با کلاس های فرزند آن نیز کار کند. برای توضیحات بیشتر می توانید به بخش The Classic Exampleدر لینک LSP مراجعه کنید.جدا سازی Interface ها : مطابق این اصل به جای آن که یک interface بسیار بزرگ داشتهباشید که همه کلاس هایی که آن را پیاده سازی می کنند می بایست کلی متد نامربوط را نیز پیاده سازی کنند، آنinterface را شکسته و اجازه دهید هر کلاس تنها آن چرا که به آن نیاز دارد پیاده سازی کند.قبل از اینکه به سراغ آخرین اصل برویم بگذارید اندکی درباره وابستگی صحبت کنیم. مطابق آن چه که تا کنونصحبت شد وابستگی امری غیر قابل اجتناب می باشد اما باید توجه داشت که وابستگی نباید سبب شود تا در اثر تغییردر نیازمندی ها برای اعمال آن ها کد های موجود نیز تغییر پیدا کنند بلکه طراحی باید به گونه ای باشد تا صرفا بانوشتن کد های جدید و تنها اندکی تغییر در کدهای موجود به آن نیاز پاسخ گفت. یکی از مهم ترین دلایل ایجاد اینمشکلات این است که شیوه وابستگی ما غلط است و کلاس هایی را به هم وابسته می کنیم که به لحاظ سطح جزئیاتدر یک سطح قرار ندارند مثلا یک interface را به یک کلاس concrete وابسته می کنیم. مطابق اصلDependency Inversion دو کلاس که با هم مرتبط و وابسته هستند باید در یک سطح از abstraction قرارداشته باشند نه این که یکی کلی تر و دیگری جزئی تر باشد. همان طور که حتما متوجه شده اید رعایت این اصل تاجای خوبی ما را به سمت رعایت OCP نزدیک می کند چرا که رعایت این اصل سبب ایجاد درخت های ارث بریو استفاده از interface و یا کلاس abstract می شود و بدین ترتیب با تغییر در نیازمندی ها کلاس های موجودتغییر پیدا نمی کند و تنها کلاس جدید به درخت ارث بری افزوده می شود. همچنین با رعایت این اصل و استفاده ازروش کلی که به آن اشاره شد (ارث بری) می توان تا حد خوبی به SRP نیز دست پیدا کرد. (روشی که در رعایتاین اصل مطرح است این است که کلاس استفاده کننده صرفا با یک interface کار کند و جزئیات ما در قالب کلاسهای concrete ای که آن interface را پیاده سازی می کنند پنهان شود. کلاس استفاده کننده تنها با آن واسط درارتباط بوده و دیگر درگیر جزئیات نمی شود).</description>
                <category>امیررضا یگانگی</category>
                <author>امیررضا یگانگی</author>
                <pubDate>Fri, 08 Jun 2018 22:30:50 +0430</pubDate>
            </item>
            </channel>
</rss>