تفکیک نگرانی ها در طراحی نرم افزار

ساخت وبلاگ

Separation of Conces in Software Design

جدایی نگرانی ها (SOC) یکی از اساسی ترین اصول در توسعه نرم افزار است.

آنقدر مهم است که 2 از 5 اصل جامد (مسئولیت واحد و تفکیک رابط) مشتقات مستقیم از این مفهوم هستند.

اصل ساده است: برنامه خود را به عنوان یک بلوک جامد ننویسید ، در عوض ، کد را به تکه هایی که قطعات ریز و درشت سیستم نهایی هستند ، تقسیم کنید که هر یک قادر به انجام یک کار ساده ساده هستند.

در این مقاله ، من در مورد استفاده از این اصل عمیق در تمام سطوح انتزاع توضیح می دهم: از کد برنامه نویسی در هر عملکرد و طراحی ماژول ها به معماری برنامه کلی ، همه برای دستیابی به ویژگی های آنچه ما یک نرم افزار کیفی می نامیم.

SOC برای توابع برنامه نویسی

اگر پایین ترین سطح (کد برنامه نویسی واقعی) را بدست آوریم ، SOC به ما دستور می دهد که از نوشتن عملکردهای پیچیده طولانی خودداری کنیم. هنگامی که عملکرد به اندازه معالجه می شود ، این پرچم قرمز است که این روش احتمالاً به طور همزمان از چیزهای زیادی مراقبت می کند.

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

SOC برای ماژول ها

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

این فرایند بسیار شبیه کاری است که ما برای کارکردها باید انجام دهیم: عملیات کمتری که دارای ارتباط کمتری هستند و ویژگی های ارائه شده در همان هدف مجزا را گروه بندی می کنند.

انسجام و اتصال

استفاده از جدایی نگرانی ها شامل دو فرآیند است: کاهش اتصال و افزایش انسجام.

انسجام اندازه گیری شباهت توسط مجموعه وظایف ، سطح جزئیات و محل است. به عنوان مثال ، توابع Drawcircle و Drawtriangle به اندازه کافی منسجم هستند که به همان ماژول مسئول نقاشی تعلق دارند و طبیعی است که این دو عملکرد را نزدیک یکدیگر در کد قرار دهید (شباهت بالا~انسجام بالا).

از طرف دیگر ، جفت شدن اندازه گیری وابستگی بخشی به بقیه سیستم است (وابستگی کم~اتصال سست).

کشش و کشش فوق الذکر می تواند توسط یک عملکرد دیگر Drawcybertruck استفاده شود. ما می توانیم وسوسه شویم که این عملکرد را در ماژول نقاشی نیز قرار دهیم ، اما Drawcyberthuck ممکن است به موتور فیزیک و حالت خارجی وابسته باشد. بنابراین این باعث می شود کل ماژول نقاشی بسیار قابل استفاده مجدد و از نزدیک با چند مؤلفه دیگر همراه باشد.

می توانید بگویید که توابع نقاشی اولیه و Crawcyberthuck متعلق به سطوح مختلف انتزاع و پیچیدگی منطق است ، بنابراین آنها باید در ماژول های مختلف زندگی کنند.

و اگر در بعضی از مواقع تصمیم بگیریم از ماژول نقاشی در یک پروژه دیگر استفاده کنیم - هیچ وابستگی به موتور فیزیک وجود نخواهد داشت ، بنابراین ما قادر خواهیم بود آن را آسان تر کنیم.

راهی سریع برای یادآوری اینکه کدام ویژگی باید افزایش یابد یا کاهش یابد:

  • جداشدن خوب است - بنابراین ما باید یک جفت سست را هدف قرار دهیم
  • کد منسجم خوب است - ما باید یک انسجام بالا را هدف قرار دهیم

نمونه خوبی از کد با انسجام بالا (پراکندگی کم) استفاده از تماس های بسته بندی به جای روش های نماینده است. کد ارسال درخواست شبکه را در نظر بگیرید:

تصور کنید که اگر urlsession یک API مبتنی بر نماینده برای انجام درخواست ها داشت: تمام پاسخ ها به یک دسته عملکرد واحد تحویل داده می شوند (پاسخ: urlresponse ، برای درخواست: urlRequest)

این امر باعث می شود شبکه سازی بسیار مستعد و خسته کننده باشد ، زیرا منطق رسیدگی به همه پاسخ ها اکنون باید با آن عملکرد گره خورده باشد.

با استفاده از API مبتنی بر تماس ، عمل و نتیجه عمل در یک مکان انجام می شود و ردیابی جریان اجرای آن بسیار آسان تر می شود.

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

فواید کوپلینگ شل و انسجام زیاد

