موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

آج، زیادہ تر سافٹ ویئر کی مصنوعات ٹیموں میں تیار کی جاتی ہیں۔ کامیاب ٹیم کی ترقی کے حالات کو ایک سادہ خاکہ کی شکل میں پیش کیا جا سکتا ہے۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

اپنا کوڈ لکھنے کے بعد، آپ کو یہ یقینی بنانا ہوگا:

  1. .
  2. یہ آپ کے ساتھیوں کے لکھے ہوئے کوڈ سمیت کسی بھی چیز کو نہیں توڑتا۔

اگر دونوں شرائط پوری ہوجاتی ہیں، تو آپ کامیابی کے راستے پر ہیں۔ ان حالات کو آسانی سے جانچنے اور منافع بخش راستے سے انحراف نہ کرنے کے لیے، ہم مسلسل انٹیگریشن کے ساتھ آئے ہیں۔

CI ایک ورک فلو ہے جہاں آپ اپنے کوڈ کو جتنی بار ممکن ہو مجموعی پروڈکٹ کوڈ میں ضم کرتے ہیں۔ اور آپ صرف انضمام ہی نہیں کرتے بلکہ یہ بھی چیک کرتے ہیں کہ سب کچھ کام کر رہا ہے۔ چونکہ آپ کو بہت زیادہ اور اکثر چیک کرنے کی ضرورت ہے، یہ آٹومیشن کے بارے میں سوچنے کے قابل ہے۔ آپ ہر چیز کو دستی طور پر چیک کر سکتے ہیں، لیکن آپ کو ایسا نہیں کرنا چاہیے، اور اس کی وجہ یہ ہے۔

  • پیارے لوگ. کسی بھی پروگرامر کے کام کا ایک گھنٹہ کسی بھی سرور کے کام کے ایک گھنٹے سے زیادہ مہنگا ہوتا ہے۔
  • لوگ غلطیاں کرتے ہیں۔. لہذا، ایسے حالات پیدا ہو سکتے ہیں جب ٹیسٹ غلط برانچ پر چلائے گئے تھے یا ٹیسٹرز کے لیے غلط کمٹ مرتب کی گئی تھی۔
  • لوگ سست ہیں۔. وقتاً فوقتاً، جب میں کسی کام کو ختم کرتا ہوں، تو یہ خیال پیدا ہوتا ہے: "چیک کرنے کے لیے کیا ہے؟ میں نے دو لائنیں لکھیں - سب کچھ کام کرتا ہے! مجھے لگتا ہے کہ آپ میں سے بعض کے ذہن میں بھی بعض اوقات ایسے خیالات آتے ہیں۔ لیکن آپ کو ہمیشہ چیک کرنا چاہئے۔

نکولائی نیسٹروف کا کہنا ہے کہ ایویٹو موبائل ڈیولپمنٹ ٹیم میں مسلسل انٹیگریشن کو کیسے لاگو کیا گیا اور تیار کیا گیا، وہ روزانہ 0 سے 450 بلڈز تک کیسے گئے، اور یہ کہ تعمیراتی مشینیں دن میں 200 گھنٹے جمع ہوتی ہیں۔nnesterov) CI/CD اینڈرائیڈ ایپلی کیشن کی تمام ارتقائی تبدیلیوں میں شریک ہے۔

کہانی اینڈرائیڈ کمانڈ کی مثال پر مبنی ہے، لیکن زیادہ تر طریقے iOS پر بھی لاگو ہوتے ہیں۔


ایک زمانے میں، ایک شخص Avito Android ٹیم میں کام کرتا تھا۔ تعریف کے مطابق، اسے مسلسل انضمام سے کسی چیز کی ضرورت نہیں تھی: اس کے ساتھ ضم کرنے والا کوئی نہیں تھا۔

لیکن درخواست میں اضافہ ہوا، زیادہ سے زیادہ نئے کام نمودار ہوئے، اور ٹیم اسی کے مطابق بڑھی۔ کسی وقت، کوڈ انضمام کے عمل کو زیادہ باضابطہ طور پر قائم کرنے کا وقت ہے۔ گٹ فلو کو استعمال کرنے کا فیصلہ کیا گیا۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

گٹ فلو کا تصور مشہور ہے: ایک پروجیکٹ کی ایک مشترکہ ڈیولپمنٹ برانچ ہوتی ہے، اور ہر نئی خصوصیت کے لیے، ڈویلپرز ایک الگ برانچ کاٹتے ہیں، اس سے عہد کرتے ہیں، دھکا دیتے ہیں، اور جب وہ اپنے کوڈ کو ڈیولپمنٹ برانچ میں ضم کرنا چاہتے ہیں، تو ایک کھولیں۔ کھینچنے کی درخواست علم کا اشتراک کرنے اور طریقوں پر تبادلہ خیال کرنے کے لیے، ہم نے کوڈ کا جائزہ متعارف کرایا، یعنی ساتھیوں کو ایک دوسرے کے کوڈ کی جانچ اور تصدیق کرنی چاہیے۔

چیک کرتا ہے۔

اپنی آنکھوں سے کوڈ دیکھنا اچھا ہے، لیکن کافی نہیں۔ اس لیے خودکار چیک متعارف کروائے جا رہے ہیں۔

  • سب سے پہلے، ہم چیک کرتے ہیں اے آر کے اسمبلی.
  • بہت کچھ جنیٹ ٹیسٹ.
  • ہم کوڈ کی کوریج پر غور کرتے ہیں۔چونکہ ہم ٹیسٹ کر رہے ہیں۔

یہ سمجھنے کے لیے کہ یہ چیک کیسے چلائے جائیں، آئیے Avito میں ترقیاتی عمل کو دیکھتے ہیں۔

