مختبر المخزون
Inventory Lab
مختبر المخزون — Inventory Lab
في هذا المختبر ستبني مخزوناً صغيراً. المطلوب ليس كوداً طويلاً؛ المطلوب أن تختار البنية المناسبة:
Productيمثل المنتج.map[string]Productيربط SKU بالمنتج.- دوال صغيرة تضيف أو تحدّث أو تطبع.
المخزون من أكثر الأمثلة قرباً لكود العمل؛ يوجد مفتاح ثابت للمنتج، كمية تتغير، وسعر يستخدم في الحسابات. لهذا لا يكفي أن “يعمل” الكود مرة واحدة. يجب أن تكون الحدود واضحة: هل المنتج موجود؟ هل التحديث نجح؟ أين نحسب قيمة المخزون؟ وهل main ينسق سير البرنامج فقط أم يحمل كل التفاصيل؟
في هذا المختبر سنستخدم map[string]Product لأن الوصول بالـ SKU مباشر ومناسب. المفتاح مثل "PEN" أو "BOOK" يعبّر عن هوية المنتج، والقيمة Product تحمل الاسم والسعر والكمية. تذكر أن قراءة struct من map تعطيك نسخة، لذلك إذا عدلت الكمية داخل النسخة يجب أن تعيد حفظها في الخريطة. هذه نقطة يقع فيها كثير من المتعلمين لأنها لا تظهر عند استخدام أنواع بسيطة فقط.
المتطلبات
اكتب برنامجاً يحقق التالي:
- ينشئ مخزوناً فيه منتجان.
- يضيف كمية جديدة إلى منتج موجود.
- يرفض تحديث SKU غير موجود برسالة واضحة.
- يطبع إجمالي قيمة المخزون.
اقرأ المتطلبات كعقود صغيرة. الدالة addStock لا تحتاج أن تطبع بنفسها؛ يكفي أن ترجع true أو false حتى يقرر المستدعي الرسالة المناسبة. الدالة inventoryValue لا تحتاج أن تعرف لماذا نحسب القيمة؛ تمر على المنتجات وتجمع السعر في الكمية. عندما تلتزم كل دالة بعقد صغير، يصبح الاختبار أسهل ويصبح تغيير الرسائل أو طريقة العرض منفصلاً عن الحساب.
بداية مقترحة
لاحظ ترتيب العمل داخل addStock: نقرأ المنتج، نفحص هل موجود، نعدّل النسخة، ثم نعيدها إلى map. لو حذفت السطر inventory[sku] = product فلن تظهر الزيادة في المخزون. هذا ليس خللاً في Go؛ هذه نتيجة طبيعية لأن Product قيمة وليست مؤشراً.
تحدي المختبر
أكمل الكود بحيث يطبع الحالة النهائية المطلوبة. لا تغيّر أسماء المنتجات أو الأسعار.
معيار القبول
الحل الجيد يستخدم دوالاً صغيرة ولا يكرر حساب قيمة المخزون داخل main. إذا كان تحديث المنتج في map لا يظهر، تذكر أن قيمة struct تُنسخ عند قراءتها من الخريطة.
فحص الحل قبل اعتباره منتهياً
ابدأ بفحص السلوك الطبيعي: تحديث "PEN" يزيد الكمية من 10 إلى 15. بعد ذلك افحص الحالة السلبية: تحديث "BAG" يجب أن يفشل دون أن يضيف منتجاً جديداً بصمت. ثم افحص الحساب النهائي: قيمة الأقلام 3.5 * 15 وقيمة الكتب 40 * 2، والمجموع 132.50. إذا اختلف الرقم، فالخطأ غالباً في نسيان تحويل الكمية إلى float64 أو في عدم حفظ النسخة المعدلة داخل الخريطة.
لا تجعل main يعرف تفاصيل أكثر مما يلزم. في حل جيد، يستطيع القارئ قراءة main كقصة قصيرة: أنشئ المخزون، حاول التحديث، اطبع الحالة، اطبع القيمة. التفاصيل الحسابية موجودة داخل دوال بأسماء واضحة. هذا الأسلوب هو ما يجعل الكود يكبر بلا فوضى عندما تضيف لاحقاً خصماً، حد تنبيه للكمية، أو قراءة المنتجات من ملف.
خلاصة
هذا المختبر يربط struct وmap بالحالة المتغيرة. أهم درس فيه أن اختيار البنية يؤثر على شكل كل دالة بعدها. map ممتازة للوصول السريع، لكنها تطلب منك أن تتعامل بوعي مع حالة المفتاح غير الموجود ومع نسخ القيم. إذا أتقنت هذا النمط، ستفهم كثيراً من كود repositories وcaches والإعدادات في مشاريع Go.