اذهب إلى المحتوى

توزيع الوحدات Modules المكتوبة بلغة Go


هدى جبور

تسمح العديد من لغات البرمجة الحديثة -بما في ذلك لغة جو- للمطورين بتوزيع مكتبات جاهزة للآخرين لاستخدامها في برامجهم. تستخدم بعض اللغات مستودعًا مركزيًا لتثبيت هذه المكتبات، بينما توزعها لغة جو من نفس مستودع التحكم في الإصدار version control repository المستخدم لإنشاء المكتبات. تستخدم لغة جو أيضًا نظام إصدار يسمى الإصدار الدلالي Semantic Versioning، ليوضح للمستخدمين متى وما هو نوع التغييرات التي أُجريت. يساعد ذلك المستخدمين على معرفة ما إذا كان الإصدار الأحدث من الوحدة آمنًا للترقية، وما إذا كان يساعد في ضمان استمرار عمل برامجهم مع الوحدة.

سننشئ في هذه المقالة وحدةً برمجيةً جديدة باستخدام لغة جو وسننشرها، وسنتعلم استخدام الإصدار الدلالي، وسننشر إصدارًا دلاليًا من الوحدة التي أنشأناها.

المتطلبات

إنشاء وحدة للتحضير لنشرها

على عكس العديد من لغات البرمجة الأخرى، توزّع الوحدة المُنشأة باستخدام لغة جو مباشرةً من مستودع الشيفرة المصدر الذي يتضمنها بدلًا من مستودع حزم مستقل. يسهل هذا على المستخدمين العثور على الوحدات المشار إليها في التعليمات البرمجية الخاصة بهم وعلى المشرفين على الوحدة لنشر إصدارات جديدة من الوحدة الخاصة بهم. سننشئ في هذا القسم وحدةً جديدة، وسننشرها بعد ذلك لجعلها متاحةً للمستخدمين الآخرين. لنبدأ بإنشاء الوحدة الآن.

سنستخدم بدايةً الأمر git clone لأخذ نسخة محلية من المستودع الفارغ الذي لا بُد أن نكون أنشأناه لأنه جزء من المتطلبات الأساسية. يمكن نسخ هذا المستودع إلى أي مكان نريده على جهاز الحاسب، لكن يميل العديد من المطورين إلى إنشاء مجلد خاص يتضمن جميع مشاريعهم. سنستخدم هنا مجلدًا باسم "projects".

أنشئ مجلد "projects" وانتقل إليه:

$ mkdir projects
$ cd projects

من مجلد "projects"، شغل الأمر git clone لنسخ المستودع إلى جهاز الحاسب:

$ git clone git@github.com:your_github_username/pubmodule.git

ستكون نتيجة تنفيذ هذا الأمر هي نسخ الوحدة إلى مجلد "pubmodule" داخل مجلد "projects". قد تتلقى تحذيرًا بأنك نسخت مستودعًا فارغًا، ولكن لا داعٍ للقلق بشأن ذلك:

Cloning into 'pubmodule'...
warning: You appear to have cloned an empty repository.

انتقل الآن إلى المجلد "pubmodule":

$ cd pubmodule

سنستخدم الآن الأمر go mod init لإنشاء الوحدة الجديدة وتمرير موقع المستودع اسمًا للوحدة. يُعد التأكد من تطابق اسم الوحدة مع موقع المستودع أمرًا مهمًا، لأن هذه هي الطريقة التي تعثر بها أداة go mod init على مكان تنزيل الوحدة عند استخدامها في مشاريع أخرى:

$ go mod init github.com/your_github_username/pubmodule

ستظهر رسالة تؤكد عملية إنشاء الوحدة من خلال إعلامنا بأن الملف "go.mod" قد أُنشئ:

go: creating new go.mod: module github.com/your_github_username/pubmodule

سنستخدم الآن محرر نصوص مثل نانو nano، لإنشاء وفتح ملف يحمل نفس اسم المستودع "pubmodule.go".

$ nano pubmodule.go