اس کی نمائندگی اس طرح کی جا سکتی ہے:

  • ایک ڈویلپر اپنے لیپ ٹاپ پر کوڈ لکھتا ہے۔ آپ انضمام کی جانچیں یہیں چلا سکتے ہیں - یا تو کمٹ ہک کے ساتھ، یا صرف پس منظر میں چیک چلائیں۔
  • ڈویلپر کے کوڈ کو آگے بڑھانے کے بعد، وہ پل کی درخواست کھولتا ہے۔ اس کے کوڈ کو ڈیولپمنٹ برانچ میں شامل کرنے کے لیے، ضروری ہے کہ کوڈ کا جائزہ لیا جائے اور مطلوبہ تعداد میں تصدیقات جمع کی جائیں۔ آپ یہاں چیک اور تعمیرات کو فعال کر سکتے ہیں: جب تک تمام تعمیرات کامیاب نہ ہو جائیں، پل کی درخواست کو ضم نہیں کیا جا سکتا۔
  • پل کی درخواست کے ضم ہونے اور کوڈ کے ڈویلپمنٹ میں شامل ہونے کے بعد، آپ ایک مناسب وقت کا انتخاب کر سکتے ہیں: مثال کے طور پر، رات کے وقت، جب تمام سرورز خالی ہوں، اور آپ جتنے چاہیں چیک چلائیں۔

کسی کو بھی اپنے لیپ ٹاپ پر اسکین چلانا پسند نہیں تھا۔ جب ایک ڈویلپر نے ایک خصوصیت ختم کر لی ہے، تو وہ اسے تیزی سے آگے بڑھانا اور پل کی درخواست کھولنا چاہتا ہے۔ اگر اس وقت کچھ لمبے چیک شروع کیے جاتے ہیں، تو یہ نہ صرف بہت خوشگوار ہے، بلکہ ترقی کو بھی سست کر دیتا ہے: جب لیپ ٹاپ کسی چیز کی جانچ کر رہا ہے، تو اس پر عام طور پر کام کرنا ناممکن ہے۔

ہمیں واقعی رات کو چیک چلانا پسند تھا، کیونکہ بہت وقت اور سرور ہوتا ہے، آپ گھوم پھر سکتے ہیں۔ لیکن، بدقسمتی سے، جب فیچر کوڈ تیار ہو جاتا ہے، تو ڈویلپر کے پاس CI کو پائی جانے والی غلطیوں کو ٹھیک کرنے کا حوصلہ بہت کم ہوتا ہے۔ صبح کی رپورٹ میں پائی جانے والی تمام خرابیوں کو دیکھ کر میں وقتاً فوقتاً اپنے آپ کو یہ سوچتا رہتا تھا کہ میں انہیں کسی دن بعد میں ٹھیک کر دوں گا، کیونکہ اب جیرا میں ایک نیا نیا کام ہے جسے میں صرف کرنا شروع کرنا چاہتا ہوں۔

اگر چیکس ایک پل کی درخواست کو روکتا ہے، تو کافی حوصلہ افزائی ہوتی ہے، کیونکہ جب تک بلڈز سبز نہیں ہوتے، کوڈ تیار نہیں ہوگا، جس کا مطلب ہے کہ کام مکمل نہیں ہوگا۔

نتیجے کے طور پر، ہم نے مندرجہ ذیل حکمت عملی کا انتخاب کیا: ہم رات کو زیادہ سے زیادہ ممکنہ چیکس چلاتے ہیں، اور ان میں سے سب سے اہم اور سب سے اہم، سب سے تیز رفتار کو ایک پل کی درخواست پر شروع کرتے ہیں۔ لیکن ہم وہاں نہیں رکتے — متوازی طور پر، ہم چیکوں کی رفتار کو بہتر بناتے ہیں تاکہ انہیں نائٹ موڈ سے منتقل کر کے درخواست کی جانچ پڑتال کی جا سکے۔

اس وقت، ہماری تمام تعمیرات بہت تیزی سے مکمل ہو گئی تھیں، اس لیے ہم نے بس پل کی درخواست کے لیے بلاکر کے طور پر ARK بلڈ، Junit ٹیسٹ اور کوڈ کوریج کے حسابات کو شامل کیا۔ ہم نے اسے آن کیا، اس کے بارے میں سوچا، اور کوڈ کوریج کو ترک کر دیا کیونکہ ہم نے سوچا کہ ہمیں اس کی ضرورت نہیں ہے۔

بنیادی CI کو مکمل طور پر ترتیب دینے میں ہمیں دو دن لگے (اس کے بعد وقت کا تخمینہ تخمینہ ہے، پیمانے کے لیے درکار ہے)۔

اس کے بعد، ہم نے مزید سوچنا شروع کیا - کیا ہم صحیح طریقے سے چیک کر رہے ہیں؟ کیا ہم پل کی درخواستوں پر تعمیرات کو صحیح طریقے سے چلا رہے ہیں؟

ہم نے اس شاخ کی آخری کمٹ پر تعمیر شروع کی جہاں سے پل کی درخواست کھولی گئی تھی۔ لیکن اس عہد کے ٹیسٹ صرف یہ دکھا سکتے ہیں کہ ڈویلپر نے جو کوڈ لکھا ہے وہ کام کرتا ہے۔ لیکن وہ ثابت نہیں کرتے کہ اس نے کچھ نہیں توڑا۔ درحقیقت، کسی خصوصیت کے ضم ہونے کے بعد آپ کو ڈیولپمنٹ برانچ کی حالت چیک کرنے کی ضرورت ہے۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

ایسا کرنے کے لیے، ہم نے ایک سادہ bash اسکرپٹ لکھا premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

یہاں ترقی سے تمام تازہ ترین تبدیلیوں کو آسانی سے کھینچ کر موجودہ برانچ میں ضم کر دیا گیا ہے۔ ہم نے premerge.sh اسکرپٹ کو تمام تعمیرات میں پہلے قدم کے طور پر شامل کیا اور بالکل وہی چیک کرنا شروع کیا جو ہم چاہتے ہیں، یعنی انضمام.

مسئلہ کو مقامی بنانے، حل تلاش کرنے اور اس اسکرپٹ کو لکھنے میں تین دن لگے۔

ایپلیکیشن تیار ہوئی، زیادہ سے زیادہ کام نمودار ہوئے، ٹیم میں اضافہ ہوا، اور premerge.sh کبھی کبھی ہمیں مایوس کرنے لگا۔ ڈویلپمنٹ میں متضاد تبدیلیاں تھیں جنہوں نے تعمیر کو توڑ دیا۔

یہ کیسے ہوتا ہے اس کی ایک مثال:

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