پیروی از اصل جدایی نگرانی ها به بهبود ویژگی های بیشمار پایگاه کد کمک می کند:

  1. وضوح بهتر کددرک این موضوع که در برنامه اتفاق می افتد بسیار ساده تر است وقتی هر ماژول دارای یک API مختصر و شفاف با مجموعه ای از روش های منطقی است.
  2. قابلیت استفاده مجدد بهتر کد (اصل خشک). مزیت اصلی استفاده مجدد از کد کاهش هزینه های نگهداری است. هر زمان که نیاز به گسترش عملکرد داشته باشید یا یک اشکال را برطرف کنید - انجام این کار بسیار دردناک است وقتی مطمئن باشید که فقط در یک مکان ظاهر می شود.
  3. قابلیت آزمایش بهترماژول های مستقل با قابلیت های مناسب و جداسازی از بقیه برنامه ، نسیم برای آزمایش هستند. لازم نیست کل محیط را تنظیم کنید تا ببینید که ماژول شما چگونه کار می کند - کافی است که ماژول های واقعی همسایه را با مسخره های ساختگی یا منابع داده جعلی جایگزین کنید. به این ترتیب می توانید با تأیید فقط خروجی ، ماژول را به عنوان جعبه سیاه آزمایش کنید ، یا به عنوان جعبه سفید نیز با دیدن اینکه کدام روش ها در ماژول های متصل (BDD) فراخوانی می شوند.
  4. تکامل سریعتر پروژه. این که آیا این یک ویژگی جدید است یا به روزرسانی موجود موجود ، جداسازی ماژول ها به استفاده از مناطقی از برنامه که ممکن است تحت تأثیر تغییر قرار بگیرند ، کمک می کند ، بنابراین سرعت بخشیدن به پیشرفت را افزایش می دهد.
  5. سازماندهی همزمان توسط مهندسین چندگانه آسان تر است. آنها فقط باید در مورد اینکه کدام ماژول در حال کار هستند موافقت کنند تا اطمینان حاصل کنند که با یکدیگر تداخل ندارند. فقط به روزرسانی API یک ماژول می تواند پرچمی برای اطلاع رسانی صریح سایر توسعه دهندگان باشد ، در حالی که بیشتر تغییرات را می توان بدون توجه فوری سایر مشارکت کنندگان اضافه کرد. هنگامی که با پوشش آزمایش خوب همراه باشد ، توسعه موازی به همان اندازه کارآمد می شود که بهره وری تجمعی هر مهندس جداگانه که صرفاً کار می کند (معمولاً کندتر است).

همانطور که مشاهده می کنید ، اتصال و انسجام ویژگی هایی است که در نهایت بر راحتی کار با کد از دیدگاه برنامه نویس تأثیر می گذارد.

SOC برای طراحی سیستم

برای یک دسته از ماژول ها با مسئولیت های متمایز و هدف واضح ، ما هنوز هم باید یک استراتژی جهانی را در مورد چگونگی مراجعه به ماژول ها به یکدیگر بیان کنیم.

اگر این استراتژی را معرفی نکنیم ، ممکن است به سیستمی با روابط درهم تنیده و جریان داده های سخت ردیابی شود.

هدف اصلی طراحی سیستم تشریح مرزهای آگاهی ماژول از یکدیگر است.

هر الگوی معماری موجود این استراتژی را ارائه می دهد. به عنوان مثال ، ما مدل-کنترلر را کنترل کنیم ، می بینیم که نمای مجاز به تعامل مستقیم با مدل نیست و باید از کنترلر به عنوان واسطه استفاده کند.

به نظر من این استراتژی ها اغلب از این ایده کلی ناشی می شوند که مجاز بودن خوب نیست. به نظر من ، این منجر به راه حل های بیش از حد مهندسی شده یا برعکس سیستم هایی با جداشدگی کافی از مسئولیت ها می شود.

من تمایل دارم فکر کنم که طراحی سیستم با معیارها و انگیزه های روشن نیاز به یک رویکرد بسیار رسمی تر دارد.

ما قبلاً دیدیم که SOC ، هنگامی که به توابع و ماژول ها اعمال می شود ، همیشه منجر به استفاده مجدد ، قابل آزمایش تر و قابل استفاده تر می شود. بنابراین چرا انسجام و جفت را به عنوان آن معیارها نمی گیرید و SOC را در سطح برنامه اعمال می کنید؟

اینگونه است که ما به تفکیک ماژول ها در لایه ها می رسیم. این یک الگوی معماری مشخص نیست ، بلکه مشخصات سطح بالایی برای آن استراتژی است که من در مورد آن صحبت می کردم.

ماژول ها در لایه ها گروه بندی می شوند ، به همان روشی که ما یک ماژول را از مجموعه توابع مجزا تشکیل می دهیم.

مجموعه حاصل از ماژول ها در یک لایه بر اساس وظایف مشابه در سیستم و همان سطح انتزاع ، انسجام بالایی دارند ، در حالی که آگاهی از ارتباط و محیط بین لایه ها برای دستیابی به جفت سست بسیار محدود است.

ما نه تنها ارتباطات را محدود می کنیم - لایه هایی با مشخصات محیط بالاتر در پایین (مخازن ، مانند بسته بندی پایگاه داده یا یک سرویس شبکه) ممنوع است که مستقیماً به هر چیزی که در لایه های بالاتر (منطق تجارت یا UI) تعریف شده است ، مراجعه کنند.

