برنامه نویسی

شما معماری خود را اشتباه می کنید!

برای طولانی ترین زمان ، “جدایی نگرانی ها” اصل راهنمای نهایی مهندسی نرم افزار بوده است. ما بدین ترتیب موارد کد خود را بر این اساس ساختار می دهیم:

  • گروه بندی پرونده های مرتبط بر اساس مسئولیت ؛
  • منطق تقسیم بندی توسط لایه های فنی ؛
  • و گاهی اوقات حتی جدا کردن با زبان برنامه نویسی.1

الگوهای معماری محبوب مانند مدل-نمای کنترل کننده (MVC) این اصل را تا نقطه جزم اعمال و رمزگذاری کرده اند. دانشگاه ها ، بوت کامپ ها و دوره ها در هر جا این تصور را که معماری MVC همه و همه الگوهای معماری است ، آموزش دهید و ادامه دهید.

برای عادلانه بودن ، معماری MVC در واقع اغلب الگوی ذهنی صحیح برای تفکیک هر برنامه سنگین و سنگین است (یعنی ، تقریباً 99.9 ٪ از برنامه های وب2) از آنجا که جریان داده ها را از منبع (یعنی “مدل”) به رابط (یعنی “نمای”) و همچنین جهش و فعال سازی بر روی داده های گفته شده (یعنی “کنترل کننده”) رسمی می کند. این کاملاً به معنای واقعی کلمه جوهر Crud است.

اما ، آیا MVC همچنین چارچوب صحیح برای ساختار کد های کد است؟

آیا ظاهراً MVC است3 الگوی ذهنی صحیح بودن لزوماً به این معنی است که باید دایرکتوری های خود را به این ترتیب بسازیم؟

در این مقاله ، ما را کشف خواهیم کرد بهتر راهی برای ساخت یک پایگاه کد با استفاده از a معماری عمودی خرد شده به جای کلاسیک models/با views/وت controllers/ طرح

معماری های افقی خرد شده

معماری MVC نمونه ای از a است معماری افقی خرد شدهبشر در یک معماری افقی خرد شده ، تفکیک نگرانی ها مطابق با لایه های فنی قطعه قطعه می شود.

نمودار یک معماری سه لایه به صورت افقی با معماری MVC

توجه داشته باشید که لایه ها نیازی به “مدل” ، “نمایش” و “کنترل کننده” ندارند. در یک برنامه وب کامل ، ممکن است خود را به جای “مؤلفه ها” ، “نقاط پایانی” و “پایگاه داده” خرد کنید.

