Anophel-آنوفل معماری ماژولار در لاراول : بررسی کامل همراه با مثال

معماری ماژولار در لاراول : بررسی کامل همراه با مثال

انتشار:
0

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

ماژول ها چیست؟

در context لاراول، ماژول ها اجزای مستقلی هستند که عملکردهای خاص یک برنامه کاربردی را در بر می گیرند. آنها جداسازی دقیق نگرانی ها را امکان پذیر می کنند و پایگاه کد را قابل خواندن تر و قابل نگهداری تر می کنند.

برای مثال :

// Example of a simple module in Laravel
// app/Modules/ExampleModule/Controllers/ExampleController.php

namespace App\Modules\ExampleModule\Controllers;

use App\Http\Controllers\Controller;

class ExampleController extends Controller
{
    public function index()
    {
        return view('example-module::index');
    }
}

تفکیک نگرانی ها در معماری ماژولار

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


مثال:

// Separating concerns in a module
// app/Modules/ExampleModule/Models/ExampleModel.php

namespace App\Modules\ExampleModule\Models;

use Illuminate\Database\Eloquent\Model;

class ExampleModel extends Model
{
    // Model logic here
}

ساختار دایرکتوری در معماری ماژولار

سازماندهی ماژول ها در پروژه لاراول برای حفظ وضوح بسیار مهم است. یک ساختار دایرکتوری تمیز ایجاد کنید که مؤلفه‌های مدولار برنامه شما را منعکس می‌کند و به توسعه‌دهندگان کمک می‌کند تا پایگاه کد را درک کنند.


مثال:

- app
  - Modules
    - ExampleModule
      - Controllers
      - Models
      - Views

autoload در لاراول

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

مثال:

// composer.json
{
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Modules\\": "app/Modules/"
        }
    }
}

ارتباط بین ماژول ها

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


مثال:

// Broadcasting an event from one module
event(new \App\Modules\ExampleModule\Events\ExampleEvent($data));

تست و نگهداری در معماری ماژولار

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

ایجاد یک پروژه ماژولار در لاراول

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


ساختار مورد نظر من به این صورت است:

app/Modules/{Module}/
├── {Module}.php (model)
├── {Module}Controller.php
├── {Module}Policy.php
├── {Module}Request.php
├── {Module}Routes.php
├── ...
└── Tests/
    ├── {Module}Factory.php
    ├── {Module}FeatureTest.php
    ├── {Module}Seeder.php
    └── {Module}UnitTest.php

برای مورد استفاده من، seeder ها فقط در تست ها قابل استفاده هستند.


ما در این مقاله قصد ندارم متدهای Controller را پیاده سازی کنم، تمرکز این پست تغییر ساختار پوشه پیش فرض برای یک API است.


نصب لاراول

با ایجاد یک پروژه جدید شروع کنید:

composer create-project laravel/laravel laravel-modular

ما از SQLite برای این کار استفاده خواهیم کرد. که در لاراول 11 به صورت پیش فرض ایجاد می شود اگر نبود آن را ایجاد کنید:

touch database/database.sqlite

سپس env. خود را ویرایش کنیم (اگر به طور خودکار از env.example. کپی کنید)، این vars را به روز کنید:

DB_CONNECTION=sqlite
DB_HOST=database/database.sqlite

حالا بیایید یک namespace برای پوشه ماژول های خود ایجاد کنیم، composer.json خود را ویرایش کنید:

"autoload": {
  "psr-4": {
      "App\\": "app/",
+     "Modules\\": "app/Modules/",
      "Database\\Factories\\": "database/factories/",
      "Database\\Seeders\\": "database/seeders/"
  }
},

همچنین در صورت تمایل می‌توانید آن را خارج از پوشه برنامه قرار دهید، فقط کارهایی را که در اینجا انجام می‌دهیم به‌روزرسانی کنید.

هر زمان که موارد autoload کامپوزر را به روز می کنید، این دستور را اجرا کنید:

composer dump-autoload

اکنون می توانید برنامه خود را با دستور زیر اجرا کنید:

php artisan serve

ایجاد ماژول ما

اجازه دهید یک ماژول Car ایجاد کنیم:

mkdir -p app/Modules/Car/Tests
php artisan make:model --all Car

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

mv -t app/Modules/Car app/Models/Car.php app/Http/Controllers/CarController.php
 app/Http/Requests/StoreCarRequest.php app/Policies/CarPolicy.php
mv -t app/Modules/Car/Tests database/factories/CarFactory.php database/seeders/CarSeeder.php

برای این آموزش، مایگرشن را در مسیر پیش‌فرض می‌گذارم، ترجیح می‌دهم همه مایگرشن ها را به ترتیب زمانی باشد، اما در صورت تمایل می‌توانید به پوشه ماژول نیز بروید.


ما همچنین فقط به یک FormRequest برای ذخیره و به روز رسانی نیاز داریم:

rm app/Http/Requests/UpdateCarRequest.php
mv app/Modules/Car/StoreCarRequest.php app/Modules/Car/CarRequest.php
# also update class name

پس از آن، ما باید هر namespace ی را در پوشه جدید خود به‌روزرسانی کنیم، همه فایل‌های موجود در app/Modules/Car را به‌روزرسانی کنیم:

namespace Modules\Car;

و همه فایل‌های موجود در "app/Modules/Car/Tests" به:

namespace Modules\Car\Tests;

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


composer dump-autoload را اجرا کنید تا ببینید آیا فایلی از PSR-4 خاموش است یا خیر.


راه اندازی مسیرها

بیایید یک مسیر مدولار ایجاد کنیم:

touch app/Modules/Car/CarRoutes.php

و فایل را آپدیت کنید:

<?php

use Illuminate\Support\Facades\Route;
use Modules\Car\CarController;

Route::resource('cars', CarController::class);

برای اینکه کار کند ما به یک ServiceProvider نیاز داریم، یکی ایجاد کنید:

php artisan make:provider ModuleServiceProvider

و یک متد بوت برای جستجوی مسیرها در ماژول‌های ما اضافه کنید (در صورت تمایل می‌توانید همین کار را برای مایگرشن ها انجام دهید):

public function boot(): void
{
    // Can also use (**) wildcard if you have subfolders
    foreach (glob(base_path('app/Modules/*')) ?: [] as $dir) {
        $modelClassName = class_basename($dir);
        $path = Str::before($dir, "\\$modelClassName");
        $moduleRouteFile = "$path/$modelClassName" . 'Routes.php';

        if (!file_exists($moduleRouteFile)) continue;

        $this->loadRoutesFrom($moduleRouteFile);
    }
}

و آن را به config/app.php در زیر Provider اضافه کنید:

App\Providers\ModuleServiceProvider::class

اکنون می توانید مسیر خود را آزمایش کنید! باید کار کند.  دقت کنید حتما اصول سالید و کد نویسی تمیز را نیز رعایت کنید، برای آشنایی بیشتر مقاله اصول سالید در لاراول را بررسی کنید.

Seeder  و Factory ها را راه اندازی کنید

به روز رسانی مایگرشن:

Schema::create('cars', function (Blueprint $table) {
  $table->id();
  $table->string('name');
  $table->timestamps();
});

سیدر را به روز کنید:

public function run(): void
{
    Car::factory()
        ->count(10)
        ->create();
}

آن را در پایگاه داده /seeders/DatabaseSeeder.php ثبت کنید:

public function run(): void
{
    // Note the leading slash
    $this->call([
        \Modules\Car\Tests\CarSeeder::class
    ]);
}

و Factory:

protected $model = Car::class;

public function definition(): array
{
    return [
        'name' => fake()->name()
    ];
}

از protected $model  استفاده کنید، چون ما از یک ساختار فایل سفارشی استفاده می کنیم، باید آن را اعلام کنیم. ما همچنین باید یک متد register را به سرویس پروایدر های خود اضافه کنیم:

public function register(): void
{
    Factory::guessFactoryNamesUsing(function (string $modelName) {
        $modelClassName = class_basename($modelName);
        $namespace = Str::before($modelName, "\\$modelClassName");
        return "$namespace\\$modelClassName\\Tests\\$modelClassName" . 'Factory';
    });

اکنون می توانید migration و seeder را اجرا کنید:

php artisan migrate:fresh --seed

تست کردن

قسمت آخر، بیایید چند تست اضافه کنیم، اجرا کنید:

php artisan make:test CarFeatureTest
mv tests/Feature/CarFeatureTest.php app/Modules/Car/Tests/CarFeatureTest.php

فراموش نکنید که namespace ها را به روز کنید!

یک تابع به فایل تست اضافه کنید:

/** @test */
public function get_cars_should_return_success(): void
{
    $response = $this->get('/cars');
    $response->assertStatus(200);
}

به /** @test */ توجه کنید، اگر این نظر را اضافه نکنید، PHPUnit تست را پیدا نمی کند. اگر میخواهید با PEST تست نویسی را انجام دهید این مقاله را بررسی کنید.

اکنون باید phpunit.xml را به روز کنیم تا تست های خود را کشف کنیم:

<testsuites>
    <testsuite name="Unit">
-       <directory suffix="Test.php">./tests/Unit</directory>
+       <directory suffix="UnitTest.php">./app/Modules</directory>
    </testsuite>
    <testsuite name="Feature">
-       <directory suffix="Test.php">./tests/Feature</directory>
+       <directory suffix="FeatureTest.php">./app/Modules</directory>
    </testsuite>
</testsuites>

شما باید از پسوند UnitTest.php یا FeatureTest.php استفاده کنید یا phpunit.xml را برای مورد استفاده خود تغییر دهید.

اکنون می توانید تست کنید:

php artisan test

با توسعه تست محور در لاراول چقدر آشنا هستید؟ مقاله توسعه تست محور در لاراول را بررسی کنید.

معایب معماری ماژولار در لاراول

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

 

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

 

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

 

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

 

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

 

عملکرد: بسته به نحوه پیاده‌سازی ماژول‌ها، ممکن است به دلیل بارگذاری و مسیریابی پویا ماژول‌ها، یک سربار عملکرد جزئی وجود داشته باشد. با این حال، این سربار معمولاً ناچیز است و می‌توان آن را از طریق کش کردن مناسب و استراتژی‌های بهینه‌سازی کاهش داد.

 

مدیریت وابستگی: مدیریت وابستگی ها بین ماژول ها می تواند مشکل باشد. اگر ماژول‌های مختلف وابستگی‌های متناقضی داشته باشند یا به نسخه‌های متفاوتی از یک بسته نیاز داشته باشند، می‌تواند منجر به مشکلات سازگاری شود که باید حل شوند.

 

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

 

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

 

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


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

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

 علاوه بر این، استفاده از یک رویکرد ماژولار ممکن است به تنظیمات و پیکربندی اضافی نیاز داشته باشد، که می تواند زمان و تلاش مورد نیاز برای شروع یک پروژه را افزایش دهد. 

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

نتیجه

پیاده سازی معماری ماژولار در لاراول یک رویکرد ساختاریافته و مقیاس پذیر برای توسعه برنامه ارائه می دهد. با درک و به کارگیری این اصول، توسعه دهندگان می توانند برنامه های لاراول قابل نگهداری، توسعه پذیرتر و سازماندهی شده تری ایجاد کنند. همانطور که می بینید، لاراول بسیار قدرتمند است و می تواند ساختارهای سفارشی بسیار خوبی را با IMO کمی دیگ بخار اداره کند. متأسفانه دستورات *:php artisan make به درستی در ماژول ها کار نمی کنند، اما می توانید دستورات جدیدی اضافه کنید تا آن را برای شما کار کند.

#laravel#laravel_madular#madular#معماری_ماژولار#لاراول#لاراول_ماژولار
نظرات ارزشمند شما :

در حال دریافت...

مقاله های مشابه

در حال دریافت...