يمكن تسمية هذا الملف بأي اسم، ولكن يُفضّل استخدام نفس اسم الحزمة لتسهيل معرفة مكان البدء عند العمل مع حزمة غير مألوفة، كما ينبغي أن يكون اسم الحزمة هو نفس اسم المستودع. بالتالي، عندما يُشير شخص ما إلى تابع أو نوع من تلك الحزمة، فإنها تتطابق مع اسم المستودع، مثل pubmodule.MyFunction. سيسهل ذلك عليهم معرفة مصدر الحزمة في حال احتاجوا إلى الرجوع إليها لاحقًا.

نُضيف الآن الدالة Hello إلى الحزمة، والتي ستعيد السلسلة !Hello, You. ستكون هذه الدالة متاحةً لأي شخص يستورد الحزمة:

package pubmodule

func Hello() string {
  return "Hello, You!"
}

لقد أنشأنا الآن وحدةً جديدةً باستخدام go mod init مع اسم وحدة يتطابق مع اسم المستودع البعيد (github.com/yourgithubusername/pubmodule)، وأضفنا أيضًا ملفًا باسم "pubmodule.go" إلى الوحدة، مع دالة تُسمى Hello يمكن استدعاؤها من قِبل مستخدمي هذه الوحدة. سننشر في الخطوة التالية هذه الوحدة بهدف إتاحتها للآخرين.

نشر الوحدة

لقد حان الوقت لنشر الوحدة التي أنشأناها في الخطوة السابقة. نظرًا لأن وحدات لغة جو تُوزّع من نفس مستودعات الشيفرة التي تُخزّن فيها، فسوف نُودع commit الشيفرة في مستودع غيت المحلي وندفعه push إلى المستودع الخاص بنا على github.com/your_github_username/pubmodule، ولكن قبل ذلك من الجيد التأكد من عدم إيداع ملفات لا نريد إيداعها عن طريق الخطأ أو عدم الانتباه، لأنها ستُنشر علنًا عند دفع الشيفرة إلى غيت هب. يمكن إظهار جميع الملفات داخل مجلد "pubmodule" والتغييرات التي ستُنفّذ باستخدام الأمر التالي:

$ git status

سيبدو الخرج كما يلي:

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    go.mod
    pubmodule.go

يجب أن نرى ملف "go.mod" الذي أُنشئ بواسطة الأمر go mod init، وملف "pubmodule.go" الذي أنشأنا فيه دالة Hello. قد يكون اسم الفرع مختلفًا عن الخرج السابق اعتمادًا على كيفية إنشاء المستودع، وستكون الأسماء غالبًا إما main أو master.

عندما نتأكد من أن الملفات التي نريدها فقط موجودة، يمكننا إدراج stage الملفات باستخدام git add وإيداعها بالمستودع باستخدام الأمر git commit:

$ git add .
$ git commit -m "Initial Commit"

سيكون الخرج كما يلي:

[main (root-commit) 931071d] Initial Commit
 2 files changed, 8 insertions(+)
 create mode 100644 go.mod
 create mode 100644 pubmodule.go

نستخدم الأمر git push لدفع الوحدة إلى مستودع غيت هب:

$ git push

سيكون الخرج كما يلي:

Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 367 bytes | 367.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:your_github_username/pubmodule.git
 * [new branch]      main -> main

ستُدفع الوحدة إلى المستودع بعد تشغيل الأمر git push، وستكون متاحةً الآن لأي شخص آخر لاستخدامها. ستستخدم جو الشيفرة الموجودة في الفرع الافتراضي للمستودع على أنها شيفرة للوحدة إذا لم يكن لديك أيّة إصدارات منشورة. لا يهم ما إذا كان اسم الفرع الافتراضي هو main أو master أو أي شيء آخر، المهم هو الفرع الذي ضُبط على أنه فرع افتراضي.

تعلّمنا في هذا القسم كيفية نشر وحدة في لغة جو على مستودع غيت هب من المستودع المحلي لإتاحتها للآخرين. واحدة من الأمور الأساسية التي يجب أخذها بالحسبان، هي التأكد من أن مستخدمي الوحدة يمكنهم استخدام إصدار مستقر منها.