دو ڈویلپرز بیک وقت فیچر A اور B پر کام کرنا شروع کر دیتے ہیں۔ فیچر A کے ڈویلپر کو پروجیکٹ میں ایک غیر استعمال شدہ فیچر کا پتہ چلتا ہے۔ answer() اور، ایک اچھے لڑکے سکاؤٹ کی طرح، اسے ہٹاتا ہے۔ اسی وقت، فیچر B کے ڈویلپر نے اپنی برانچ میں اس فنکشن میں ایک نئی کال شامل کی ہے۔

ڈویلپر اپنا کام ختم کرتے ہیں اور اسی وقت پل کی درخواست کھولتے ہیں۔ تعمیرات شروع کر دی گئی ہیں، premerge.sh تازہ ترین ترقی کی حالت سے متعلق دونوں پل درخواستوں کی جانچ کرتا ہے - تمام چیکس سبز ہیں۔ اس کے بعد، خصوصیت A کی پل کی درخواست کو ضم کر دیا جاتا ہے، خصوصیت B کی پل کی درخواست کو ضم کر دیا جاتا ہے... Boom! ڈیولپ بریکس کیونکہ ڈیولپمنٹ کوڈ میں غیر موجود فنکشن کو کال ہوتی ہے۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

جب یہ ترقی نہیں کر رہا ہے، یہ ہے مقامی آفت. پوری ٹیم کچھ بھی جمع نہیں کر سکتی اور اسے جانچ کے لیے جمع نہیں کر سکتی۔

ایسا ہوا کہ میں نے اکثر بنیادی ڈھانچے کے کاموں پر کام کیا: تجزیات، نیٹ ورک، ڈیٹا بیس۔ یعنی، میں نے ہی وہ فنکشنز اور کلاسز لکھی ہیں جو دوسرے ڈویلپر استعمال کرتے ہیں۔ اس کی وجہ سے، میں نے خود کو اکثر ایسے ہی حالات میں پایا۔ یہاں تک کہ میں نے یہ تصویر تھوڑی دیر کے لیے لٹکی ہوئی تھی۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

چونکہ یہ ہمارے لیے مناسب نہیں تھا، اس لیے ہم نے اس کو روکنے کے طریقے تلاش کرنا شروع کر دیے۔

ترقی کو کیسے نہ توڑا جائے۔

پہلا اختیار: ترقی کو اپ ڈیٹ کرتے وقت تمام پل کی درخواستوں کو دوبارہ بنائیں۔ اگر، ہماری مثال میں، خصوصیت A کے ساتھ پل کی درخواست سب سے پہلے ڈیولپمنٹ میں شامل کی گئی ہے، تو فیچر B کی پل کی درخواست کو دوبارہ بنایا جائے گا، اور، اس کے مطابق، تالیف کی خرابی کی وجہ سے چیک ناکام ہو جائیں گے۔

یہ سمجھنے کے لیے کہ اس میں کتنا وقت لگے گا، دو PR کے ساتھ ایک مثال پر غور کریں۔ ہم دو PRs کھولتے ہیں: دو تعمیرات، دو رن آف چیک۔ پہلے PR کو ترقی میں ضم کرنے کے بعد، دوسرے کو دوبارہ تعمیر کرنے کی ضرورت ہے۔ مجموعی طور پر، دو PRs کے لیے تین رنز کی جانچ کی ضرورت ہوتی ہے: 2 + 1 = 3۔

اصول میں، یہ ٹھیک ہے. لیکن ہم نے اعداد و شمار کو دیکھا، اور ہماری ٹیم میں عام صورت حال 10 اوپن پی آرز تھی، اور پھر چیکوں کی تعداد ترقی کا مجموعہ ہے: 10 + 9 +... + 1 = 55۔ یعنی 10 کو قبول کرنا PRs، آپ کو 55 بار دوبارہ تعمیر کرنے کی ضرورت ہے۔ اور یہ ایک مثالی صورت حال میں ہے، جب تمام چیک پہلی بار پاس ہو جاتے ہیں، جب کوئی بھی اضافی پل کی درخواست نہیں کھولتا ہے جب کہ یہ درجن بھر کارروائی ہو رہی ہے۔

اپنے آپ کو ایک ایسے ڈویلپر کے طور پر تصور کریں جسے "ضم کریں" بٹن پر کلک کرنے کے لیے سب سے پہلے بننے کی ضرورت ہے، کیونکہ اگر کوئی پڑوسی ایسا کرتا ہے، تو آپ کو اس وقت تک انتظار کرنا پڑے گا جب تک کہ تمام تعمیرات دوبارہ نہ ہو جائیں... نہیں، یہ کام نہیں کرے گا۔ ، یہ سنجیدگی سے ترقی کو سست کردے گا۔

دوسرا ممکنہ طریقہ: کوڈ کا جائزہ لینے کے بعد پل کی درخواستیں جمع کریں۔ یعنی، آپ ایک پل کی درخواست کھولتے ہیں، ساتھیوں سے منظوریوں کی مطلوبہ تعداد جمع کرتے ہیں، جس چیز کی ضرورت ہے اسے درست کریں، اور پھر تعمیرات شروع کریں۔ اگر وہ کامیاب ہو جاتے ہیں، تو پل کی درخواست کو ترقی میں ضم کر دیا جاتا ہے۔ اس صورت میں، کوئی اضافی دوبارہ شروع نہیں ہے، لیکن رائے بہت سست ہے. ایک ڈویلپر کے طور پر، جب میں پل کی درخواست کھولتا ہوں، میں فوراً یہ دیکھنا چاہتا ہوں کہ آیا یہ کام کر رہا ہے۔ مثال کے طور پر، اگر کوئی ٹیسٹ ناکام ہوجاتا ہے، تو آپ کو اسے فوری طور پر ٹھیک کرنے کی ضرورت ہے۔ تاخیر سے تعمیر کی صورت میں، فیڈ بیک سست ہوجاتا ہے، اور اس وجہ سے پوری ترقی۔ یہ ہمیں بھی مناسب نہیں تھا۔

نتیجے کے طور پر، صرف تیسرا آپشن رہ گیا - موٹر سائیکل. ہمارے تمام کوڈ، ہمارے تمام ذرائع بٹ بکٹ سرور پر ایک ذخیرہ میں محفوظ ہیں۔ اس کے مطابق، ہمیں Bitbucket کے لیے ایک پلگ ان تیار کرنا تھا۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

