Enterprise C#: كيفية كتابة كود لا تخجل من عرضه في مراجعة الكود

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Enterprise C#: لماذا كود البنك وكود المشروع الشخصي عالمين مختلفين تمامًا

\n\n

إذا كنت قد انتقلت يومًا من استوديو ويب صغير إلى شركة كبيرة أو شركة تكنولوجيا مالية، فأنت تعرف شعور الصدمة الثقافية الخفيفة. بالأمس فقط، كان بإمكانك إجراء "إصلاح عاجل" بدون اختبارات ومع تعليق واحد //TODO: refactor، واليوم تتلقى مراجعة تحتوي على 20 ملاحظة، حيث تتطلب كل طريقة عامة توثيقًا بتنسيق XML، وأي تبعية تتطلب تسجيلًا في حاوية DI.

\n\n

التطوير بلغة C# في Enterprise لا يتعلق بـ "القيام بذلك بسرعة"، بل يتعلق بـ "القيام بذلك بحيث لا يتعطل بعد ثلاث سنوات عندما يتم فصل مؤلف الكود". إنه يتعلق بالقابلية للتنبؤ، والتوسع، ومراجعات الكود التي لا نهاية لها. دعنا نفهم مما يتكون تطوير Enterprise بلغة C# حقًا، وكيف لا تُفصل من الأسبوع الأول.

\n\n

1. البنية: SOLID ليست كلمة عصرية، بل قانون

\n\n

في الشركة الناشئة، يمكنك تحمل بناء متجانس مع نصوص "سحرية" وفئات ضخمة تحتوي على 2000 سطر. في Enterprise - لا. هنا، كل مبدأ من مبادئ SOLID ليس مجرد تجريد، بل دليل للعمل.

\n\n

مبدأ المسؤولية الواحدة (SRP)

\n

يجب ألا تعرف فصلك كيفية إرسال رسائل البريد الإلكتروني، والحفظ في قاعدة البيانات، وتحليل XML في نفس الوقت. إذا رأيت ثلاث "مسؤوليات" أو أكثر في فئة واحدة - فهذه رائحة كريهة. في Enterprise، سيتم رفض هذا الكود في مراجعة الكود مع صياغة "انتهاك SRP، أعد الكتابة". مثال على كود سيء:

\n\n
public class OrderService\n{\n    public void ProcessOrder(Order order)\n    {\n        // 1. التحقق\n        // 2. الحفظ في قاعدة البيانات\n        // 3. إرسال البريد الإلكتروني\n        // 4. التسجيل\n    }\n}
\n\n

النهج الصحيح هو تقسيمها إلى خدمات منفصلة واستخدام نمط Mediator أو Pipeline:

\n\n
public class ProcessOrderCommandHandler : IRequestHandler<ProcessOrderCommand, bool>\n{\n    private readonly IOrderRepository _repo;\n    private readonly IEmailService _email;\n    private readonly ILogger<ProcessOrderCommandHandler> _logger;\n\n    public ProcessOrderCommandHandler(IOrderRepository repo, IEmailService email, ILogger<ProcessOrderCommandHandler> logger)\n    {\n        _repo = repo;\n        _email = email;\n        _logger = logger;\n    }\n\n    public async Task<bool> Handle(ProcessOrderCommand request, CancellationToken cancellationToken)\n    {\n        var order = await _repo.GetByIdAsync(request.OrderId);\n        // منطق\n        await _email.SendAsync(order.CustomerEmail, "Order processed");\n        _logger.LogInformation("Order {Id} processed", order.Id);\n        return true;\n    }\n}
\n\n

لاحظ: كل خدمة تقوم بمهمة واحدة بالضبط. اختبار مثل هذا الكود أسهل بكثير.

\n\n

2. Dependency Injection - صديقك الأهم

\n\n

في مشاريع Enterprise بلغة C#، نادرًا ما ترى new MyService() داخل فئة. بدلاً من ذلك - حاوية DI (عادةً Autofac أو Microsoft.Extensions.DependencyInjection المدمجة).

\n\n

القاعدة بسيطة: إذا كانت الفئة تنشئ تبعياتها بنفسها - فهي تنتهك مبدأ انعكاس التبعية. في Enterprise، يعتبر هذا خطأ في البنية. مثال:

\n\n
// ❌ سيء: ارتباط صلب\npublic class ReportGenerator\n{\n    private readonly PdfExporter _exporter = new PdfExporter();\n    public byte[] Generate() => _exporter.Export();\n}\n\n// ✅ جيد: انعكاس التبعيات\npublic class ReportGenerator\n{\n    private readonly IExporter _exporter;\n    public ReportGenerator(IExporter exporter) => _exporter = exporter;\n    public byte[] Generate() => _exporter.Export();\n}
\n\n

التسجيل في بدء التشغيل:

\n
services.AddScoped<IExporter, PdfExporter>();\nservices.AddScoped<ReportGenerator>();
\n\n

لماذا هذا مطلوب؟ أولاً، الاختبارات: يمكنك محاكاة IExporter وعدم إنشاء

المدونات

توصيات الكتب