من المحتمل أن نرغب في إجراء تغييرات وإضافة ميزات إلى الوحدة من الآن فصاعدًا، ولكن إذا أجرينا هذه التغييرات دون استخدام مفهوم الإصدارات، فقد تتعطل شيفرة شخص ما يستخدم هذه الوحدة عن طريق الخطأ. لحل هذه المشكلة: يمكننا إضافة إصدارات إلى الوحدة عندما نصل إلى مرحلة جديدة في عملية التطوير، ومع ذلك، عند إضافة إصدارات جديدة يجب التأكد من اختيار رقم إصدار مفيد حتى يعرف المستخدمون ما إذا كان من الآمن لهم الترقية فورًا أم لا.

الإصدار الدلالي

يعطي رقم الإصدار التعبيري meaningful version number للمستخدمين فكرةً عن مدى تغير الواجهة العامة أو واجهة برمجة التطبيقات التي يتفاعلون معها. تنقل جو هذه التغييرات من خلال نظام أو مخطط إصدار versioning scheme يُعرف باسم الإصدار الدلالي semantic versioning -أو اختصارًا SemVer. يستخدم الإصدار الدلالي سلسلة الإصدار لنقل المعنى حول تغييرات الشيفرة، ومن هنا يأتي اسم الإصدار الدلالي. يُستخدم الإصدار الدلالي لتحديد الإصدارات الأحدث من الإصدار الحالي المُستخدم، وما إذا كان بالإمكان الترقية للإصدار الأحدث آليًا بأمان.

يعطي الإصدار الدلالي كل رقم في سلسلة الإصدار معنى meaning. يحتوي الإصدار النموذجي في SemVer على ثلاثة أرقام أساسية: الإصدار الرئيسي major والإصدار الثانوي minor وإصدار التصحيح patch version. تُدمج كل من هذه الأرقام مع بعضها بواسطة النقطة (.) لتشكيل سلسلة الإصدار، مثلًا 1.2.3، تُرتّب فيه الأرقام وفقًا للآلية التالية: أول رقم للإصدار الرئيسي ثم الإصدار الثانوي ثم إصدار التصحيح أخيرًا. يمكنك بهذه الطريقة معرفة أيهما أحدث لأن الرقم الموجود في مكان معين أعلى من الإصدارات السابقة. على سبيل المثال، الإصدار 2.2.3 أحدث من 1.2.3 لأن الإصدار الرئيسي أعلى، وبالمثل، فإن الإصدار 1.4.3 أحدث من 1.2.10 لأن الإصدار الثانوي أعلى، وعلى الرغم من أن 10 أعلى من 3 في إصدار التصحيح، فإن الإصدار الثانوي 4 أعلى من 2، لذا فإن هذا الإصدار له الأسبقية.

عندما يزداد رقم في سلسلة الإصدار، يُعاد ضبط جميع الأجزاء الأخرى من الإصدار التي تليها إلى 0. على سبيل المثال، تؤدي زيادة الإصدار الثانوي من 1.3.10 إلى 1.4.0 وزيادة الإصدار الرئيسي من 2.4.1 إلى 3.0.0.

يسمح استخدام هذه القواعد للغة جو بتحديد إصدار الوحدة التي يجب استخدامها عند تشغيل go get. مثلًا، لنفرض أن لدينا مشروعًا يستخدم الإصدار 1.4.3 من الوحدة github.com/your_github_username/pubmodule. إذا كنا نعتمد على كون الوحدة pubmodule مستقرة، فقد نرغب فقط في ترقية إصدار التصحيح تلقائيًا 3..

إذا شغّلت الأمر:

go get -u=patch github.com/your_github_username/pubmodule

ستستنتج لغو جو أننا تريد ترقية إصدار التصحيح للوحدة، وستبحث فقط عن الإصدارات الجديدة مع 1.4 للجزء الرئيسي والثانوي من الإصدار.

من المهم أن نضع في الحسبان كيف تغيرت واجهة برمجة التطبيقات العامة للوحدة عند إنشاء إصدار جديد منها، إذ ينقل لنا كل جزء من سلسلة الإصدار الدلالية نطاق التغيير في واجهة برمجة التطبيقات وكذلك للمستخدمين. تنقسم هذه الأنواع من التغييرات عادةً إلى ثلاث فئات مختلفة، تتماشى مع كل مكون من مكونات الإصدار؛ إذ تؤدي التغيرات الأصغر إلى زيادة إصدار التصحيح، وتزيد التغييرات متوسطة الحجم من الإصدار الثانوي، وتزيد التغييرات الأكبر في الإصدار الرئيسي. سيساعدنا استخدام هذه الفئات في تحديد رقم الإصدار المراد زيادته وتجنب تعطل break الشيفرة الخاصة بنا أو شيفرة أي شخص آخر يعتمد على هذه الوحدة.