یہ پلگ ان پل کی درخواست کو ضم کرنے کے طریقہ کار کو اوور رائیڈ کرتا ہے۔ آغاز معیاری ہے: PR کھلتا ہے، تمام اسمبلیاں شروع ہوتی ہیں، کوڈ کا جائزہ مکمل ہوتا ہے۔ لیکن کوڈ کا جائزہ مکمل ہونے کے بعد اور ڈویلپر "مرج" پر کلک کرنے کا فیصلہ کرتا ہے، پلگ ان چیک کرتا ہے کہ کس ڈیولپمنٹ سٹیٹ کے خلاف چیک چلائے گئے تھے۔ اگر ڈیولپمنٹ کو بنانے کے بعد اپ ڈیٹ کر دیا گیا ہے، تو پلگ ان اس طرح کی پل کی درخواست کو مین برانچ میں ضم ہونے کی اجازت نہیں دے گا۔ یہ نسبتاً حالیہ ترقی کی تعمیرات کو آسانی سے دوبارہ شروع کر دے گا۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

متضاد تبدیلیوں کے ساتھ ہماری مثال میں، اس طرح کی تعمیرات تالیف کی خرابی کی وجہ سے ناکام ہو جائیں گی۔ اس کے مطابق، فیچر B کے ڈویلپر کو کوڈ کو درست کرنا ہوگا، چیک کو دوبارہ شروع کرنا ہوگا، پھر پلگ ان خود بخود پل کی درخواست کو لاگو کردے گا۔

اس پلگ ان کو لاگو کرنے سے پہلے، ہم نے اوسطاً 2,7 ریویو رنز فی پل کی درخواست کی۔ پلگ ان کے ساتھ 3,6 لانچ ہوئے۔ یہ ہمارے لیے موزوں تھا۔

یہ بات قابل غور ہے کہ اس پلگ ان میں ایک خرابی ہے: یہ صرف ایک بار تعمیر کو دوبارہ شروع کرتا ہے۔ یعنی اب بھی ایک چھوٹی سی کھڑکی باقی ہے جس کے ذریعے متضاد تبدیلیاں ترقی کر سکتی ہیں۔ لیکن اس کا امکان کم ہے، اور ہم نے شروع کی تعداد اور ناکامی کے امکان کے درمیان یہ تجارت کی ہے۔ دو سالوں میں اس نے صرف ایک بار فائر کیا، اس لیے یہ شاید بیکار نہیں تھا۔

بٹ بکٹ پلگ ان کا پہلا ورژن لکھنے میں ہمیں دو ہفتے لگے۔

نئے چیک

اس دوران ہماری ٹیم بڑھتی چلی گئی۔ نئے چیک شامل کیے گئے ہیں۔

ہم نے سوچا: اگر ان کو روکا جا سکتا ہے تو غلطیاں کیوں کریں؟ اور اسی لیے انہوں نے عمل درآمد کیا۔ جامد کوڈ تجزیہ. ہم نے lint کے ساتھ شروعات کی، جو Android SDK میں شامل ہے۔ لیکن اس وقت وہ کوٹلن کوڈ کے ساتھ کام کرنے کا طریقہ بالکل نہیں جانتا تھا، اور ہمارے پاس پہلے سے ہی 75% درخواست کوٹلن میں لکھی ہوئی تھی۔ لہذا، بلٹ ان کو لنٹ میں شامل کیا گیا تھا۔ اینڈرائیڈ اسٹوڈیو چیک کرتا ہے۔

ایسا کرنے کے لیے، ہمیں بہت زیادہ بگاڑنا پڑا: اینڈرائیڈ اسٹوڈیو لیں، اسے ڈوکر میں پیک کریں اور اسے ورچوئل مانیٹر کے ساتھ CI پر چلائیں، تاکہ یہ سمجھے کہ یہ اصلی لیپ ٹاپ پر چل رہا ہے۔ لیکن اس نے کام کیا۔

اس دوران ہم نے بہت کچھ لکھنا بھی شروع کیا۔ آلات کے ٹیسٹ اور لاگو کیا اسکرین شاٹ ٹیسٹنگ. یہ تب ہوتا ہے جب ایک الگ چھوٹے منظر کے لیے ایک حوالہ اسکرین شاٹ تیار کیا جاتا ہے، اور ٹیسٹ میں منظر سے اسکرین شاٹ لینے اور اس کا موازنہ معیاری براہ راست پکسل بائی پکسل کے ساتھ کرنا ہوتا ہے۔ اگر کوئی تضاد ہے تو اس کا مطلب ہے کہ لے آؤٹ کہیں غلط ہو گیا ہے یا سٹائلز میں کچھ گڑبڑ ہے۔

لیکن آلات کے ٹیسٹ اور اسکرین شاٹ ٹیسٹ آلات پر چلانے کی ضرورت ہے: ایمولیٹرز پر یا حقیقی آلات پر۔ اس بات پر غور کرتے ہوئے کہ بہت سارے ٹیسٹ ہیں اور وہ کثرت سے چلائے جاتے ہیں، ایک پورے فارم کی ضرورت ہے۔ اپنا فارم شروع کرنا بہت محنت طلب ہے، اس لیے ہمیں ایک ریڈی میڈ آپشن ملا - Firebase Test Lab۔

فائر بیس ٹیسٹ لیب

اس کا انتخاب اس لیے کیا گیا کیونکہ Firebase ایک Google پروڈکٹ ہے، یعنی اسے قابل اعتماد ہونا چاہیے اور اس کے مرنے کا امکان نہیں ہے۔ قیمتیں مناسب ہیں: حقیقی ڈیوائس کے آپریشن کے فی گھنٹہ $5، ایمولیٹر کے آپریشن کے فی گھنٹہ $1۔

ہمارے CI میں Firebase ٹیسٹ لیب کو لاگو کرنے میں تقریباً تین ہفتے لگے۔