بنابراین اگر فقط سرویس شبکه ای را که با پس زمینه صحبت می کند ، بگیریم ، نباید در مورد بقیه سیستم چیزی ندانیم و فقط API را برای ارسال درخواست ها ارائه دهیم.

لایه منطق کسب و کار از آن مخزن آگاه خواهد بود و از آن استفاده می کند ، اما در صورت اتصال هر UI به سیستم ، هیچ ایده ای ندارد.

لایه UI از ماژول های منطق کسب و کار آگاه است و از API آنها برای خواندن داده های به روز و اقدامات شروع می کند ، اما در عین حال ، چیزی در مورد مخزن نمی داند ، زیرا منطق تجارت زیرساخت های اساسی را از آن پنهان می کندآی تی.

به این ترتیب ما می توانیم قابلیت آزمایش ذاتی کل سیستم را تضمین کنیم ، جایی که هر لایه یا حتی نمی داند که دیگری وجود دارد یا به چنین درجه بالایی جدا می شود که به راحتی می تواند با تمسخر در آزمون ها احاطه شود.

مخزن

اگرچه جدا کردن منطق کسب و کار و UI یک حرکت استاندارد است ، اما تعجب آور است که اکثر الگوهای محبوب ما برای iOS بر اهمیت جدا کردن منطق کسب و کار از دروازه داده ها ، مانند یک لایه شبکه ، تأکید نمی کنند.

بارها و بارها دیدم که درخواست ها از طریق کنترل کننده های نمایش یا سایر ماژول های منطق کسب و کار ارسال می شوند. همین مورد با نمایش داده های پایگاه داده ، UserDefaults و سایر ذخیره های داده محلی یا از راه دور.

همانطور که ممکن است حدس بزنید ، من جفت محکم را در اینجا دوست ندارم. اما این فقط اتصال بین ماژول ها نیست ، که کم و بیش تحمل است.

ما در مورد اتصال محکم بین ورودی های الگوریتم و خود الگوریتم صحبت می کنیم. چنین کدهایی آزمایش یا تکامل تقریباً غیرممکن است.

دلایل مختلفی وجود دارد که شما نمی خواهید عملیات مستقیم خواندن را در منطق تجارت خود جاسازی کنید ، بنابراین قادر به تعویض تماس های واقعی با موارد مسخره نیستید:

  1. با اجرای یک الگوریتم ناتمام ، ممکن است به طور تصادفی داده های ارزشمند را خراب کنید
  2. دسترسی به داده های واقعی ممکن است کند باشد (اندازه پرونده های بزرگ برای منابع محلی ، سرور شبکه / تست آهسته هنگام دسترسی به منابع از راه دور)
  3. داده های خارجی ممکن است در دسترس نباشد (پایگاه داده محلی خالی است و باید از قبل جمع شود ، سرور پایین است یا قطع اتصال به اینترنت وجود دارد)
  4. پس زمینه ممکن است ناگهان قالب پاسخ را تغییر دهد وقتی انتظار ندارید

مورد دوم بدنام است. البته در یک دنیای ایده آل ، این هرگز نباید اتفاق بیفتد ، اما این اتفاق می افتد ، و بیشتر از آنچه فکر می کنید. حتی CI شما را نجات نمی دهد.

این برنامه کار را متوقف می کند و اولین کسی که مقصر شناخته می شود شما ، مهندس موبایل خواهید بود. برنامه شما شکست. و باید در اولین دقایق پس از کشف شکست ، بهانه هایی ارائه دهید و به نظر برسد.

تصور کنید مدیرعامل شرکت شما برنامه را در مورد یک رویداد مهم برای سرمایه گذاران ارائه می دهد و این اتفاق می افتد.

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

حالت نمایشی آفلاین؟به نظر می رسد کار زیادی است! اما اینطور نیست که شما از دروازه های داده جدا شده و انتزاع شوید.

هنگامی که ما یک ماژول منطق کسب و کار داریم که داده ها را از جاهای دیگر پرس و جو می کند ، باید نگرانی از دسترسی به منابع داده های خارجی را به یک ماژول جداگانه استخراج کنیم و جزئیات پرس و جو غیر ضروری را در پشت یک نمای پنهان کنیم.

اینگونه است که یک مخزن تشکیل می شود.

بیایید یک مثال ببینیمما یک ViewController داریم که لیستی از برخی موارد را بارگیری و نمایش می دهد:

اولین کاری که باید انجام شود ، معرفی پروتکل Listrepository و Refactor ViewController برای استفاده از آن است:

آشنایی با رمزارزها...
ما را در سایت آشنایی با رمزارزها دنبال می کنید

برچسب : نویسنده : بهاءالدین خرمشاهی بازدید : 48 تاريخ : دوشنبه 7 فروردين 1402 ساعت: 23:48