أرقام الإصدارات الرئيسية

الرقم الأول في SemVer هو رقم الإصدار الرئيسي (1.4.3)، وهو أهم رقم يجب مراعاته عند إطلاق إصدار جديد من الوحدة. في هذا النوع من الإصدارات يكون هناك تغيّر كبير في الإصدار يُشير إلى تغيرات غير متوافقة backward-incompatible changes مع الإصدارات السابقة لواجهة برمجة التطبيقات العامة المستخدمة API؛ وقد يكون التغير غير المتوافق مع الإصدارات السابقة هو أي تغير يطرأ على الوحدة من شأنه أن يتسبب في تعطل breaking برنامج شخص ما إذا أجرى الترقية دون إجراء أي تغييرات أخرى. يمكن أن يمثّل التعطّل أي حالة فشل في البناء بسبب تغيير اسم دالة أو تغيير في كيفية عمل المكتبة، بحيث أن تابعًا أصبح يُعيد "v1" بدلًا من "1". هذا فقط من أجل واجهة برمجة التطبيقات العامة الخاصة بنا، ومع ذلك يمكن لشخص آخر استخدام أي أنواع أو توابع قد صُدّرت.

إذا كان الإصدار يتضمن فقط تحسينات لن يلاحظها مستخدم المكتبة، فلا يحتاج إلى تغيير كبير في الإصدار. قد تكون إحدى الطرق لتذكر التغييرات التي تناسب هذه الفئة هي أخذ كل "تحديث" أو "حذف" بمثابة زيادة كبيرة في الإصدار.

ملاحظة: على عكس الأنواع الأخرى من الأرقام في SemVer، فإن الإصدار الرئيسي 0 له أهمية خاصة إضافية، إذ يُعد إصدارًا "قيد التطوير in development". لا يُعد أي SemVer بإصدار رئيسي 0 مستقرًا، وأي شيء يمكن أن يتغير في واجهة برمجة التطبيقات في أي وقت. يُفضّل أن نبدأ دومًا بالإصدار الرئيسي 0 عند إنشاء وحدة جديدة، وتحديث الإصدارات الثانوية والإصدارات التصحيحية فقط حتى ننتهي من التطوير الأولي للوحدة. بعد الانتهاء من تغيير واجهة برمجة التطبيقات العامة للوحدة وعدّها مستقرةً للمستخدمين، حان الوقت لبدء الإصدار 1.0.0.

لنأخذ الشيفرة التالية مثالًا على الشكل الذي قد يبدو عليه تغيير الإصدار الرئيسي. لدينا دالة تسمى UserAddress تقبل حاليًا string معاملًا وتعيد string:

func UserAddress(username string) string {
    // تُعيد عنوان المستخدم مثل سلسلة
}

تُعيد الدالة حاليًا سلسلة، وقد يكون من الأفضل لنا وللمستخدمين إذا أعادت الدالة السابقة بنيةً struct مثل Address*، إذ يمكن بهذه الطريقة تضمين بيانات إضافية (مثل الرمز البريدي) وبطريقة منظمة:

type Address struct {
    Address    string
    PostalCode string
}

func UserAddress(username string) *Address {
    // تُعيد عنوان المستخدم والرمز البريدي مثل بنية
}

قد يكون هذا مثالًا على تغيير رئيسي في الإصدار لأنه سيتطلب من المستخدمين إجراء تغييرات على التعليمات البرمجية الخاصة بهم من أجل استخدامها. سيكون الأمر نفسه صحيحًا إذا قررنا حذف الدالة UserAddress، لأن المستخدمين سيحتاجون إلى تحديث التعليمات البرمجية الخاصة بهم لاستخدام البديل.

مثال آخر على تغيير الإصدار الرئيسي هو إضافة معامل جديد إلى دالة UserAddress على الرغم من أنها ما زالت تُعيد string:

func UserAddress(username string, uppercase bool) string {
    // true تُعيد عنوان المستخدم مثل سلسلة بأحرف كبيرة إذا كان المعامل المنطقي قيمته
}

نظرًا لأن هذا التغيير يتطلب أيضًا من المستخدمين تحديث التعليمات البرمجية الخاصة بهم إذا كانوا يستخدمون دالة UserAddress، فسيتطلب ذلك أيضًا زيادة كبيرة في الإصدار.

لن تكون كل التغييرات التي نجريها على الشيفرة جذرية، إذ سنُجري أحيانًا تغييرات على واجهة برمجة التطبيقات العامة API، بحيث نُضيف دوالًا أو قيمًا جديدة، ولكن هذا لا يغير أيًا من الدوال أو القيم الحالية.

أرقام الإصدارات الثانوية

الرقم الثاني في إصدار SemVer هو رقم الإصدار الثانوي (1.4.3)، وهنا يطرأ تغيير بسيط في الإصدار للإشارة إلى التغييرات المتوافقة مع الإصدارات السابقة لواجهة برمجة التطبيقات العامة الخاصة بنا. سيكون التغيير المتوافق مع الإصدارات السابقة أي تغيير لا يؤثر على التعليمات البرمجية أو المشاريع التي تستخدم الوحدة الحالية. على غرار رقم الإصدار الرئيسي؛ يؤثر هذا فقط على واجهة برمجة التطبيقات العامة. قد تكون إحدى الطرق لتذكر التغييرات التي تناسب هذه الفئة، هي أي شيء يعد "إضافة"، ولكن ليس "تحديثًا".

باستخدام نفس المثال السابق الذي شرحنا فيه رقم الإصدار الرئيسي، تخيل أن لديك تابع باسم UserAddress يُعيد سلسلة string:

func UserAddress(username string) string {
    //تُعيد عنوان المستخدم مثل سلسلة
}

هنا بدلًا من تحديث UserAddress بجعله يُعيد Address*، سنضيف تابع جديد تمامًا يسمى UserAddressDetail:

type Address struct {
    Address    string
    PostalCode string
}

func UserAddress(username string) string {
   // تُعيد عنوان المستخدم مثل سلسلة
}

func UserAddressDetail(username string) *Address {
   // تُعيد عنوان المستخدم والرمز البريدي مثل بنية
}

لا تتطلب إضافة الدالة الجديدة UserAddressDetail إجراء تغييرات من قِبل المستخدمين إذا حدّثوا إلى هذا الإصدار من الوحدة، لذلك ستُعد زيادة بسيطة في رقم الإصدار. يمكن للمستخدمين الاستمرار في استخدام UserAddress وسيحتاجون فقط إلى تحديث التعليمات البرمجية الخاصة بهم إذا كانوا يفضلون تضمين المعلومات الإضافية من UserAddressDetail.

من المحتمل ألا تكون تغييرات واجهة برمجة التطبيقات العامة هي المرة الوحيدة التي نُطلق فيها إصدارًا جديدًا من الوحدة. تُعد الأخطاء bugs جزءًا لا مفر منه من تطوير البرامج، ورقم إصدار التصحيح موجود للتستر على تلك الثغرات.

أرقام إصدارات التصحيح

الرقم الأخير في صيغة SemVer هي إصدار التصحيح، (1.4.3). تغيير إصدار التصحيح هو أي تغيير لا يؤثر على واجهة برمجة التطبيقات العامة API للوحدة. تكون غالبًا التغييرات التي لا تؤثر على واجهة برمجة التطبيقات العامة للوحدة، أشياءً مثل إصلاحات الأخطاء أو إصلاحات الأمان.

بالعودة إلى الدالة UserAddress من الأمثلة السابقة، لنفترض أن إصدارًا من الوحدة يفتقد إلى جزء من العنوان في السلسلة التي تُعيدها الدالة. إذا أطلقنا إصدارًا جديدًا من الوحدة لإصلاح هذا الخطأ، سيؤدي ذلك إلى زيادة إصدار التصحيح فقط، ولن يتضمن الإصدار أيّة تغييرات في كيفية استخدام المستخدم لواجهة برمجة التطبيقات العامة UserAddress، وإنما مُجرد تعديلات لضمان صحة البيانات المُعادة.

