واجهة CLI للمسؤول
جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 103 من 107.
التحدي
سهللنَبْنِ واجهة سطر أوامر لنظام إدارة المكتبة باستخدام نمط الأوامر! ستنشئ CLI يعالج أوامر المسؤول مثل إضافة الكتب، وتسجيل المستخدمين، وإدارة عمليات الاستعارة: كل ذلك من خلال بنية نظيفة قابلة للتوسّع.
ستنظّم شيفرتك عبر ستة ملفات:
book.go: بنيةBookالخاصة بك مع وسوم JSON لكل منIDوTitleوAuthorوISBNوAvailable. ضمّن المُنشئNewBook.user.go: بنيةUserالخاصة بك مع وسوم JSON لكل منIDوNameوEmailوBorrowedBooks. ضمّن المُنشئNewUser.library.go: بنيةLibraryالخاصة بك مع خرائط للكتب والمستخدمين، إلى جانب أساليبAddBookوAddUserوBorrowوReturnمن الدروس السابقة.commands.go: هنا يظهر نمط الأوامر بوضوح! عرّف واجهةCommandمع أسلوبExecuteيأخذ*Libraryو[]stringمن الوسائط، ويُرجع نتيجة نصية. ثم نفّذ بنى الأوامر التالية:AddBookCommand: يتوقع 4 وسائط: id وtitle وauthor وisbn. يضيف الكتاب ويُرجعBook added: [title]AddUserCommand: يتوقع 3 وسائط: id وname وemail. يضيف المستخدم ويُرجعUser added: [name]BorrowCommand: يتوقع وسيطين: userID وbookID. يُرجعBorrowed: [bookID]عند النجاح، أوError: [message]عند الفشلReturnCommand: يتوقع وسيطين: userID وbookID. يُرجعReturned: [bookID]عند النجاح، أوError: [message]عند الفشلListBooksCommand: لا يأخذ أي وسائط. يُرجع معرّف كل كتاب وعنوانه في سطر منفصل بالتنسيق[id]: [title]، أوNo booksإذا كانت القائمة فارغة (مع ترتيب الكتب حسب المعرّف)
إذا تلقّى أحد الأوامر عددًا غير كافٍ من الوسائط، فأرجع
Error: insufficient argumentscli.go: أنشئ بنيةCLIتحتوي على مؤشر إلىLibraryوخريطة لأسماء الأوامر وتطبيقاتCommand. أنشئ ما يلي:- المُنشئ
NewCLIالذي يهيّئ CLI باستخدام مكتبة ويسجّل جميع الأوامر:addbookوadduserوborrowوreturnوlistbooks - أسلوب
Runالذي يأخذ سلسلة إدخال، ويحللها باستخدامstrings.Fields، ويبحث عن الأمر، ثم ينفّذه. أرجعNo command providedعند الإدخال الفارغ، أوUnknown command: [name]للأوامر غير المعروفة
- المُنشئ
main.go: أنشئ مكتبة وCLI، ثم عالج الأوامر من الإدخال. اقرأ عدد الأوامر، ثم اقرأ سلسلة كل أمر في سطر منفصل. لكل أمر، استدعِRunواطبع النتيجة.
ستُوفَّر المدخلات التالية:
- عدد الأوامر
- كل أمر كسلسلة كاملة في سطر مستقل
على سبيل المثال، عند إعطاء:
6
addbook B001 Go-Programming Alan-Donovan 978-0134190440
addbook B002 Clean-Code Robert-Martin 978-0132350884
adduser U001 Alice alice@test.com
borrow U001 B001
listbooks
borrow U001 B001يجب أن يكون ناتجك:
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableوعند إعطاء:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd testيجب أن يكون ناتجك:
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdوعند إعطاء:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001يجب أن يكون ناتجك:
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001لاحظ أن CLI لا يحتاج إلى معرفة تفاصيل كل عملية. فهو يبحث ببساطة عن الأمر ويفوّض التنفيذ إليه. وهذا يجعل إضافة أوامر جديدة أمرًا بسيطًا مثل إنشاء بنية جديدة تنفّذ واجهة Command وتسجيلها في CLI!
جرّب بنفسك
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// اقرأ عدد الأوامر
var n int
fmt.Scanln(&n)
// أنشئ ماسحًا لقراءة الأسطر الكاملة
scanner := bufio.NewScanner(os.Stdin)
// TODO: أنشئ Library جديدة
// TODO: أنشئ CLI جديدة مع المكتبة
// TODO: عالج كل أمر
// لكل أمر من الأوامر n:
// - اقرأ سطر الأمر باستخدام scanner.Scan() و scanner.Text()
// - نفّذ الأمر من خلال CLI
// - اطبع النتيجة
_ = scanner // احذف هذا السطر عندما تستخدم scanner
}
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP في Go
الملفات الخارجيةمساحة العمل والـ Modules في Goالـ Packages والـ Importsالأسماء المصدرة مقابل غير المصدرةمقدمة إلى الـ OOP في Goالـ Structs كـ Classesتعريف الـ Methods في الـ Structsالـ Pointer Receivers مقابل الـ Value Receiversتهيئة الـ Structدوال الـ Constructorمراجعة - آلة حاسبة بسيطة4الواجهات
مقدمة في الواجهاتالتنفيذ الضمنيالواجهة كعقدالواجهة الفارغة (any)تأكيد النوع (Type Assertion)تبديل النوع (Type Switch)تركيب الواجهاتواجهات Stringer و Errorمراجعة - حاسبة الأشكال7التغليف
الحقول المصدرة وغير المصدرةالتغليف على مستوى الحزمةدوال الـ Getter والـ Setterإخفاء المعلومات في Goملخص - سجلات الطلاب10الأنواع العامة (Go 1.18+)
مقدمة في الأنواع العامةمعاملات الأنواعقيود الأنواعالـ Structs العامةحل بديل للـ Methods العامةملخص - المجموعات العامة13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Abstract Factoryنمط Observerنمط Strategy2تعمق في الأنواع و Structs
الأنواع الأساسية والمركبةتعريفات الأنواع المخصصةStruct TagsStructs مجهولةStructs متداخلةالقيم الصفرية والافتراضيةمراجعة - دفتر العناوين5التركيب بدلاً من الوراثة
لماذا لا تدعم Go الوراثةأساسيات تضمين الـ Structترقية الـ Methodتضمين عدة Structsالتضمين مقابل التجميعحجب الـ Methods المضمنةملخص - الهيكل الهرمي للموظفين8معالجة الأخطاء و OOP
واجهة errorأنواع الأخطاء المخصصةتغليف الأخطاء (fmt.Errorf)أخطاء Sentinelerrors.Is() و errors.As()Panic و Defer و Recoverملخص - File Parser11المكتبة القياسية والبرمجة كائنية التوجه (OOP)
io.Reader و io.Writerواجهة sort.Interfaceواجهة fmt.Stringerencoding/json مع Structsواجهة http.Handlerمراجعة - نماذج REST API14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبMiddleware كنمط مزين3المؤشرات والذاكرة
أساسيات المؤشرات في Goالمؤشرات إلى الـ Structsالتمرير بالقيمة مقابل التمرير بالمرجعدالة ()newGarbage Collection في Goملخص - بناء Linked List6تعدد الأشكال في Go
تعدد الأشكال عبر InterfacesDuck Typing في Goقواعد استيفاء الـ Interfaceمجموعات متعددة الأشكالحقن التبعيةمراجعة - معالج الدفع9التزامن والبرمجة كائنية التوجه (OOP)
أساسيات الـ Goroutinesالقنوات (Channels) والاتصالالقنوات المخزنة (Buffered) مقابل غير المخزنةجملة Selectsync.Mutex و sync.RWMutexsync.WaitGroupتصميم الـ Structs الآمنة للخيوط (Thread-Safe)مراجعة - Worker Pool12مفاهيم OOP المتقدمة
نمط Functional Optionsنمط Builder في Goتسلسل الدوال (Method Chaining)الأسماء المستعارة للأنواع مقابل التعريفاتأساسيات الـ Reflectionنظرة عامة على Code Generation15مشروع: إدارة المكتبة
نظرة عامة وهيكل المشروعهياكل Structs الكتاب والمستخدمتدرّب بنفسك: مترجم Go عبر الإنترنت