عنوان:

‫اصول پرامپت‌نویسی مهندسی در GitHub Copilot


نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۵/۲۹ ۱۲:۰۰
آدرس: www.dntips.ir
کیفیت خروجی GitHub Copilot نسبت مستقیمی با وضوح دستور ورودی (Prompt) دارد. ارسال درخواست‌های مبهم مانند «Create an API» هوش مصنوعی را وادار به حدس زدن می‌کند که معمولاً به تولید کدهای غیراستاندارد، نقض اصول معماری یا بازنویسی‌های مکرر منتهی می‌شود. برای دریافت کدهای دقیق و متناسب با استانداردهای مدرن دات‌نت، پرامپت‌ها باید بر اساس یک ساختار مهندسی ۵ مرحله‌ای تنظیم شوند:

  • زمینه (Context): تعیین نقش فریم‌ورک و ماژول مدنظر (مانند ASP.NET Core 8 یا ۹).
  • هدف اصلی (Goal): عملکرد مشخصی که متد یا کلاس باید انجام دهد (مانند دریافت سفارش بر اساس شناسه).
  • محدودیت‌ها و الزامات (Constraints): رعایت مباحثی مثل async/await، عدم افشای مستقیم موجودیت‌های EF Core و ارسال CancellationToken.
  • پیروی از قراردادها (Existing Conventions): هماهنگی با الگوهای طراحی فعلی پروژه (مانند استفاده از Minimal APIs یا Controller-based و نحوه تزریق وابستگی‌ها).
  • خروجی مورد انتظار (Expected Output): نوع بازگشتی مشخص (مثل Results یا ActionResult).

نمونه پرامپت استاندارد برای ایجاد یک Endpoint
ایجاد یک اکشن متد در کنترلر سفارشات (OrdersController) در ASP.NET Core با الزامات زیر:
  • به صورت Asynchronous با پشتیبانی از CancellationToken.
  • اعتبارسنجی ورودی و بازگرداندن پاسخ 404 Not Found در صورت عدم وجود سفارش.
  • عدم بازگرداندن مستقیم Entity و مپ کردن آن به OrderResponseDto.
  • استفاده از Interface لایه سرویس (IOrderService) از طریق Dependency Injection.

کد پیشنهادی استاندارد حاصل از این پرامپت در #C:
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IOrderService _orderService;
    private readonly ILogger<OrdersController> _logger;

    public OrdersController(IOrderService orderService, ILogger<OrdersController> logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    [HttpGet("{id:guid}")]
    [ProducesResponseType(typeof(OrderResponseDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<OrderResponseDto>> GetOrderByIdAsync(
        Guid id, 
        CancellationToken cancellationToken)
    {
        var order = await _orderService.GetByIdAsync(id, cancellationToken);
        
        if (order is null)
        {
            _logger.LogWarning("Order with ID {OrderId} was not found.", id);
            return NotFound();
        }

        var response = new OrderResponseDto(
            order.Id, 
            order.OrderDate, 
            order.TotalAmount, 
            order.Status);

        return Ok(response);
    }
}

نکات تکمیلی برای غنی‌سازی زمینه (Context) در Visual Studio و VS Code

  • نقش فایل‌های باز (Open Tabs): کوپایلوت تب‌های فعال ادیتور را به عنوان Context همسایه بررسی می‌کند. قبل از درخواست برای نوشتن کد، فایل‌های Order.cs و OrderResponseDto.cs را باز نگه دارید تا ساختار پراپرتی‌ها و تایپ‌ها را بدون نیاز به تایپ مجدد شناسایی کند.
  • استفاده از ارجاعات مستقیم (Chat Participants & Variables): در پنل Copilot Chat، از عملگرهای @ و # استفاده کنید (مانند #file:OrderService.cs یا #selection) تا مدل دقیقاً بداند بر اساس کدام بخش از سورس‌کد باید پیاده‌سازی را انجام دهد.
  • تنظیم فایل copilot-instructions.md: برای عدم تکرار محدودیت‌های سراسری، یک فایل با نام .github/copilot-instructions.md در ریشه مخزن بسازید و قواعدی نظیر «همیشه از C# File-scoped namespaces استفاده کن» یا «همه اکشن‌ها باید CancellationToken داشته باشند» را تعریف کنید تا به طور خودکار به تمام پرامپت‌ها ضمیمه شود.

چه زمانی نباید پرامپت طولانی نوشت؟
پرامپت‌های تفصیلی برای تصمیم‌گیری‌های معماری، ایجاد کلاس‌ها و پیاده‌سازی منطق‌های چندمرحله‌ای است. برای تکمیل خطوط ساده (مانند var customer = یا فراخوانی‌های تک‌خطی LINQ)، رفتار پیش‌فرض هوش مصنوعی بر پایه‌ی توقف و تکمیل خودکار (Ghost Text) بهترین عملکرد و بیشترین سرعت را دارد. قاعده کلی: هرچه تصمیم فنی بزرگ‌تر و حساس‌تر باشد، زمینه و قیود پرامپت باید دقیق‌تر و کامل‌تر تعیین شوند.