لیکن ٹیم بڑھتی رہی، اور فائربیس نے بدقسمتی سے ہمیں مایوس کرنا شروع کیا۔ اس وقت، اس کے پاس کوئی SLA نہیں تھا۔ بعض اوقات Firebase نے ہمیں اس وقت تک انتظار کرنے پر مجبور کیا جب تک کہ آلات کی مطلوبہ تعداد ٹیسٹوں کے لیے مفت نہ ہو، اور جیسا کہ ہم چاہتے تھے فوری طور پر ان پر عمل درآمد شروع نہیں کیا۔ لائن میں انتظار کرنے میں آدھا گھنٹہ لگ گیا جو کہ بہت طویل وقت ہے۔ آلات کے ٹیسٹ ہر PR پر چلائے جاتے تھے، تاخیر نے واقعی ترقی کو سست کر دیا، اور پھر ماہانہ بل ایک گول رقم کے ساتھ آیا۔ عام طور پر، فائر بیس کو چھوڑ کر اندرون ملک کام کرنے کا فیصلہ کیا گیا تھا، کیونکہ ٹیم کافی بڑھ چکی تھی۔

Docker + Python + bash

ہم نے Docker کو لیا، اس میں ایمولیٹر بھرے ہوئے، Python میں ایک سادہ پروگرام لکھا، جو صحیح وقت پر مطلوبہ ورژن میں ایمولیٹرز کی مطلوبہ تعداد لاتا ہے اور ضرورت پڑنے پر انہیں روک دیتا ہے۔ اور، ظاہر ہے، ایک دو باش اسکرپٹس - ہم ان کے بغیر کہاں ہوں گے؟

ہمارا اپنا ٹیسٹ ماحول بنانے میں پانچ ہفتے لگے۔

نتیجے کے طور پر، ہر پل کی درخواست کے لیے چیک کی ایک وسیع ضم بلاک کرنے والی فہرست موجود تھی:

  • اے آر کے اسمبلی؛
  • جنیٹ ٹیسٹ؛
  • لنٹ;
  • اینڈرائیڈ اسٹوڈیو چیک کرتا ہے؛
  • آلات کے ٹیسٹ؛
  • اسکرین شاٹ ٹیسٹ۔

اس نے بہت سے ممکنہ خرابیوں کو روک دیا۔ تکنیکی طور پر سب کچھ کام کر گیا، لیکن ڈویلپرز نے شکایت کی کہ نتائج کا انتظار بہت طویل تھا۔

کتنا لمبا ہے؟ ہم نے Bitbucket اور TeamCity سے ڈیٹا کو تجزیہ کے نظام میں اپ لوڈ کیا اور اس کا احساس ہوا۔ اوسط انتظار کا وقت 45 منٹ. یعنی، ایک ڈویلپر، جب پل کی درخواست کھولتا ہے، تعمیر کے نتائج کے لیے اوسطاً 45 منٹ انتظار کرتا ہے۔ میری رائے میں، یہ بہت کچھ ہے، اور آپ اس طرح کام نہیں کر سکتے۔

یقینا، ہم نے اپنی تمام تعمیرات کو تیز کرنے کا فیصلہ کیا۔

آئیے تیز کرتے ہیں۔

یہ دیکھ کر کہ بلڈس اکثر قطار میں کھڑے ہوتے ہیں، سب سے پہلے ہم یہ کرتے ہیں۔ مزید ہارڈ ویئر خریدا - وسیع ترقی سب سے آسان ہے۔ عمارتوں نے قطار لگانا بند کر دیا، لیکن انتظار کا وقت صرف تھوڑا سا کم ہوا، کیونکہ کچھ چیکوں میں خود کافی وقت لگتا ہے۔

بہت زیادہ وقت لینے والے چیک کو ہٹانا

ہمارا مسلسل انضمام اس قسم کی غلطیوں اور مسائل کو پکڑ سکتا ہے۔

  • نہیں جا رہی. جب کوئی چیز متضاد تبدیلیوں کی وجہ سے نہیں بنتی ہے تو CI تالیف کی غلطی پکڑ سکتا ہے۔ جیسا کہ میں نے پہلے ہی کہا تھا، پھر کوئی کچھ نہیں جمع کر سکتا، ترقی رک جاتی ہے، اور سب گھبرا جاتے ہیں۔
  • رویے میں بگ. مثال کے طور پر، جب ایپلیکیشن بنتی ہے، لیکن بٹن دبانے پر کریش ہو جاتی ہے، یا بٹن بالکل نہیں دبایا جاتا ہے۔ یہ برا ہے کیونکہ ایسا بگ صارف تک پہنچ سکتا ہے۔
  • لے آؤٹ میں بگ. مثال کے طور پر، ایک بٹن پر کلک کیا گیا ہے، لیکن 10 پکسلز بائیں طرف منتقل ہو گیا ہے۔
  • تکنیکی قرضوں میں اضافہ.

اس فہرست کو دیکھنے کے بعد، ہم نے محسوس کیا کہ صرف پہلے دو نکات ہی اہم ہیں۔ ہم پہلے ایسے مسائل کو پکڑنا چاہتے ہیں۔ لے آؤٹ میں کیڑے ڈیزائن کے جائزے کے مرحلے پر دریافت ہوتے ہیں اور پھر آسانی سے درست کیے جا سکتے ہیں۔ تکنیکی قرض سے نمٹنے کے لیے ایک الگ عمل اور منصوبہ بندی کی ضرورت ہوتی ہے، اس لیے ہم نے پل کی درخواست پر اس کی جانچ نہ کرنے کا فیصلہ کیا۔

اس درجہ بندی کی بنیاد پر، ہم نے چیک کی پوری فہرست کو ہلا دیا۔ لنٹ کو کراس آؤٹ کیا۔ اور اس کا آغاز راتوں رات ملتوی کر دیا: صرف اس لیے کہ یہ رپورٹ پیش کرے کہ اس منصوبے میں کتنے مسائل تھے۔ ہم نے تکنیکی قرض کے ساتھ الگ سے کام کرنے پر اتفاق کیا، اور اینڈرائیڈ اسٹوڈیو کی جانچ مکمل طور پر ترک کردی گئی تھی۔. ڈوکر میں اینڈرائیڈ اسٹوڈیو انسپکشن چلانے کے لیے دلچسپ لگتا ہے، لیکن سپورٹ میں کافی پریشانی کا سبب بنتا ہے۔ اینڈرائیڈ اسٹوڈیو ورژن میں کسی بھی اپ ڈیٹ کا مطلب ناقابل فہم کیڑوں کے ساتھ جدوجہد ہے۔ اسکرین شاٹ ٹیسٹ کو سپورٹ کرنا بھی مشکل تھا، کیونکہ لائبریری زیادہ مستحکم نہیں تھی اور غلط مثبت تھے۔ اسکرین شاٹ ٹیسٹ کو چیک لسٹ سے ہٹا دیا گیا ہے۔.

