عنوان:

‫الگوبرداری از معماری موجود و جلوگیری از کدهای ناهمگون با GitHub Copilot


نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۵/۲۹ ۱۲:۰۶
آدرس: www.dntips.ir
یکی از رایج‌ترین خطاهای توسعه‌دهندگان، درخواست پیاده‌سازی اجزای جدید بدون اشاره به الگوهای تثبیت‌شده درون پروژه است. هنگامی که دستوری ساده مانند «Create ProductController» ارسال می‌شود، Copilot ساختار را بر اساس رایج‌ترین نمونه‌های موجود در داده‌های عمومی آموزش خود تولید می‌کند؛ خروجی این روش اغلب منجر به ناهماهنگی در معماری، نام‌گذاری‌ها و شیوه مدیریت خطاها نسبت به ساختار فعلی پروژه می‌شود.
مخزن کدهای شما حاوی یک «معماری ضمنی» است. هوش مصنوعی زمانی بیشترین بازدهی را دارد که به عنوان بازتولیدکننده این معماری هدایت شود، نه مخترع یک الگوی ساختاری جدید.

ساختار پرامپت الگوبرداری (Pattern-Based Prompting)

فرض کنید در ساختار پروژه لایه‌های زیر تعریف شده‌اند:
Controllers/
Services/
Repositories/
DTOs/
Validators/
به‌جای درخواست خام، نمونه‌های استاندارد پروژه را به عنوان الگو معرفی کرده و المان‌های کلیدی معماری را قید کنید:
کلاس ProductController را با الگوبرداری مستقیم از قراردادها و ساختار موجود در CustomerController.cs و OrderController.cs پیاده‌سازی کن. الزامات و قراردادهای تحت نظارت:
  • شیوه تزریق وابستگی (Constructor Injection / Primary Constructors)
  • فرمت نام‌گذاری اکشن‌ها و روت‌ها (Routing & Action Conventions)
  • ساختار تایپ‌های بازگشتی (استفاده یکدست از ActionResult یا TypedResults)
  • مکانیزم یکپارچه مدیریت خطا (مانند ProblemDetails یا Custom Result Types)
  • الگوی ثبت لاگ‌ها (Structured Logging و Message Templates)
  • ویژگی‌های امنیتی و احراز هویت (Authorization Attributes و Policies)
  • سبک مستندسازی (XML Documentation)

نمونه خروجی هماهنگ با قراردادهای پروژه (C# Example)

اگر کنترلرهای مرجع از Primary Constructors در C# 12+ و لاگ‌گذاری ساختاریافته پیروی کنند، Copilot کنترلر جدید را دقیقاً با همان امضا تولید خواهد کرد:
namespace MyApp.Api.Controllers;

/// <summary>
/// مدیریت عملیات و واکشی داده‌های محصولات.
/// </summary>
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[Authorize(Policy = "RequireScopeRead")]
public sealed class ProductsController(
    IProductService productService,
    ILogger<ProductsController> logger) : ControllerBase
{
    /// <summary>
    /// دریافت اطلاعات یک محصول بر اساس شناسه منحصربه‌فرد.
    /// </summary>
    [HttpGet("{id:guid}")]
    [ProducesResponseType(typeof(ProductResponseDto), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
    public async Task<ActionResult<ProductResponseDto>> GetByIdAsync(
        Guid id, 
        CancellationToken cancellationToken)
    {
        logger.LogInformation("Fetching product details for Id: {ProductId}", id);

        var result = await productService.GetByIdAsync(id, cancellationToken);
        if (result is null)
        {
            logger.LogWarning("Product with Id {ProductId} not found.", id);
            return NotFound(new ProblemDetails
            {
                Title = "Product Not Found",
                Detail = $"No product matches the identifier '{id}'.",
                Status = StatusCodes.Status404NotFound
            });
        }

        return Ok(result);
    }
}

نکات تکمیلی برای کنترل زمینه در محیط توسعه (IDE Context Control)

  • ارجاع مستقیم به فایل‌های مرجع با #file: در پنجره Copilot Chat، به جای نوشتن نام فایل‌ها در متن ساده، از متغیرهای زمینه‌ای استفاده کنید: #file:CustomerController.cs #file:ICustomerService.cs Create ProductController using these patterns
  • این کار تضمین می‌کند که کدهای الگو مستقیماً وارد پنجره کانتکست (Context Window) مدل شوند.

  • ارجاع به ساختار DTOها و Validatorها: اگر برای کنترلر به اعتبارسنجی نیاز است، فایل‌های FluentValidation موجود (مثل CustomerValidator.cs) را نیز ضمیمه کنید تا ساختار ProductValidator.cs از همان قواعد ارزیابی (مثل پیام‌های خطای سفارشی یا کدهای وضعیت) پیروی کند.

  • استفاده از اسکوپ Solution در Visual Studio: هنگام کار با کدهای بزرگ دات‌نت، باز کردن فایل‌های هم‌خانواده در تب‌های ویرایشگر یا استفاده از @workspace در VS Code به Copilot کمک می‌کند الگوهای لایه‌بندی پروژه را به درستی شناسایی کند.

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