يُعد اختيار رقم إصدار جديد بعناية طريقة مهمة لكسب ثقة المستخدمين، إذ يُظهر استخدام الإصدار الدلالي للمستخدمين مقدار العمل المطلوب للتحديث إلى إصدار جديد، وبالتأكيد لن تفاجئهم عن طريق الخطأ بتحديث يكسر برنامجهم. بعد التفكير في التغييرات التي أجريناها على الوحدة، وتحديد رقم الإصدار التالي المطلوب استخدامه، يمكننا الآن نشر الإصدار الجديد وإتاحته للمستخدمين.

نشر إصدار جديد من الوحدة

سنحتاج إلى تحديث الوحدة بالتغييرات التي نخطط لإجرائها قبل نشر أي إصدار جديد من الوحدة. لن نكون قادرين على تحديد أي جزء من الإصدار الدلالي يجب أن يزداد دون أن نُجري تغييرات. بالنسبة للوحدة التي أنشأناها، سنضيف التابع Goodbye لاستكمال التابع Hello، وبعد ذلك ستنشر هذا الإصدار الجديد للاستخدام.

افتح ملف "pubmodule.go" وضِف التابع الجديد Goodbye إلى واجهة برمجة التطبيقات العامة API:

package pubmodule

func Hello() string {
  return "Hello, You!"
}

func Goodbye() string {
  return "Goodbye for now!"
}

سنحتاج الآن إلى التحقق من التغييرات التي يُتوقع أن تُنفّذ عن طريق تنفيذ الأمر التالي:

$ git status

يوضّح الخرج أن التغيير الوحيد في الوحدة الخاصة بنا، هو التابع الذي أضفناه إلى ملف "pubmodule.go":

On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   pubmodule.go

no changes added to commit (use "git add" and/or "git commit -a")

نضيف بعد ذلك التغيير إلى الملفات المُدرجة ونجري التغيير في المستودع المحلي باستخدام git add و git commit:

$ git add .
$ git commit -m "Add Goodbye method"

سيكون الخرج كما يلي:

[main 3235010] Add Goodbye method
 1 file changed, 4 insertions(+)

سنحتاج إلى دفع التغييرات بعد تنفيذها إلى مستودع غيت هب الخاص بنا، وتكون عادةً هذه الخطوة مختلفة قليلًا عند العمل على مشروع برمجي أكبر أو عند العمل مع مطورين آخرين في مشروع. عند إجراء تطوير على ميزة جديدة، يُنشئ المطور فرع غيت جديد لإجراء تلك التغييرات وتحضيرها إلى أن تصبح هذه الميزة مستقرة وجاهزة للإصدار، وبعدها سيأتي مطور آخر ويُراجع هذه التغييرات ضمن ذلك الفرع للتأكد أو لاكتشاف المشكلات التي ربما غفل عنها المطور الأول. يُدمج الفرع الخاص بتلك الميزة في الفرع الافتراضي، مثل master أو main بمجرد الانتهاء من المراجعة، وتُجمع هذه التغييرات في الفرع الافتراضي حتى يحين وقت نشر إصدار جديد.

هنا لا تمر الوحدة بهذه العملية (إضافة ميزة جديدة في فرع آخر)، لذا سيكون دفع التغييرات التي أجريناها على المستودع، هو فقط التغييرات التي أجريناها:

$ git push

سيكون الخرج على النحو التالي:

numerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 369 bytes | 369.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:your_github_username/pubmodule.git
   931071d..3235010  main -> main

يوضح الخرج أن الشيفرة الجديدة جاهزة للاستخدام في الفرع الافتراضي من قبل المستخدمين.

كل ما فعلناه حتى الآن يُطابق ما فعلناه عند نشر الوحدة في البداية. الآن، تأتي نقطة مهمة في عملية إطلاق الإصدارات، وهي اختيار رقم الإصدار.

إذا نظرنا إلى التغييرات التي أجريناها على الوحدة، فإن التغيّر الوحيد على واجهة برمجة التطبيقات العامة (أو أي تغيير) هو إضافة التابع Goodbye إلى الوحدة. بما أنه يمكن للمستخدم التحديث من الإصدار السابق الذي كان يحتوي فقط على الدالة Hello، دون إجراء تغييرات من جانبهم، سيكون هذا التغيير متوافقًا مع الإصدارات السابقة. قد يعني ذلك (ضمن مفهوم الإصدار الدلالي) التغيير المتوافق مع الإصدارات السابقة لواجهة برمجة التطبيقات العامة زيادةً في رقم الإصدار الثانوي. هذا الإصدار هو الإصدار الأول من الوحدة التي نشرناها، لذلك ليس هناك إصدار سابق لنزيد عليه. عمومًا، إذا كان الإصدار الحالي هو 0.0.0 أي "لا يوجد إصدار"، ستقودنا زيادة الإصدار الثانوي إلى الإصدار 0.1.0، وهو الإصدار التالي من الوحدة التي أنشأناها.

الآن، بعد أن أصبح لدينا رقم إصدار نُعطيه للوحدة، أصبح بإمكاننا استخدامه مع وسوم غيت لنشر إصدار جديد. عندما يستخدم المطورون غيت لتتبع شيفرة المصدر الخاصة بهم (حتى في لغات أخرى غير جو)، فإن العرف الشائع هو استخدام وسوم غيت لتتبع الشيفرة التي أُطلقت لإصدار معين؛ فبهذه الطريقة يمكنهم استخدام الوسم إذا احتاجوا في أي وقت إلى إجراء تغييرات على إصدار قديم. بما أن لغة جو تُنزّل الوحدات من المستودعات المصدرية، بالتالي تستطيع الاستفادة من هذه الخاصية في استخدام وسوم الإصدار نفسها.

لنشر نسخة جديدة من الوحدة التي أنشأناها باستخدام هذه الوسوم، سنضع وسمًا على الشيفرة التي نطلقها باستخدام الأمر git tag، وستحتاج أيضًا إلى تقديم وسم الإصدار مثل وسيط لهذا الأمر.

لإنشاء وسم الإصدار، نبدأ بالبادئة v ونضيف SemVer بعدها مباشرةً. في حالتنا، سيكون وسم الإصدار النهائي هو v0.1.0.

شغل الأمر git tag لتمييز الوحدة التي أنشأناها بوسم الإصدار هذا:

$ git tag v0.1.0

سنحتاج -بعد إضافة وسم الإصدار محليًا- إلى دفع هذا الوسم إلى مستودع غيت هب باستخدام git push مع origin:

$ git push origin v0.1.0

بعد نجاح تنفيذ الأمر git push، سترى أن الوسم v0.1.0 قد أُنشئ:

Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:your_github_username/pubmodule.git
 * [new tag]         v0.1.0 -> v0.1.0

يوضح الخرج أعلاه أن الوسم السابق قد أَُضيف، وأن مستودع غيت هب الخاص بنا يحتوي على الوسم الجديد v0.1.0، وسيكون متاحًا لمستخدمي الوحدة الوصول إليه.

بعد نشر إصدار جديد من الوحدة واستخدام الأمر git tag، لن يكون المستخدم بحاجة إلى تنزيل إصدار جديد بناءً على أحدث إيداع تعمية hash من الفرع الافتراضي، وذلك عندما يرغب بالحصول على أحدث إصدار من الوحدة باستخدام الأمر go get.

بعد إطلاق إصدار الوحدة، ستبدأ أداة go في استخدام هذه الإصدارات لتحديد أفضل طريقة لتحديث الوحدة، ويتيح لنا ذلك إلى جانب الإصدار الدلالي، إمكانية تكرار الوحدات وتحسينها مع تزويد المستخدمين بتجربة متسقة ومستقرة.

الخاتمة

أنشأنا خلال هذه المقالة وحدةً برمجيةً عامة باستخدام لغة جو ونشرناها في مستودع غيت هب حتى يتمكن الآخرون من استخدامها، واستخدمنا أيضًا مفهوم الإصدار الدلالي لتحديد رقم إصدار مناسب للوحدة. وسّعنا أيضًا دوال هذه الوحدة، ونشرنا الإصدار الجديد اعتمادًا على مفهوم الإصدار الدلالي مع ضمان عدم تعطّل البرامج التي تعتمد عليها.

ترجمة -وبتصرف- للمقال How to Distribute Go Modules لصاحبه Kristin Davidson.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...