نتیجے کے طور پر، ہمارے پاس رہ گیا:

  • اے آر کے اسمبلی؛
  • جنیٹ ٹیسٹ؛
  • آلات کے ٹیسٹ۔

گریڈل ریموٹ کیش

بھاری جانچ پڑتال کے بغیر، سب کچھ بہتر ہو گیا. لیکن کمال کی کوئی حد نہیں ہے!

ہماری درخواست کو پہلے ہی تقریباً 150 گریڈ ماڈیولز میں تقسیم کیا گیا تھا۔ گریڈل ریموٹ کیش عام طور پر اس معاملے میں اچھی طرح کام کرتا ہے، لہذا ہم نے اسے آزمانے کا فیصلہ کیا۔

گریڈل ریموٹ کیش ایک ایسی خدمت ہے جو انفرادی ماڈیولز میں انفرادی کاموں کے لیے تعمیراتی نمونے کیش کر سکتی ہے۔ گریڈل، اصل میں کوڈ کو مرتب کرنے کے بجائے، ریموٹ کیش پر دستک دینے کے لیے HTTP کا استعمال کرتا ہے اور پوچھتا ہے کہ کیا کسی نے یہ کام پہلے ہی انجام دیا ہے۔ اگر ہاں، تو یہ صرف نتیجہ ڈاؤن لوڈ کرتا ہے۔

Gradle ریموٹ کیشے کو چلانا آسان ہے کیونکہ Gradle ایک Docker امیج فراہم کرتا ہے۔ ہم یہ کام تین گھنٹوں میں کرنے میں کامیاب ہو گئے۔

آپ کو بس ڈوکر لانچ کرنا تھا اور پروجیکٹ میں ایک لائن لکھنا تھا۔ لیکن اگرچہ اسے تیزی سے لانچ کیا جا سکتا ہے، لیکن ہر چیز کو اچھی طرح سے کام کرنے میں کافی وقت لگے گا۔

ذیل میں کیش مسز گراف ہے۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

بالکل شروع میں، کیش کی کمی کا فیصد تقریباً 65 تھا۔ تین ہفتوں کے بعد، ہم اس قدر کو 20% تک بڑھانے میں کامیاب ہو گئے۔ پتہ چلا کہ اینڈرائیڈ ایپلی کیشن جن کاموں کو اکٹھا کرتی ہے ان میں عجیب عبوری انحصار ہوتا ہے، جس کی وجہ سے گریڈل کیشے سے محروم رہتا ہے۔

کیشے کو جوڑ کر، ہم نے تعمیر کو بہت تیز کیا۔ لیکن اسمبلی کے علاوہ، آلات کے ٹیسٹ بھی ہیں، اور ان میں کافی وقت لگتا ہے۔ شاید ہر پل کی درخواست کے لئے تمام ٹیسٹ چلانے کی ضرورت نہیں ہے۔ یہ جاننے کے لیے، ہم اثر تجزیہ کا استعمال کرتے ہیں۔

اثر تجزیہ

پل کی درخواست پر، ہم git diff جمع کرتے ہیں اور ترمیم شدہ گریڈل ماڈیولز تلاش کرتے ہیں۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

صرف انسٹرومینٹیشن ٹیسٹ چلانا سمجھ میں آتا ہے جو بدلے ہوئے ماڈیولز اور ان پر منحصر تمام ماڈیولز کو چیک کرتے ہیں۔ پڑوسی ماڈیولز کے لیے ٹیسٹ چلانے کا کوئی فائدہ نہیں ہے: وہاں کا کوڈ تبدیل نہیں ہوا ہے اور کچھ بھی نہیں ٹوٹ سکتا ہے۔

انسٹرومینٹیشن ٹیسٹ اتنے آسان نہیں ہیں، کیونکہ ان کو اعلیٰ سطح کے ایپلیکیشن ماڈیول میں ہونا چاہیے۔ ہم نے بائیک کوڈ تجزیہ کے ساتھ ہیورسٹکس کو یہ سمجھنے کے لیے استعمال کیا کہ ہر ٹیسٹ کا تعلق کس ماڈیول سے ہے۔

انسٹرومینٹیشن ٹیسٹ کے آپریشن کو اپ گریڈ کرنا تاکہ وہ صرف اس میں شامل ماڈیولز کی جانچ کریں تقریباً آٹھ ہفتے لگے۔

معائنہ کو تیز کرنے کے اقدامات نے کامیابی سے کام کیا ہے۔ 45 منٹ سے ہم تقریباً 15 تک چلے گئے۔ ایک تعمیر کے لیے چوتھائی گھنٹے انتظار کرنا پہلے سے ہی معمول ہے۔

لیکن اب ڈویلپرز نے شکایت کرنا شروع کر دی ہے کہ انہیں سمجھ نہیں آ رہی کہ کون سی بلڈز لانچ کی جا رہی ہیں، لاگ کہاں سے دیکھیں، بلڈ ریڈ کیوں ہے، کون سا ٹیسٹ فیل ہوا وغیرہ۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

تاثرات کے ساتھ مسائل ترقی کو سست کرتے ہیں، لہذا ہم نے ہر PR اور تعمیر کے بارے میں واضح اور تفصیلی معلومات فراہم کرنے کی کوشش کی۔ ہم نے Bitbucket to PR میں تبصرے کے ساتھ شروعات کی، جس سے یہ ظاہر ہوتا ہے کہ کون سی تعمیر ناکام ہوئی اور کیوں، اور Slack میں ہدفی پیغامات لکھے۔ آخر میں، ہم نے صفحہ کے لیے ایک PR ڈیش بورڈ بنایا ہے جس میں ان تمام تعمیرات کی فہرست ہے جو فی الحال چل رہی ہیں اور ان کی حیثیت: قطار بند، چل رہی، کریش یا مکمل۔ آپ بلڈ پر کلک کر کے اس کے لاگ پر جا سکتے ہیں۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

تفصیلی آراء پر چھ ہفتے گزارے گئے۔

منصوبے

آئیے حالیہ تاریخ کی طرف چلتے ہیں۔ فیڈ بیک کے مسئلے کو حل کرنے کے بعد، ہم ایک نئی سطح پر پہنچ گئے - ہم نے اپنا ایمولیٹر فارم بنانے کا فیصلہ کیا۔ جب بہت سے ٹیسٹ اور ایمولیٹر ہوتے ہیں تو ان کا انتظام کرنا مشکل ہوتا ہے۔ نتیجے کے طور پر، ہمارے تمام ایمولیٹرز لچکدار وسائل کے انتظام کے ساتھ k8s کلسٹر میں چلے گئے۔

اس کے علاوہ اور بھی منصوبے ہیں۔

  • ریٹرن لنٹ (اور دیگر جامد تجزیہ)۔ ہم پہلے ہی اس سمت میں کام کر رہے ہیں۔
  • ہر چیز کو PR بلاکر پر چلائیں۔ آخر سے آخر تک ٹیسٹ تمام SDK ورژن پر۔

لہذا، ہم نے Avito میں مسلسل انضمام کی ترقی کی تاریخ کا سراغ لگایا ہے. اب میں ایک تجربہ کار نقطہ نظر سے کچھ مشورہ دینا چاہتا ہوں۔

Советы

اگر میں صرف ایک مشورہ دے سکتا ہوں تو یہ ہوگا:

براہ کرم شیل اسکرپٹ سے محتاط رہیں!

باش ایک بہت لچکدار اور طاقتور ٹول ہے، اسکرپٹ لکھنا بہت آسان اور تیز ہے۔ لیکن آپ اس کے ساتھ جال میں پھنس سکتے ہیں، اور بدقسمتی سے، ہم اس میں پھنس گئے۔

یہ سب سادہ اسکرپٹ کے ساتھ شروع ہوا جو ہماری تعمیراتی مشینوں پر چلتی ہیں:

#!/usr/bin/env bash
./gradlew assembleDebug

لیکن، جیسا کہ آپ جانتے ہیں، وقت کے ساتھ ساتھ ہر چیز تیار ہوتی ہے اور مزید پیچیدہ ہوتی جاتی ہے - آئیے ایک اسکرپٹ کو دوسرے سے چلاتے ہیں، آئیے وہاں کچھ پیرامیٹرز کو پاس کرتے ہیں - آخر میں ہمیں ایک فنکشن لکھنا پڑا جو اس بات کا تعین کرتا ہے کہ اب ہم کس سطح پر بیش نیسٹنگ کی ترتیب میں ہیں۔ ضروری اقتباسات داخل کرنے کے لیے، یہ سب شروع کرنے کے لیے۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

آپ اس طرح کے اسکرپٹ کی ترقی کے لیے مزدوری کے اخراجات کا تصور کر سکتے ہیں۔ میں تمہیں مشورہ دیتا ہوں کہ اس جال میں نہ پڑو۔

کیا تبدیل کیا جا سکتا ہے؟

  • کوئی بھی اسکرپٹنگ زبان۔ کو لکھیں ازگر یا کوٹلن اسکرپٹ زیادہ آسان کیونکہ یہ پروگرامنگ ہے، اسکرپٹ نہیں۔
  • یا فارم میں تمام تعمیراتی منطق کو بیان کریں۔ حسب ضرورت گریڈل ٹاسکس آپ کے منصوبے کے لئے.

ہم نے دوسرا آپشن منتخب کرنے کا فیصلہ کیا، اور اب ہم منظم طریقے سے تمام bash اسکرپٹس کو حذف کر رہے ہیں اور بہت سے حسب ضرورت گریڈل کام لکھ رہے ہیں۔

ٹپ #2: کوڈ میں انفراسٹرکچر اسٹور کریں۔

یہ آسان ہوتا ہے جب مسلسل انضمام کی ترتیب جینکنز یا ٹیم سٹی وغیرہ کے UI انٹرفیس میں نہیں بلکہ ٹیکسٹ فائلوں کی شکل میں براہ راست پروجیکٹ کے ذخیرے میں محفوظ کی جاتی ہے۔ یہ ورژن کی اہلیت دیتا ہے۔ کسی اور برانچ پر کوڈ کو رول بیک کرنا یا بنانا مشکل نہیں ہوگا۔

اسکرپٹ کو پروجیکٹ میں محفوظ کیا جاسکتا ہے۔ ماحول کے ساتھ کیا کرنا ہے؟

ٹپ #3: ڈوکر ماحول میں مدد کر سکتا ہے۔

یہ یقینی طور پر اینڈرائیڈ ڈویلپرز کی مدد کرے گا؛ بدقسمتی سے iOS کے پاس ابھی تک کوئی نہیں ہے۔

یہ ایک سادہ ڈوکر فائل کی مثال ہے جس میں jdk اور android-sdk شامل ہیں:

FROM openjdk:8

ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" 
    ANDROID_HOME="/usr/local/android-sdk" 
    ANDROID_VERSION=26 
    ANDROID_BUILD_TOOLS_VERSION=26.0.2

# Download Android SDK
RUN mkdir "$ANDROID_HOME" .android 
    && cd "$ANDROID_HOME" 
    && curl -o sdk.zip $SDK_URL 
    && unzip sdk.zip 
    && rm sdk.zip 
    && yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses

# Install Android Build Tool and Libraries
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" 
    "platforms;android-${ANDROID_VERSION}" 
    "platform-tools"

RUN mkdir /application
WORKDIR /application

اس ڈوکر فائل کو لکھنے کے بعد (میں آپ کو ایک راز بتاتا ہوں، آپ کو اسے لکھنے کی ضرورت نہیں ہے، بلکہ صرف اسے GitHub سے تیار کر کے کھینچیں) اور تصویر کو اسمبل کرنے کے بعد، آپ کو ایک ورچوئل مشین ملتی ہے جس پر آپ ایپلی کیشن بنا سکتے ہیں۔ اور Junit ٹیسٹ چلائیں۔

دو اہم وجوہات جن کی وجہ سے یہ سمجھ میں آتا ہے وہ ہیں اسکیل ایبلٹی اور ریپیٹ ایبلٹی۔ ڈوکر کا استعمال کرتے ہوئے، آپ تیزی سے ایک درجن بلڈ ایجنٹس کو اکٹھا کر سکتے ہیں جن کا بالکل وہی ماحول ہو گا جیسا کہ پچھلے والے۔ اس سے CI انجینئرز کی زندگی بہت آسان ہو جاتی ہے۔ android-sdk کو docker میں دھکیلنا کافی آسان ہے، لیکن ایمولیٹرز کے ساتھ یہ قدرے مشکل ہے: آپ کو تھوڑی محنت کرنی پڑے گی (یا GitHub سے تیار شدہ کو دوبارہ ڈاؤن لوڈ کریں)۔

ٹپ نمبر 4: یہ نہ بھولیں کہ معائنے معائنے کے لیے نہیں بلکہ لوگوں کے لیے کیے جاتے ہیں۔

فوری اور سب سے اہم بات، واضح فیڈ بیک ڈویلپرز کے لیے بہت اہم ہے: کیا ٹوٹ گیا، کون سا ٹیسٹ ناکام ہوا، میں بلڈ لاگ کہاں دیکھ سکتا ہوں۔

ٹپ #5: مسلسل انٹیگریشن تیار کرتے وقت عملی بنیں۔

واضح طور پر سمجھیں کہ آپ کس قسم کی غلطیوں کو روکنا چاہتے ہیں، آپ کتنے وسائل، وقت اور کمپیوٹر کا وقت خرچ کرنے کو تیار ہیں۔ بہت زیادہ وقت لینے والے چیکس، مثال کے طور پر، راتوں رات ملتوی ہو سکتے ہیں۔ اور ان میں سے جو بہت اہم غلطیاں نہیں پکڑتے انہیں مکمل طور پر ترک کر دینا چاہیے۔

ٹپ #6: ریڈی میڈ ٹولز استعمال کریں۔

اب بہت سی کمپنیاں ہیں جو کلاؤڈ CI فراہم کرتی ہیں۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

چھوٹی ٹیموں کے لیے یہ ایک اچھا حل ہے۔ آپ کو کسی بھی چیز کی حمایت کرنے کی ضرورت نہیں ہے، صرف تھوڑا سا پیسہ ادا کریں، اپنی درخواست بنائیں اور یہاں تک کہ آلات کے ٹیسٹ بھی چلائیں۔

ٹپ #7: ایک بڑی ٹیم میں، اندرون ملک حل زیادہ منافع بخش ہوتے ہیں۔

لیکن جلد یا بدیر، جیسے جیسے ٹیم بڑھے گی، اندرون ملک حل زیادہ منافع بخش ہو جائیں گے۔ ان فیصلوں میں ایک مسئلہ ہے۔ معاشیات میں منافع کو کم کرنے کا ایک قانون ہے: کسی بھی منصوبے میں، ہر بعد کی بہتری زیادہ سے زیادہ مشکل ہوتی ہے اور اس کے لیے زیادہ سے زیادہ سرمایہ کاری کی ضرورت ہوتی ہے۔

معاشیات ہماری پوری زندگی کو بیان کرتی ہے، بشمول مسلسل انضمام۔ میں نے اپنے مسلسل انضمام کی ترقی کے ہر مرحلے کے لیے مزدوری کے اخراجات کا ایک شیڈول بنایا۔

موبائل ڈویلپمنٹ ٹیم میں CI کا ارتقاء

یہ واضح ہے کہ کوئی بھی بہتری مشکل سے مشکل تر ہوتی جارہی ہے۔ اس گراف کو دیکھ کر، آپ سمجھ سکتے ہیں کہ مسلسل انضمام کو ٹیم کے سائز کی ترقی کے مطابق تیار کرنے کی ضرورت ہے۔ دو افراد کی ٹیم کے لیے، اندرونی ایمولیٹر فارم تیار کرنے میں 50 دن گزارنا ایک معمولی خیال ہے۔ لیکن ایک ہی وقت میں، ایک بڑی ٹیم کے لیے، Continuous Integration بالکل نہ کرنا بھی برا خیال ہے، کیونکہ انضمام کے مسائل، مواصلات کو ٹھیک کرنا وغیرہ۔ یہ اور بھی زیادہ وقت لگے گا.

ہم نے اس خیال سے آغاز کیا کہ آٹومیشن کی ضرورت ہے کیونکہ لوگ مہنگے ہیں، وہ غلطیاں کرتے ہیں اور سست ہیں۔ لیکن لوگ خودکار بھی ہوتے ہیں۔ لہذا، تمام ایک جیسے مسائل آٹومیشن پر لاگو ہوتے ہیں.

  • آٹومیشن مہنگا ہے۔ مزدوری کا شیڈول یاد رکھیں۔
  • جب آٹومیشن کی بات آتی ہے تو لوگ غلطیاں کرتے ہیں۔
  • کبھی کبھی یہ خودکار کرنے میں بہت سست ہوتا ہے، کیونکہ سب کچھ اس طرح کام کرتا ہے۔ کچھ اور کیوں بہتر، یہ سب مسلسل انضمام کیوں؟

لیکن میرے پاس اعدادوشمار ہیں: 20% اسمبلیوں میں غلطیاں پکڑی جاتی ہیں۔ اور اس کی وجہ یہ نہیں ہے کہ ہمارے ڈویلپرز کوڈ خراب لکھتے ہیں۔ اس کی وجہ یہ ہے کہ ڈویلپرز کو یقین ہے کہ اگر وہ کچھ غلطی کرتے ہیں، تو یہ ترقی میں ختم نہیں ہوگی، اسے خودکار جانچ کے ذریعے پکڑا جائے گا۔ اس کے مطابق، ڈویلپرز مقامی طور پر کسی چیز کو چلانے اور جانچنے کے بجائے کوڈ اور دلچسپ چیزیں لکھنے میں زیادہ وقت صرف کر سکتے ہیں۔

مسلسل انضمام کی مشق کریں۔ لیکن اعتدال میں۔

ویسے نکولائی نیسٹروف نہ صرف خود بڑی اچھی رپورٹیں دیتے ہیں بلکہ پروگرام کمیٹی کے ممبر بھی ہیں۔ AppsConf اور دوسروں کو آپ کے لیے بامعنی تقریریں تیار کرنے میں مدد کرتا ہے۔ اگلے کانفرنس کے پروگرام کی تکمیل اور افادیت کا اندازہ اس کے عنوانات سے لگایا جا سکتا ہے۔ شیڈول. اور تفصیلات کے لیے 22-23 اپریل کو Infospace پر آئیں۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں