این پست ترجمهای از وبلاگ Mitchell Hashimoto تحت عنوان «Contributing to Complex Projects» است.
به عنوان یک مشارکتکننده و نگهدارنده دائمی در پروژههای متنباز، متدواما از من سوال میشه که: از کجا شروع میکنی؟ رویکردت برای ایجاد یک تغییر معنادار در پروژه جدید چیه؟ چطور ممکنه که بشه جزئیات داخلی یک پروژه پیچیده رو متوجه شد؟
این سوالات برای هر نوع پروژه نرمافزاری، چه متنباز باشن یا اختصاصی، و چه حرفهای باشن یا برای تفریح صادق هستن. رویکرد من برای همه این حالات یکسانه. اگرچه، یک تفاوت اساسی در پروژههای حرفهای اینه که شما به مهندسینی که مایلن تا به شما کمک کنن — اگه مجبور نباشن — دسترسی دارید، درحالی که در پروژههای متنباز بیشتر کار پای شماست.
من الگویی تکراری برای نزدیکشدن به پروژههای پیچیده ایجاد کردم که در این پست مستندسازی شده. انتظار ندارم که این الگو برای همه جواب بده، اما امیدوارم برای سایر کسانی که اعتماد به نفس کافی برای مشارکت و تلاش برای یادگیری پروژههای پیچیده دارن کمککننده باشه.
من از عبارت «پروژه پیچیده» برای توصیف هر پروژه نرمافزاری استفاده میکنم که فهم پیادهسازیش بدیهی نباشه. این تعریف یک تعریف شخصیه؛ ممکنه بعضی افراد پروژههایی رو پیچیده بدونن که برای سایر افراد پیچیده نیست، و برعکس.
اولین گام برای فهمیدن جزئیات داخلی هر پروژهای اینه که کاربر اون پروژه بشید. حتما لزومی نداره که یک کاربر متخصص بشید، اما معیار شخصی من برای فراغت از این گام اینه که سعی کنید چیزی واقعی با این پروژه بسازید، حتی اگه کوچیک یا ساده باشه. به عنوان مثال، من قبل از مشارکت در زبان برنامهنویسی Zig، چندین کتابخانه واقعی نوشتم.
به عنوان یک کاربر، شما درک گستردهای از قابلیت های پروژه کسب میکنید. تفاوت فاحشی بین خوندن مستندات مرجع یک پروژه و استفاده از اون در عمل وجود داره، و ساخت پروژههای کوچک گام مهمی برای رسیدن از درک تئوری به عملیه.
علاوه بر این، شما شروع به یادگیری اصطلاحات پروژه که رنگ فرهنگی پروژه رو شکل میده میکنید و کمک میکنه تا بفهیمد چرا پروژه اینطوری کار میکنه، چرا این قابلیتها رو داره، و غیره. این موضوع مهمیه چرا که کمک میکنه تا یکدلی بین کسانی که روی پروژه کار میکنن شکل بگیره و همچنین به عنوان راهنمایی عمل میکنه که چه تغییراتی در پروژه منطقیه و چه تغییراتی منطقی نیست.
من همچنین توصیه میکنم که در این نقطه وارد کامیونیتی و اجتماعات اون پروژه بشید. به IRC و یا دیسکورد اون پروژه ملحق بشید، در ملاقاتهای محلی شرکت کنید، سخنرانیهاشو ببینید، و غیره. تا یک مدت زمانی بیشتر گوش بدید تا اینکه صحبت کنید. هدف در این قسمت اینه که همدلی کسب کنید و بفهمید که پروژه چطور کار میکنه. بعضی اوقات تعجب میکنم از اینکه چقدر از تماشا کردن یادگرفتنهای بقیه یادمیگیرم.
یادبگیرید که چطور پروژه رو بیلد کنید و یک باینری (و یا معادلش) که کار میکنه تولید کنید. خودتونو با فهمیدن سیستمی که بیلد رو انجام میده، وابستگیهای پروژه و ... درگیر نکنید. فقط برید سراغ راهنماها، وب سایتها، و هر چیزی که به طور قابل اتکا و تکرارپذیری شما رو از سورس کد به یک باینری قابل اجرا در سیستم میرسونه.
قبل از یادگرفتن نحوه بیلد کردن پروژه کدها رو نخونید. خیلی اوقات افرادی رو میبینم که تلاش میکنن سورس کد رو بفهمن، قبل از اینکه یادبگیرن چطور پروژه رو بیلد کنن. برای من، بخشی از فرایند یادگیری اینه که چیزای مختلف رو آزمایش کنم و خراب کنمشون، و خیلی سخته که شما بتونید چیزی رو آزمایش یا خراب کنید، بدون اینکه بتونید بیلدش کنید.
نگران بیلدهایی که همه قابلیتها رو به طور کامل دارن نباشین. پروژههای پیچیده عموما قابلیتهایی دارن که فقط در صورتی در دسترس قرار میگیرن که پیشنیازهای درست، سیستمهای درست، تنظیمات درست و ... داشته باشید. در چنین حالتی نگران هیچ کدوم از این موارد نباشید. هدف اینه که یک باینری که به اندازه کافی روی سیستم شما خوب کار میکنه داشته باشید. هرچه که قدمهای بیشتری برمیدارین، تجربه و اعتماد به نفس بیشتری برای شروع کار با بیلدهای با قابلیتهای بیشتر پیدا میکنین.
در حین این مرحله، من همچنین پیشنهاد میکنم یاد بگیرید که چطور تستها رو اجرا کنید و اونهارو به موفقیت برسونید. این باعث میشه راحتتر بتونید در گامهای بعدی روی چیزای مختلف آزمایش کنید یا اونها رو خراب کنید. پروژههای پیچیده معمولا تست سوئیتهای پیچیدهای هم دارن، بنابراین در بعضی حالات ممکنه منظور اجرای فقط زیرمجموعهای از تستها باشه — هرچندتایی که برای آزمایش شما کافیه.
برای یادگیری جزئیات داخلی، من دوست دارم رویکردی که «دنبالکردن رو به پایین، یادگیری رو به بالا» صداش میزنم رو استفاده کنم.
⬇️ دنبال کردن رو به پایین
من با یک قابلیت یا مورد کاربردی شروع میکنم، و از بیرون شروع میکنم به دنبالکردن مسیر کد به سمت اون قابلیت. در حین این فرایند، از فایلها، خطوط، و توابعی که رد میشم یادداشت برداری میکنم، اما هنوز تلاشی برای فهمیدن اینکه چی چطور کار میکنه نمیکنم. این فاز «دنبالکردن رو به پایینه».
به عنوان مثال، زمانی که کامپایلر Zig رو یادمیگرفتم، از دنبال کردن دستور zig build-exe
شروع کردم تا از روی یک سورس کد Zig یک خروجی قابل اجرا بسازم. این دنبالکردن من رو به سمت پیدا کردن سورس کد محیط دستوری Zig، زیردستور build-exe
، و سپس به سمت زیرسیستم «کامپایل»، که در نهایت تجزیهگر کد، لکسر و ... رو صدا میزد هدایت کرد. از جزئیات پیادهسازی فقط چیزایی رو خوندم که بتونم مسیر رو دنبال کنم، نه بیشتر.
از یادداشتهای دنبالکردن کد، معمولا میتونید یه «تصویر بزرگ» از اینکه یه چیز چطور کار میکنه بسازید. براساس نام فایلها، توابع و غیره معمولا میتونید زیرسیستمهای اصلی پروژه رو شناسایی کنید. این کمک میکنه تا بعدا فرایند یادگیری رو به بخشهایی با اندازههای معقولتر بشکنید.
سعی نکنید که همه چیز رو یاد بگیرید. یکی از اشتباهات رایجی که میبینم مردم مرتکبش میشن اینه که هفتهها و حتی ماهها توی کد گم میشن و در نهایت هم دلسرد میشن چون میخوان که کل پروژه رو خط به خط بخونن. تمرکز کنید و قابلیت به قابلیت یاد بگیرید.
نکته: وقتی قابلیتی رو انتخاب میکنید، یکی از قابلیتهایی باشه که به عنوان کاربر باهاش آشنا هستید. همچنین، اگه ممکنه، قابلیتی رو انتخاب کنید که از روی سطح پروژه آسون به نظر بیاد. به عنوان مثال، اولین برنامه Zig که سعی کردم دنبالش کنم تا کامپایلر رو یاد بگیرم برنامهای بود که دو عدد رو جمع میزد و هیچ خروجیای نداشت.
⬆️ یادگیری رو به بالا
بعد از دنبال کردن یک قابلیت، الان وقتش رسیده که ببینید چطور چندین زیرسیستم مختلف کار میکنن. درحالیکه برای فاز دنبالکردن، از بیرونیترین نقطه مثل محیط دستوری یا صدازدن رابطهای برنامهنویسی شروع میکنم، برای فاز یادگیری، از دورنیترین نقطه شروع میکنم.
از درونیترین نقطه شروع میکنم، چرا که معمولا بنیادیترین و کمترین میزان انتزاع رو داره. همینطور که از لایهها بالا میریم، به نظر ارتباط مستقیمی با افزایش سطوح انتزاع داره که باعث میشه اگه قطعات مختلف اجزا رو نمیفهمید، یادگیریتون سختتر بشه.
برای یادگیری یک زیرسیستم مشخص، من به طور بازگشتی «دنبالکردن رو به پایین، یادگیری رو به بالا» رو انجام میدم. اول با بررسی رابطهای عمومی و بیرونی سطوح شروع میکنم، و بعد از اون یاد میگیرم که صدا زدن هر کدوم از این رابطها چطور کار میکنه. این روشی هست که لایههای بالایی از زیرسیستمها استفاده میکنند، بنابراین هم من رو راهنمایی میکنه که چطور یادبگیرم، و هم همون طور که به سمت بالا حرکت میکنم قضیه روشنتر میشه.
در حین فرایند «دنبالکردن رو به پایین، یادگیری رو به بالا»، آزمایشکردن و خرابکردن چیزها رو برای یادگیری اینکه چطور چیزی کار میکنه مفید میدونم. به خاطر همین هم هست که یادگیری اینکه چطور پروژه رو بیلد کنیم رو قبل از تلاش برای خوندن جزئیات داخلی پروژه ضروری میبینم.
لاگهای جدید اضافه کنید، بخشهای کوچک با قابلیتهای جدید پیادهسازی کنید، قابلیتهای فعلی رو تغییر بدید و ... در نهایت پروژه رو مجددا بیلد کنید و ببینید که چه اتفاقی میفته. این همچنین راه خوبیه تا فهم خودتون رو از اینکه چیزی چطور کار میکنه محک بزنید.
به عنوان مثال، زمانی که در مورد توکنساز [۱] Zig یاد میگرفتم، توکنهای جدیدی اضافه کردم و دیدم که توکنها شناسایی میشن اما تجزیهگر به خطا میخوره. وقتی سراغ سیستم بعدی (تجزیهگر) رفتم، از توکنهای جدیدم استفاده کردم تا کاری انجام بدن. و به همین منوال...
در این فاز، یادگیری کد رو با رسانههایی مثل کتابها، ویدئوها، بلاگ پستها و ... تکمیل کنید. اگر محتوایی که جزئیات داخلی رو پوشش میده وجود داره، بخونیدش!
اگرچه، نباید انتظار داشته باشید که این محتوا به تنهایی شما رو به سطح یک آدم خبره برسونه. مشابه گام اول و «یک کاربر پروژه شدن»، هیچ مکملی برای کثیف کردن دستاتون و بازی با سورسکدهای واقعی به هدف «یک نگهدارنده شدن» وجود نداره. این مثال دیگهای از کاربردهای تئوری در مقابل عملیه.
نکته: اگه منبعی برای یادگیری جزئیات داخلی وجود نداره، سعی کنید خودتون بنویسیدش! من از اونجایی که نتونستم هیچ منبع بهروز مشابهی رو پیدا کنم، این کار رو در مورد Zig انجام دادم و در مورد جزئیات داخلی Zig نوشتم. نوشتن در مورد چیزی راه خوبی برای تقویت یادگیری شماست و همچنین به مشارکت کنندگان بعدی هم کمک میکنه.
به عنوان قدم آخر برای یادگیری جزئیات داخلی، من کامیتهای اخیر مربوط به زیرسیستمهایی که مطالعهشون کردم رو میخونم و تست میکنم که آیا تغییری که انجام شده رو کاملا میفهمم یا نه. این برای من بخش «انجام تمرینهای انتهای کتاب» از یادگیریمه.
من یا کامیتهای اخیر از پروژه و یا تاریخچه کامیتها از یک فایل یا پوشه مخصوص که مربوط به زیرسیستمی که قبلا مطالعه کردم رو نگاه میکنم. بعد از اون یا راهحل رو مطالعه میکنم (تغییرات درون کامیت) و یا باگی که سعی داشته رفع کنه رو نگاه میکنم و سعی میکنم که خودم رفعش کنم و ببینم که آیا به راه حل مشابهی میرسم یا نه؟
برای کار روی مشکل و حلش، مخزن رو دقیقا تا قبل از اون کامیتی که در حال مطالعش هستم دریافت میکنم. باگی که قرار برطرف کنه رو به وجود میارم (اگه مربوط به رفع باگ باشه)، و بعد سعی میکنم که راه حل رو خودم پیادهسازی کنم. درنهایت، کار خودم رو با کامیتی که توسط مشارکتکننده یا نگهدارنده انجامشده مقایسه میکنم.
تنها راهنماییای که به خودم میکنم اندازه تغییرات مورد نیاز هست (نمادهای +/-
در کنار خطوط تغییرات در سورس کنترل). توصیه میکنم برای شروع از تغییراتی که به بیشتر از ۵۰ تا ۱۰۰ خط تغییر در خطوط کد نیاز دارن پرهیز کنید.
من دوست دارم با تغییر کوچکی شروع کنم و به صورت تدریجی وظایف بزرگ و بزرگتری رو انجام بدم. در این فاز، شما اجزا فنی پروژه رو میفهمید، و الان وقتش رسیده که اجزا انسانی رو یاد بگیرید. هدف در اینجا اینه که تغییر کوچکی بدید و فرایندهای مشارکت و مرور کد رو یاد بگیرید.
معمولا سختترین قسمت پیدا کردن یک تغییر کوچک برای انجام دادنه. هیچ گلوگه نقرهای[۲] اینجا وجود نداره. من بین ایشوهای[۳] ثبتشده میگردم تا چیزی پیدا کنم که بشه مشارکت کرد. من معمولا چند بار شروع اشتباهی دارم، و یا یک ایشو رو کلا بیخیال میشم و سعی میکنم ایشو دیگهای رو رفع کنم. درنهایت یکی پیدا میکنم. اینبار کمی طول میکشه تا مشکل رو پیدا کنم و یا حتی رفع مشکل میتونه به طور ناامیدکنندهای طول بکشه، اما این هزینهایه که باید پرداخت کرد. پروژهها معمولا برچسبهای «مخصوص مشارکتکنندهها» دارن تا مشارکتکنندههای جدید رو راهنمایی کنن.
امروزه بیشتر پروژهها مستندات خوبی در مورد فرایند مشارکت کردن دارن، بنابراین وقتی تغییرات پیادهسازی شد، دقیقا مطابق فرایند پیش برید. اگه در مراحل ابتدایی به کامیونیتی ملحق شدید، فرصت خوبیه تا از کسی کمک بخواید تا فرایند مشارکت شمارو دومرتبه بررسی کنه.
به عنوان مثال، اولین مشارکت من در Zig یک تغییر سه خطی بود که در فاصله دو عصر چیزی نزدیک به چهار تا پنج ساعت از وقتم رو گرفت (بدون احتساب زمان برای انجام قدمهای قبلی). اگه امروز با این باگ مواجه میشدم در چند دقیقه برطرفش میکردم، اما زمان میبره تا به چنین سطح مهارتی برسید.
در این نقطه، شما یک پروژه پیچیده رو یاد گرفتید و در اون مشارکت کردید.
از پیچیدگی نترسید. من فکر میکنم تعداد زیادی از مهندسین از پروژههایی مثل زبانهای برنامهنویسی، مرورگرها، پایگاههای داده و ... که به طور کلیشهای پیچیده هستند به شکل یک جادو و یا مقدر شده برای موجوداتی برتر نگاه میکنن. میخوام یادآوری کنم که همه پروژهها توسط سایر انسانها شروع شدن. اگه اونا میتونستن که انجامش بدن، من هم میتونم. پس تو هم میتونی.
امیدوارم که با به اشتراک گذاشتن رویکرد من، بقیه هم پروژههای پیچیده رو بیشتر قابل مشارکت ببینن.
۱: Tokenizer
۲: منظور نویسنده این است که راهحل جادویی برای رفع مشکل وجود ندارد
۳: Issue