models/
├── feature-a.ts
├── feature-b.ts
└── feature-c.ts
controllers/
├── feature-a.ts
├── feature-b.ts
└── feature-c.ts
views/
├── feature-a.tsx
├── feature-b.tsx
└── feature-c.tsx
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بنابراین ، این ساختار پروژه چه مشکلی دارد؟

  • برای افزودن یک ویژگی جدید ، شما باید پرش بین چندین دایرکتوری – یعنی models/feature/*با controllers/feature/*وت views/feature/*بشر با گذشت زمان ، این یک است بخش از تغییر زمینه ، سرپرستی ذهنی و مراسم ناوبری!
  • اغلب بلافاصله مشخص نیست که کدام ماژول ها توسط یک ویژگی خاص استفاده می شوند. از آنجا که همه چیز به صورت افقی خرد شده است ، هر ماژول می تواند از لحاظ تئوری وارد کند هیچ ماژول از لایه زیر. این امر ردیابی و ارزیابی تأثیر تغییرات کد را دشوار می کند.
  • در نتیجه ، ماژول ها در لایه های موجود در محدوده یک ویژگی واحد تمایل به نشان دادن اتصال زیاد و انسجام کم به متوسط ​​دارند.
  • “اوه … کدام پرونده ها دوباره به کجا می روند؟” – احتمالاً شما برای 10 دقیقه گذشته ، به این فکر می کنید که پرونده های جدید را برای یک ویژگی قرار دهید.

معماری های خرد شده عمودی

حالا بیایید MVC را در کنار خود بچرخانیم – به معنای واقعی کلمه! در الف معماری عمودی خرد شده، جدایی نگرانی ها مطابق با ویژگی ها بریده می شود. ایده اصلی بودن: هر ماژول ویژگی باید فقط خودش را محصور کند پایان به پایان منطق و هیچ چیز دیگری.

نمودار یک معماری سه لایه عمودی خرد شده که در آن یک ماژول ویژگی در تمام لایه های پشته فناوری قرار دارد

در عمل ، در اینجا همان چیزی است که یک ساختار پروژه محور با ویژگی می تواند به نظر برسد:

features/
├── feature-a/
│   ├── model.ts
│   ├── controller.ts
│   └── view.tsx
├── feature-b/
│   ├── model.ts
│   ├── controller.ts
│   └── view.tsx
└── feature-c/
    ├── model.ts
    ├── controller.ts
    └── view.tsx
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

منطق اشتراکی در بین چندین ویژگی (به عنوان مثال ، مدل های پایگاه داده ، برنامه های مشترک و غیره) ممکن است در ماژول های مشترک در جای دیگر مجدداً مورد استفاده قرار گیرند. آنچه مهم است این است که منطق خاص ویژگی است خود دار وت پایان به پایانبشر

جالب اینجاست که ، الگوهای MVC حتی در یک معماری عمودی خرد شده کاملاً ناپدید نشده اند – همانطور که توسط داخلی مشهود است model.tsبا controller.tsوت view.tsx پرونده ها در داخل یک ماژول ویژگی خاص. برش متفاوت است ، اما جدایی نگرانی ها به سبک MVC در روح باقی مانده است.

بنابراین ، چه چیزی این را بهتر می کند؟

  • تمام کد مربوط به یک ویژگی خاص را می توان در یک فهرست واحد یافت. بین دایرکتوری های دور دیگر به عقب و جلو نیست!4
  • جمع آوری منطق پایان به پایان ، بار شناختی را هنگام توسعه ویژگی ها یا رفتارهای اشکال زدایی کاهش می دهد.5
  • با ساخت و ساز ، یک معماری با ویژگی محور به طور طبیعی منجر به ماژول های ویژگی بسیار مستقل می شود که دارای اتصال کم هستند (بین برش های عمودی) و انسجام زیاد (در داخل برش های عمودی).

مثال: React + Next.js

امروزه ، بیشتر چارچوب های وب تمام پشته مسیریابی را به عنوان یک ویژگی درجه یک ارائه می دهند. در Next.js ، src/app/ دایرکتوری شامل نقاط ورود برای هر مسیر است. به طور خاص ، page.tsx پرونده مؤلفه ای را که باید برای آن مسیر خاص روی صفحه ارائه شود ، صادر می کند.

حالا بیایید تصور کنیم page.tsx پرونده به عنوان یک ارکستر که فقط ماژول های ویژگی را از آن وارد می کند src/features/بشر نتیجه گیری طبیعی این است که یک ساختار پروژه به صورت عمودی تقسیم شده مستلزم تقسیم منطق برنامه به عنوان “مؤلفه های ویژگی” خود است که می تواند توسط هر مسیری وارد شود-یا هر نقطه ورود به طور کلی.

src/
├── app/
│   ├── dashboard/
│   │   ├── layout.tsx
│   │   └── page.tsx
│   └── page.tsx
├── features/
│   ├── create-order/
│   │   ├── index.tsx
│   │   ├── context.ts
│   │   ├── hooks.ts
│   │   └── actions.ts
│   └── login-form/
│       ├── index.tsx
│       ├── context.ts
│       ├── hooks.ts
│       └── actions.ts
├── database/
│   ├── index.ts
│   └── schema.ts
└── components/
    ├── card.tsx
    ├── button.tsx
    └── input.tsx
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در واقع ، ماژول های ویژگی مانند create-order وت login-form ممکن است حاوی مؤلفه های خاص ، زمینه ها ، قلاب ها و اقدامات سرور باشد.

  • به عنوان مثال ، یک مؤلفه خاص از ویژگی ها ممکن است از مشترکان وارد شود src/components/ دایرکتوری برای کارتهای مشترک ، دکمه ها و ورودی ها.
  • در همین حال ، یک عمل سرور خاص از ویژگی ها ممکن است نمایش داده های پایگاه داده را از مشترکان فراخواند src/database/ دایرکتوری

نکته اصلی این است که بدانیم چه موقع منطق مشترک را استخراج می کنیم (به عنوان مثال ، src/database/ وت src/components/) و چه موقع باید منطق خاص ویژگی را از بقیه برنامه جدا کنیم.

پایان

در هسته آن ، فراخوان عمل ساده است: به سادگی MVC را در سمت خود بچرخانید.

معماری های خرد شده به صورت عمودی ما را برای نوشتن مؤلفه های بسیار مستقل که دارای اتصال کم هستند ، تنظیم کرده است (بین برش های عمودی) و انسجام زیاد (در داخل برش های عمودی). نتیجه یک ساختار پروژه است که خواندن ، درک ، نگهداری و گسترش آن به راحتی آسان تر است.

خواندن بیشتر


  1. به عنوان مثال ، در توسعه وب ، داشتن یک اختصاصی بسیار معمول است css/ دایرکتوری برای شیوه نامه ها و الف js/ دایرکتوری برای اسکریپت ها. ↩

  2. استناد مورد نیاز است. 😅

  3. به خاطر این مقاله ، ما فرض می کنیم که این امر به طور کلی صحیح است: MVC است در واقع مدل ذهنی صحیح برای برنامه های کاربردی سنگین و سنگین. ↩

  4. مسلماً ، عقب و جلو بین زیر مکتب ها با این وجود اجتناب ناپذیر است. با این حال ، ناوبری حداقل به جای پرش بین دایرکتوری های دوردست ، حداقل در یک فهرست اصلی موجود است که این یک پیروزی در کتاب من است. ↩

  5. من فقط می توانم این کار را با تجربه شخصی خودم و همچنین شواهد حکایتی از دوستانم پشتیبان بگیرم. ↩

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا