گفتههای آرش خانگلدی از اسپاتیفای
خوندن صحبت کسایی که توی شرکتهای بزرگ دنیا کار کردند به ما کمک میکنه که بدونیم ساز و کار این شرکتها چطوریه، بر اساس چه اصولی مدیریت میشن و پروژههاشون رو چطوری جلو میبرند.
از اینجور مصاحبهها تو اینترنت پیدا میشه ولی این یکی فرق داره؛ چون صحبتهای یه ایرانی هست که مدتها تو ایران بوده و علاوه بر موارد بالا، در مورد نحوهی مهاجرت و تفاوتهای اونجا با ایران هم صحبت کرده.
پیشنهاد میکنم صحبتهای آرش رو که خیلی با دقت گفته شده و جزئیات زیادی از شرکت اسپاتیفای داره رو بخونید.
پیشگفتار
این صحبتها در ۲ جلسه به صورت video conference و یک جلسه حضوری از پاییز ۹۶ تا بهار ۹۷ انجام شده و بعدها قسمتهایی برای انسجام مطلب جابهجا شده یا بهش اضافه شده. امیدواریم براتون مفید باشه.
همینطور تا امروز آرش برامون ۲ جلسه در مورد SOLID و Test ارائه داشته که میتونید ببینید و پیشنهاد میدم چنل YouTube یا آپارات یا تلگرام ما رو دنبال کنید تا از ارائههای بعدیش هم با خبر شید.
معرفی
سلام
برای اونایی که منو نمیشناسن یه معرفی کوچیک کنم.
من آرشم، از سال ۹۱-۹۲ اندروید کار میکنم. قبل از این تاریخ توی شرکتی به عنوان وب دولوپر کار میکردم. تازه اندروید اومد بود، یه خورده جذبش شدم و sdk رو دانلود کردم، با Eclipse شروع به کار کردم. یه اپ برای شرکت نوشتم و بعد دورهی اول استارتاپ ویکند رو شرکت کردم. بعد اون یه جورایی به سمت اندروید کشیده شدم. اندروید دولوپر خیلی کم بود، یه سری پروژه سمتم اومد و انجام دادم. کارایی که انجام دادم و معروف بودن بیسفون و نواک بودند. این دو تا پروژههایی بود که حداقل یکی دو سال داخلشون بودم. چندتا پروژه کوچیک و بزرگ دیگه هم در مجموع انجام دادم.
از ۵ ماه و خوردهای پیش با نقش Android engineer اومدم اسپاتیفای. اینجا کلا senior یا junior خیلی معنی نداره، متناسب با contribution که به سورس کد میکنی و متناسب با مسئولیتهایی که به عهده میگیری حقوقت بالاتر و پایینتر میاد. کسی senior نیست و مفهوم جالبی هم هست. خیلی از این موضوع خوشم اومد. چون با این بحث در ایران که کی senior یا junior هست موافق نبودم. از نظر خودم ما ها هممون تا آخر عمرمون چیز برای یادگیری داریم و خیلی دوست نداشتم بگم من این عنوان رو دارم یا ندارم.
- بیشتر توضیح میدی چطور حقوق مشخص میشه؟
جلوتر بیشتر توضیح میدم ولی مثلا بستگی به این داره که روی یه سورس کد contribute کنی یا چند تا، بیشتر بخوام توضیح بدم ما تیمی داریم به اسم core، تیم core با ++c یه سری فیچرهای core اسپاتیفای رو میزنن که توی همه اپهای وب، ios، اندروید و ماشین مشترک هست. اینا هر روز صبح باید شبیه تیمهای دیگه feature release بدن و بگن این کد امروز ما هست. هر موقع core آپدیت میشد، ما هم باید gradle رو آپدیت میکردیم. آپدیت گریدل ۲۰ دقیقه طول میکشید و همه شرکت باید منتظر میموند. اومدن اپ رو modularize کردن و الان اپ اندروید ماژولهای مختلفی داره. اینکه شما توی چند ماژول contribute کنی به عنوان یه اندروید engineer یا حتی بکاند یاد بگیری و به بکاند دولوپرها کمک کنی، پروژهی خودتو بکاندشو بزنی، Machine Learning یاد بگیری یا Data Science و … متناسب با این مشخص میشه تو چه stepای هستی. step یه مقیاسی توی شرکت اسپاتیفای هست که مشخص میکنه آیا فقط تنها به خودت و پروژهی خودت کمک میکنی؟ آیا داری به کل تیمت کمک میکنی (Squad)؟ آیا داری به اعضای چندتا تیمی که با هم به دنبال یک هدف مشترکید کمک میکنی (Tribe)؟ آیا داری به کل شرکت کمک میکنی؟ متناسب با این مشخص میشه stepت چیه، حقوقت متناسب با اون شکل میگیره و به قولی اون درجهی سنیوریتی اونجا مشخص میشه. منتها هرچقدر step بره بالاتر مسئولیتهات بیشتر میشه و طبیعتا باید تجربهی این کار رو هم داشته باشی. اگر میخوای یه step بری بالاتر باید خودتو واقعا ثابت کرده باشی.
رفتن به اسپاتیفای
سعی میکنم خلاصه بگم که چی شد اومدم اسپاتیفای.
نواک یه اپ music streaming هست و کاری که میکنه خیلی خیلی شبیه اسپاتیفای هست. در واقع خیلی جاها ما از اسپاتیفای الهام میگرفتیم، چون اسپاتیفای واقعا جزء شرکتهای پیشرو توی این زمینه هست. منم اونجا اندروید انجینیر بودم.
یکی از Recruiterهای اسپاتیفای با من تماس گرفت و گفت اگر دوست داشته باشی میتونیم با هم کار کنیم. منم با خانومم صحبت کردم و گفتم که همچین موقعیتی هست. ما تو فکرمون بود که از ایران بریم ولی جای خاصی توی ذهنمون نبود، بیشتر بصورت ایده و کلی بود.
۴ مرحله مختلف ازم تست گرفتند. ۳ تاش تو ایران و ریموت بود. و آخریش که خیلی طولانی بود دعوتم کردن دفتر مرکزی در استکهلم، on-site interview که باید بری توی دفتر و اونجا باهات صحبت میکنن. از تستها اونایی که توی ایران بود کاملا فنی و کد نویسی بود.
اولیش یه تست چهار جوابی خیلی سریع بود. اگر اشتباه نکنم چیزی نزدیک به بیست سوال رو باید خیلی سریع جواب میدادی، اینقدر سریع که فرصت نمیکردی آنلاین چیزی رو چک کنی، یا باید ولش میکردی و جواب نمیدادی یا غلط جواب میدادی که بدتر بود. هر مرحله بهت ایمیل میزنن که توی این مرحله قبول شدی یا نه.
مرحله بعدی یکی از انجینیرهای اسپاتیفای یه سری سوال فنی ازم پرسید. مثلا در مورد بیس اندروید، چقدر با اکتیویتیها آشنایی؟ چقدر با کامپوننتها آشنایی؟ از چه ابزارهایی استفاده میکنی؟ تو RXJava این رو استفاده کردی؟ تو Dagger اونو استفاده کردی؟ مثلا این رو میدونی چطور باید تنظیم کنی؟ از اینجور بحثها، از چیزای خیلی ابتدایی اندروید شروع کرد رفت بالا تا ببینه چقدر میتونم جواب بدم.
نیم ساعتی به سوال جواب گذشت، بعد گفت یه کد بنویس. آنلاین باید همونجا اسکرینم رو share میکردم و کد مینوشتم. اگه اشتباه نکنم تو یه ساعت میخواست یه اپ خیلی ساده مثل Run Keeper بنویسم که قدمها رو میشماره و حساب میکنه چند دقیقه دوییدید. فقط تفاوتش این بود که ui مهم نبود، مهم این بود که pure چه جور logic مینویسم، و اینکه باید از Thread استفاده میکردم، میخواستند ببینند ipc بلدم؟ بین تردها میتونم دیتا جابهجا کنم؟ که یا باید از RXJava استفاده میکردم یا EventBus و این جور چیزها.
بعد از این مرحله هم یه google doc با من share کرد و گفت ما تو این داک یه کدی نوشتیم هرچقدر میتونی ازش اشتباه بگیر. یعنی اشتباه داره اشتباهاش رو مشخص کن. که از اشتباههای syntax و تایپی، کامنت داشتن-نداشتن، اشتباه Architecture، Unit Test داشتن-نداشتن، اینکه چیزی مثلا NullPointerException تو runtime بگیرم-نگیرم، از هرچیزی که میتونستم باید ایراد میگرفتم.
مرحله بعدی باز با یه اندروید انجینیر دیگه جلسه داشتم و یه نفر دیگه که نمیدونم برنامه نویس اندروید بود یا نه، اونم تست برنامه نویسی بود. بیشتر میخواستند ببینند تو بازه کوتاه چقدر سریع و با دقت میتونم کد بزنم. یا اگر بهم وقت بدن چقدر میتونم تمیز کد بزنم.
وقتی هم از این مرحله قبول شدم گفتند باید بیای اینجا.
وقتی اومدم سوئد یک روز کلا از صبح تا شب فقط مصاحبه بود، تو ۴ تا مصاحبه تقسیم شد. ۲ ساعت اول با ۲ تا از مدیرهای ۲ تا تیم جلسه گذاشتیم برای این که کاندید بودم به یکی از اون ۲ تا تیم اضافه بشم، در واقع مصاحبه فرهنگی بود. اسمش Cultrual Interview بود، خیلی سوالهای کلی میپرسیدند. ربطی به برنامه نویسی نداشت مثلا چه جوری خودت رو از لحاظ تکنولوژی آپدیت نگه میداری؟ چه بلاگهایی میخونی؟ اگر تو محیط کار این مشکل پیش بیاد چطور حلش میکنی؟ اگه این کار اورژانسی پیش بیاد چکار میکنی؟ اگه وقت نباشه ریفکتور کنی ولی فیچرو لازم داشته باشیم چه جور سعی میکنی هم کد رو تمیز نگه داری هم فیچر رو به موقع برسونی؟ از لحاظ شخصیتی چطور آدمی هستی؟
بعد یه مصاحبه داشتم با ۲ تا انجینیر اندروید. بهم گفته بودند یه کدی بنویس بیار و هرچی دوست داری استفاده کن؛ هم architectureای که دوست داری هم ابزارهایی که دوست داری. من یه اپ ساده نوشته بودم و باید از کدم دفاع میکردم. تا جایی که میتونستم باید تمیز مینوشتم، دست خودم بود که چقدر وقت بزارم و تمیز بنویسم. باید دفاع میکردم چرا وقتی که با Lint چک بیلد میگیریم این warningها رو درست نکردم؟ یا مثلا چرا این قسمت تست code coverage خوب نبوده؟ یا چرا این logic رو تست نداره؟ باید دفاع میکردم. بعضی چیزهاشم نمیدونستم که باید این کار رو میکردم. همونجا هم یه چیزایی رو گفتند که باید اضافه میکردم و دوباره شروع کردم کد نوشتن.
یه قسمتی از تست دوباره فرهنگی بود با دو سه نفر از اعضای تیمها نهار خوردیم که فقط ببینند من چه جور آدمی هستم، میتونیم با هم تو یه تیم باشیم یا نه.
آخرین تست بهش میگفتند Problem Solving (حل مساله) که کاملا الگوریتمی بود. یه تخت سیاه دادن دستمون، یه مسئلهای گفتند و باید با pseudocode (شبهکد) حلش میکردم و مرتبه زمانی الگوریتمش رو حساب میکردم. مسئله رو یادم نمیاد چی بود. اون قسمتش برای من چالش برانگیزترینش بود چون تو ایران خیلی شبهکد نمینویسیم و مرتبه زمانی الگوریتم حساب نمیکنیم. البته بهم گفته بودند که همچین تستی ازت میگیریم و من مجبور شده بودم یه دورهی یادآوری از طراحی الگوریتم و دیتا استراکچر بگذرونم که یادم بیاد چیبهچی بود. عملکرد خیلی خوبی نداشتم تو اون تست چون بر خلاف اینجا تو ایران الگوریتم به عنوان چیزی که باید روش مسلط باشی خیلی مطرح نبود.
آخر هم بهم ایمیل زدن که قبول شدی و کی میتونی بیای و مراحل اومدن رو شروع کردم. تو نواک هم کار دستم خیلی زیاد بود همه رو تحویل دادم. کمکم آماده شدم اومدم اینجا.
ورود به اسپاتیفای
وقتی رسیدم تو ۳ مرحله من رو OnBoard کردند. Onboarding فرایندی هست که وقتی شما وارد شرکت بشید شروع میشه برای اینکه یاد بگیری چه جوری با شرکت کار بکنی و فرآیندهای خاص شرکت رو یاد بگیری. برای همه ۳ مرحله Onboarding انجام میشه. مجموعا چیزی حدود ۲ هفته من تحت آموزش بودم؛ همش یه جا نبود تو زمانهای مختلف بود. تو اون ۲ هفته من یک خط کد هم نمینوشتم چون داشتم یاد میگرفتم.
تو مرحله اول یاد گرفتم اسپاتیفای به صورت کلی ساختارش چه جوریه؟ رییس کیه؟ به کی گزارش میدی؟ تیمها چه جوری شکل میگیرن؟ چه جوری دلیویر میکنی محصولی که باید دلیویر کنی؟ استک کلی پروژه چه جوریه؟ آیا ما رو کلاودیم؟ آیا ما خودمون دیتا سنتر داریم؟ اندروید پروژه کی شروع شد؟ از اینجور چیزا شروع میکنند و بعد بیشتر توضیح میدند. مثلا ما از چه متودولوژیهایی استفاده میکنیم؟ چه جوری اجایل رو مدیریت میکنیم که ازش نتیجه بگیریم؟ مثلا در قالب یه سری بازی فکری این که چطور اجایل کار میکنند رو به ما یاد میدند، که خیلی جالب بود ایدههاش و اصلا هزینه هم نداشت، صفر بود عملا، فقط لازم بود یه نفر اجایل رو خوب بشناسه.
بعد Mobile Onboarding بود که مخصوص موبایل انجینیرها هست. طبیعتا بکاند آنبوردینگ، دیتا آنبوردینگ، و از اینجور چیزها هم دارند. تو موبایل آنبوردینگ مثلا اینکه چه جور از اندروید استادیو استفاده میکنیم یا از چیز دیگه، gradle رو چه جور بیلد میکنیم، مثلا اگه بخوای یه A/B test بنویسی پلتفورمش چیه؟ اگه بخوای کدت رو Modulraize بکنی پلتفورمش چیه؟ اگه بخوای یه کامپوننت جدید تو اسپاتیفای رجیستر کنی چطوره؟ یه فیچر کلا جدید بخوای بنویسی چه جوری باید این کار رو بکنی؟ کجا باید رجیسترش کنی؟ چه جوری میتونی تیمت رو رجیستر کنی به عنوان owner این کد؟ و BestPracticeهای شرکت.
آخرین مرحله آنبوردینگ IntroDays که کاملا اطلاعات سطح مدیریتی اسپاتیفای بود. مثلا چه جوری پول در میاره؟ چه جوری تبلیغات میکنه؟ چه جوری با هنرمندا قرارداد میبنده؟ یا چه اطلاعاتی میتونید پابلیک بگید چیارو نمیتونید بگید؟ یا اگر نمیدونید چی رو نمیتونید بگید از فلان کس بپرسید. IT چیکار میکنه تو شرکت؟ HR چیکار میکنه؟ اطلاعات کلی شرکت بود.
خیلی خیلی آدم زیاد هست تو شرکت و اوایلش گیج میشدم، وقتی یه مشکلی پیش میاد باید چیکار کنم؟ از کی بپرسم؟ یه چیز خیلی خوبی که داشت یک آدمی Assign میشه به تازه واردها به اسم buddy (همون رفیق)؛ کسی هست که role شما رو داره، اونم اندروید انجینیر هست ولی سابقه کار طولانی داره؛ مثلا ۳ ساله اندروید انجینیر هست تو شرکت. تو ماه اول قدم به قدم باهاتون میاد هر سوالی داشته باشید میتونید ازش بپرسید. مثلا از کجا آب بخورم؟ تا اینکه شرکت چه جوری پول در میاره؟ من اگه بخوام به این اطلاعات مالی شرکت دسترسی داشته باشم کجا باید برم؟ اگر بخوام کد رو clone کنم کجا باید برم؟ چون روزهای اول حجم اطلاعاتی که میگرید انقدر زیاد هست که آدم گم میشه تو اون اطلاعات. یه خورده طول میکشه بتونه مدیریتش کنه. حداقل برا من اینجوری بود.
چیزی که برام جالب بود شرکتایی که خارج از ایران کار میکنند، برای همه کارمندها یه دوره آزمایشی دارند. با هر رولی که وارد شرکت بشی حتی رول CEO. این دوره از طرف کشور کلا اعمال میشه. تو سوئد قانون هست؛ همه افرادی که استخدام میشند ۶ ماه دوره آزمایشی دارند. تو کشورهای دیگه هم هست یه خورده کمتر بیشتر. مثلا من هنوز تو دوره آزمایشیمم. تو دوره آزمایشی ممکنه شما انقدر خراب کنی که بگند نمیخوایم باهات کار کنیم. یا خودت به این نتیجه برسی که من نمیخوام اینجا بمونم. ولی بعد از دوره آزمایشی قراردادت اتومات بدون اینکه چیزی امضا کنی تبدیل میشه به کارمند فول تایم شرکت.
این نحوه ورود من به شرکت بود.
- اطلاعات مالی شرکت کامل شفافه؟
بله
- حقوق بقیه رو میشه دید؟
تا حالا دنبالش نرفتم ولی خیلی سخت نباید باشه دیدنش. کلا اینجا اطلاعات مالی خیلی شفافه، نه فقط اسپاتیفای، کلا تو سوئد حتی حساب کتابهای دولت هم میتونید چک کنید. چه برسه به یه شرکت چند ۱۰ هزار نفره.
ساختار تیمها
بحث بعدی که دربارهی شرکت خیلی جذاب هست، مدل شکل گیری تیمها و structureشون هست. از پایین به بالا توضیح میدم. از مهندس نرمافزار تا CEO.
در لول پایین squad هست، یه تیم متشکل از یه سری آدم که برای هدف مشترک کار میکنند. مثلا من وارد تیمی شدم که کار سرچ انجام میداد. فیچر و پروداکت سرچ دست این تیم بود. (الان تیمم عوض شده) تیم سرچ از من و یه اندروید engineer دیگه، دو تا ios engineer، یه backend developer، یه product owner، یه designer و آدمی به اسم agile coach و کسی که کار chapter lead رو انجام میده تشکیل شده. یعنی این همه آدم فقط داشتن front end سرچ رو مینوشتند.
ما دو تا تیم سرچ داریم. یه تیم به اسم search experience و یه تیم دیگه به اسم search platform. من تو search experience بودم، ما فقط front end بخش سرچ رو انجام میدادیم. مثلا بخش اندروید دست من بود، باید maintenance میکردم. اگر پروداکت منیجر چیزی میخواست باید انجام میدادم. اگر A/B Test یا … بود باید پیاده میکردم. ورژنهای قبلی رو باید maintenance میکردم. چون چندین ورژن از قبل هست که کد بیس و مدل برنامه نویسیش فرق داره و قدیمی بوده. ابزارهایی که توش استفاده شده متفاوت بوده و هنوز لایو هستند، در نتیجه باید maintenanceشون بکنیم. و یه سری کارهای دیگه روزمره.
backend engineer تیم ما از تیم search platform اطلاعات رو میگرفت aggregate میکرد و به front end میداد. برای مثال وقتی یه سرچ توی اسپاتیفای انجام میدید، ۱۰ مرحله اطلاعات توی سرویسهای مختلف جابهجا میشه تا برسه دست کاربر، این ده مرحله تو search platform انجام میشه مثلا خوندن اطلاعات از دیتابیسهای distributed و رتبهبندی کردنشون، ساختن اطلاعات از microserviceها و FlatBuffer و باینری کردن اینها، optimization برای حداقل کردن زمان. ۱۰ سرویس مختلف هست که این اطلاعات سرچ رو میسازه. backend engineer ما اطلاعات این ده سرویس مختلف رو aggregate میکرد و تحویل front end میداد. کار ما از اینجا شروع میشد، اطلاعات رو از backend خودمون میگرفتیم و نمایشش میدادیم و ….
تیم ما یه رولی داره (توی اسکوادمون) به اسم به product owner یا product manager، آدم کاملا غیر فنی هست که نحوهی رشد و اداره کردن این product رو بر عهده داره. این آدم تصمیم میگیره که توی product چه اتفاقاتی بیوفته. مثلا این A/B Test اجرا شه که ما ببینیم میتونیم concussion یوزرمون رو ببریم بالا یا نه، ببینیم میتونیم session یوزر رو بیشتر بکنیم یا نه. یا مثلا براساس یه سری اطلاعات که شرکت بدست آورده اگر اطلاعات رو به جای افقی، عمودی نشون بدیم بهتره؛ حالا اینو زمانبندی میکنیم که این feature یه ماه وقت میگیره و اون میشکونتش به taskهای کوچکتر و ما شروع میکنیم روش کار کردن. یا احتمال داره تیمهای دیگه به ما feature request بدن و بگن این feature رو احتیاج داریم، پروداکت منیجر هست تصمیم میگیره ما توان انجامشو داریم یا نه و اینکه چقدر طول میکشه بخوایم انجامش بدیم، آیا لازم هست کسی از تیم دیگه بیاد کمکمون برای پیاده سازی این feature یا نه.
مثلا شرکت تصمیم میگیره تو شش ماه آینده ۱۰۰ میلیون کاربر جدید بگیریم. اینکه چطور این کاربرها گرفته بشه در قالب یه سری اهداف به تیمهای مختلف اعلام میشه. مثلا برای گرفتن ۱۰۰ میلیون کاربر لازم هست که توی بازار فلان کشور وارد بشیم و یوزرهاشو نگه داریم. برای انجام این کار باید فیچر x این کارو بکنه و فیچر y اینکار. اینو وقتی product owner فهمید میاد با تیم صحبت میکنه که این فیچر رو میخوایم بزنیم. حالا شما باید نیازمندیهای شرکت رو رفع کنید، بتونی اون چیزی که ازت میخوان رو تحویل بدی، باید زمانبندی کنی، بگی من اینکارو میتونم بکنم ولی دو ماه ازم وقت میگیره. اندروید یه تخمین میده ios یه تخمین، back end یه تخمین. زمان تست و … بهش اضافه میکنن و اعلام میکنن این فیچر اینقدر طول میکشه. ممکن هست یه تیم دیگه به یه فیچر شما نیاز داشته باشه. مثلا یه A/B test بکنه یه چیز جدید اضافه کنه. نمونش ویو سرچ دست ما هست ولی اسپاتیفای یه فیچری اضافه کرد به اسم audio assitance، یه دکمه هست تو تولبار بالای سرچ اضافه شده (نمیدونم تو همه کشورها ریلیز شده یا نه) وقتی میزنید میتونید از اسپاتیفای مثل گوگل home سوال کنید، به فرض فلان آهنگ رو پخش کن. توی این مودم برام یه آهنگی رو پخش کن. این assitance باید توی سرچ اضافه میشد. منتها اضافه کردن فقط یه دکمه نبود، چون باید اینو توی پلتفرمهای مختلف جا بدیم یا اصلا بتونیم توی نسخههای مختلف سرچ جا بدیم، یعنی ممکن هست شما بری یه code base رو ادیت کنی که آخرین بار سه سال پیش ادیت شده، چالشش فقط اضافه کردن یه دکمه نبود؛ درگیری برای ما زیاد داشت. باید unit test, end to end test, integration test بنویسی و مطمئن باشی مشکل نداره. طبیعتا code baseای که سه سال پیش نوشته شده نمیتونی توش از rxjava2 استفاده کنی؛ باید اونجا با یه روش دیگه اضافش کنی. خلاصش اینکه تیم چطوری و چه کارهایی رو با چه dead line میتونه انجام بده رو product manager یا product owner مشخص میکنه.
نقش جالب دیگه که تو همهی تیمها داریم technical owner هست. معمولا قدیمیترین engineer اون تیم و برخلاف product owner کاملا فنی هست، کد مینویسه همه کار میکنه منتها این نقش رو هم برعهده داره. این دو نفر با هم نقشه راه تیم رو در طول زمانهای مختلف مشخص میکنند. مثلا ممکن هست یه فیچر باحال به ذهنمون بیاد یا یکی بهمون پیشنهاد بده یا اصلا CEO بگه اگر این فیچر اضافه شه خیلی خوب میشه. ولی technical owner بگه ما توانایی انجامشو نداریم یا کار ضروری تری داریم. اینجوری نیست که فقط product owner از دید غیر فنی بگه اینکارو بکنیم یا این کارو نکنیم.
تیمهای ما که بهش میگیم Squad معمولا ۱۰ - ۱۲ نفر هستند، یه فیچر دستشونه و باید اونو توسعه بدن یا نگهداری کنند. شرکت چند طبقه هست و به هر طبقه Tribe میگن. ترایب مجموعهای از چندتا squad هست معمولا ۵ - ۶ تا و حدود ۸۰ - ۱۰۰ نفر که برای یه هدف مشخص کار میکنند. برای مثال من توی ترایبی بودم به اسم core experience. این ترایب از ۵ اسکواد مختلف تشکیل شده و کل ux و ui اپ موبایل اسپاتیفای دست ترایب ما هست؛ تقریبا اکثر فیچرهایی که توی اپ میبینید. صفحه home, your library, search, radio, album, artist همه اینارو ترایب ما زده. ما با هم تعامل نسبتا نزدیکی داریم، مثلا تیمی که صفحه artist رو مینویسه ممکنه بیاد از code base شما استفاده کنه یا یه A/B test بخواد ران کنه که سرچ یه تغییراتی بکنه. هر هفته یه جلسهی مشترک داریم. چیزایی که توسعه میدیم رو با هم share میکنیم. اگر چیزی یاد بگیریم داکیومنت میکنیم و به بقیه میدیم.
بعد از level ترایب یه تیمبندی بزرگتری به اسم Alliance داریم، مجموعهای از tribeها هستند که باز یه کار مشترک ولی در سطح بالاتر انجام میدن. مثلا تمام تیمهای فنی اسپاتیفای توی یه alliance قرار میگیرند. مثل تیم موبایل، دسکتاپ، ماشین یا data science. تعداد هم خیلی زیاد هست مثلا alliance ما ۱۵۰۰ نفر هستند. توی alliance معمولا خیلی ارتباط نزدیک معنا نداره. چون بعضی از تیمها اصلا توی یه کشور نیستند. مثلا تیم رادیو توی آمریکا هست و سوئد نیست. ولی خب بفرض من مجبور بودم برای یه A/B test که خودم مینوشتم با یه تیم توی بوستون هماهنگ میشدم که بخاطر محدودیت زمانی که داشتیم کلا دو سه ساعت مشترک میتونیستم کار کنیم. یا اونا بیرون شرکت بودن یا ما. سعی میکنند خیلی مجبور نشید با تیمهای یه کشور دیگه کار کنید چون زمان از دست میدید.
سطح بالای alliance میشه خود شرکت، که مثلا ceo, cto و نقشهای دیگه داخلش هست.
این نحوهی تیمبندی اسپاتیفای هست. سطح اول اسکواد با تیمهای ۱۰-۱۲ نفره، بالای اون ترایب معمولا شامل ۵-۶ اسوکاد، بالای اون alliance با ۷-۸ ترایب مختلف که معمولا تعداد افرادشون خیلی زیاد میشه.
مدیریت پروژه
توی اسپاتیفای یه داکیومنتی share شده بین همه اعضا و با اون هدف گذاری میکنند. این داکیومنتها رو معمولا مدیرهای رده بالا C level engineer یا خود CEO میسازند. برای مثال یه مفهومی توی اسپاتیفای وجود داره به اسم north star goal (هدف ستاره قطبی). ستاره قطبی یه مفهوم هست، چیزی که باهاش مسیرمون رو پیدا کنیم. اهداف ستاره قطبی رو CEO میسازه. اینا اهدافی هستند که آینده موسیقی یا صنعت رو قراره شکل بدن. خیلی سطح بالا هستند و ربطی به کارهایی که الان میکنیم نداره و شاید اصلا هیچوقت هم بهش نرسیم. فقط با اون اهداف جهت گیری تیمها مشخص میشه. برای مثال یکی از اهداف اسپاتیفای رسیدن به یک بیلیون کاربر فعال هست. این یک بیلیون کاربر فعال عدد بزرگی هست و طبیعتا طول میکشه بخوایم بهش برسیم. ولی کاربردهایی داره، شما میتونی متناسب با این هدف کار خودت رو بسنجی و بفهمی در راستای این هدف میری جلو یا نه. برای مثال ما میخوایم به یک بیلیون کاربر برسیم و هدف x, y, z. متناسب با این اهداف سالیانه رو میسازیم. مثلا برای رسیدن به یک بیلیون امسال باید ۱۰۰ میلیون کاربر بگیریم. حالا هدف امسال میشه ۱۰۰ میلیون کاربر. بعد اهداف امسال رو میشکونیم به فصلهای مختلف که بهش میگن quarter مثلا q1, q2, q3, q4. مشخص میکنیم تو هر کوارتر برای رسیدن به هدف چیکار میتونیم بکنیم.
با توجه به اهداف مشخص شده با product owner برای یه فصل برنامهریزی میکنیم، بفرض ۴ ۵ ۶ تا اسپرینت میبندیم. توی اسپرینت ۱ به اینا میرسیم توی ۲ اونا رو انجام میدیم و توی ۳ اینا. به همین ترتیب اسپرینتها رو میچینیم. البته دونه دونه، یعنی برای ۴ تا اسپرینت بعدی برنامه ریزی نمیکینم، برای یه اسپرینت بعدی برنامه میریزیم. منتها تو backlog (از jira استفاده میکنیم) تمام تسکهایی که باید توی یه کوارتر بهش برسیم هست. اگر توی این کوارتر بهش رسیدیم که عالی دممون گرم، میریم بیرون شام میخوریم. اگر نرسیدیم یه جلسه میذاریم که چرا نرسیدیم؟ چه مشکلی هست؟ آیا باید آدم بیشتری بگیریم؟ آیا درست برنامه ریزی نکردیم؟
تسکهای جیرا رو به این شکل صفر میکنیم و به اونجا میرسونیم که بگیم به اهداف این کوارتر رسیدیم، ایول حالا بریم کوارتر بعدی. این مدلی ما تسک بندی میکنیم.
- یک بیلیون کاربر فعال رو درست گفتی؟ فکر کنم چند برابر جمعیت زمین هست!
نه درست گفتم! Billion تو فارسی میشه یک میلیارد! :)
شکل رسیدن اهداف به تیمها، در قالب یه structure هست که بهش میگن OKR. مفهوم OKR احتمالا تو شرکتهای دیگه به شکل دیگه وجود داره ولی بنیان گزارش گوگل هست. OKR یه مفهوم دو لبه هست که از لحاظ مدیریتی باید هم از بالا به پایین به این مفهوم برسیم و هم از پایین به بالا. OKR مخفف objectives and key results هست. یعنی شرکت میاد اهدافش رو مشخص میکنه که میشه objectiveهای شرکت، مثلا شرکت میگه ما بفرض میخوایم به ۱۰۰ میلیون یوزر جدید برسیم، این میشه objective یا در کنار یه سری اهداف دیگه. برای رسیدن به این اهداف چیزی میاد که تضمین کننده رسیدن یا عقلانی بودن اهداف میشه، به اسم key result. یعنی اگر به این نتایج برسیم (هر objective معمولا چندتا key result داره) این objectiveمون انجام شده. مثلا شرکت اعلام میکنه session کاربرا رو از ۲ ساعت بکنیم ۲.۵، ما برگردیم بگیم شدنی نیست غیر منطقی هست یا ایول شدنی هست بریم انجامش بدیم. این بحث دو طرفه هست تا objective مشخص بشه. بعد از اینکه هدف قابل دسترس شد، ما به عنوان تیمها میایم key resultهامون رو مشخص میکنیم. یعنی میگیم ما برای اینکه به این session برسیم، تیم سرچ consumption آهنگهارو از ۵ دقیقه به ۷ دقیقه، از ۱۰ دقیقه به ۱۵ میرسونه. پله پله میبره بالا. چجوری؟ مثلا با اجرا کردن این A/B تست و مارکت کردن توی فلان کشور و کار x و y و z. یعنی میگیم ما به عنوان تیم سرچ برای رسیدن به این هدف چیکار میکنیم. تیمهای دیگه هم key resultهاشون رو اعلام میکنند، key resultها از تیمهای مختلف جمع میشه تا مشخص شه ما توی کوارتر بعدی یا سال بعد قراره چیکار کنیم تا به این هدف برسیم.
- به key result نمره میدید؟
بله
- به اون تیکه که گفتی قراره ۵ بشه ۷ نمره میدید؟
آره درجه اولویت داره و یه سری از بقیه مهمتر هستند. مثلا ما تصمیم میگیریم بریم وارد بازار چین بشیم و شرکت میگه این هدف شماره یک هست. متناسب با اون چند هدف دیگه هم اعلام میشه ولی هدف شماره یک مهمترین هست و برا همه درجه اولویتش بالاست. key result که متناسب با اون هدف یا آبجکتیو اعلام میکنی هم ردهبندی داره و میگی مثلا من برا objective شماره ۱ این key result رو مشخص میکنم برا objective شماره ۲ اینارو و ممکنه به objective شماره ۳ نرسم چون هدف شماره ۳ هست و انقدر هم مهم نیست ولی هدف ۱ و ۲ اولویت بالا داره و باید بهش برسیم.
- با توجه به اولویتی که داره ضریب میدید؟
تقریبا درصدی میریم جلو و زمان درصدی تقسیم میشه، مثلا تا آخر ۳ هفته بعد باید به objective شماره یک برسیم، بکلاگمون رو نگاه میکنیم، میبینیم این آبجکتیو ۱۰ تا تسک داره که هنوز انجام نشده در نتیجه میایم با برنامه نویسها یا آدمهایی که باید پیادهسازی کنند صحبت میکنیم و میگیم که چقدر زمان میخوای که این رو انجام بدی؟ میگه من این ۱۰ تا تسک رو تو ۲ هفته انجام میدم. برا اون یه هفته باقی مانده برا objective شماره ۲ تصمیم گیری میکنیم، خوب تو این هفته چندتا تسک میتونی انجام بدی؟ میگه مثلا از objective شماره ۲ این ۲ تا رو میتونم انجام بدم. اول باید به objective شماره یک برسی در کنارش باید برای بقیه هم حرکت کنی.
- چطور OKR با اسکرام هماهنگ میکنید؟
اول OKR از C level manager اعلام میشه و به alliance منیجرها ابلاق میشه (تیم بزرگ که همه تیمهای فنی توش بودن، همه HR، همه ریکروتر و … همه اینها برا خودشون alliance دارند. برای ما تیم دسکتاپ، وب، موبایل و … توشند) اینا پروداکتهایی که دستشون هست رو خوب میشناسند، alliance میگه مثلا برای اینکه به ۱۰۰ میلیون کاربر برسیم پروداکت موبایل ۶۰، دسکتاپ ۲۰، اتومبیل ۵ و … میلیون کاربر جدید جذب کنه.
آبجکتیو که تو alliance مشخص شد، alliance منیجر میاد به ترایب منیجر (ترایب همون چندتا اسکواد کنار هم بود و ترایب منیجر مدیر بالا سر همه اسکوادهایی هست که تو این ترایب کار میکنند) میگه شما به عنوان مدیر ارشد بخش موبایل باید تضمین کنی سال بعد ۶۰ میلیون کاربر بگیریم. حالا ترایب منیجر تقسیمبندی میکنه، برای این کار باید این مارکت رو بگیریم، اونکار رو کنیم و …. یا اگر بگن session کاربر افزایش بدیم از ۱ ساعت بکنیم ۱.۵ ساعت، یه تقسیمبندی میکنه میگه تیم home شما باید انقدر افزایش بدید، تیم سرچ انقدر، تیم آرتیست انقدر، میشکونتش به اسکوادهای مختلف و اون موقع هست که به تیم ما به عنوان پایینترین سطح هرم مدیریتی محول میشه. مشخص میشه OKR ما برای ۳ ماه بعد یا سال بعد ۱۵ دقیقه افزایش session کاربر توی جستجو هست. حالا ما به عنوان تیم سرچ این توانایی داریم و تصمیم میگیریم این کار رو بکنیم، اون فیچر اضافه کنیم و به این شکل افزایش میدیم. وقتی همه تیمها sessionشون رو افزایش بدن در نهایت کل اسپاتیفای سشنش از ۱ ساعت میشه یه ساعت و نیم چون هر کدوم از تیمها جدا این کار رو میکنه.
تو تیمهایی که XP یا اسکرام کار میکنند، بعد از تصویب OKR کجا نوبت اسکرام و XP میشه؟
این رو product owner تصمیم میگیره، با توجه به چیزایی که بهش اعلام شده و آبجکتیوها و توانایی تیم شروع میکنه و فیچرهای ۳ ماه بعد رو مشخص میکنه. مثلا این A/B Test رو ران کنیم یا … توی backlog جیرا میذاره، متناسب با اون اسپرینت میبنده، زمان بندی میکنه، تسکها محول میکنه و …
- تو xp که اکثرا تسکها روزانست و تایم کمتر و اسپرینت نداریم مشکلی پیش میاد، از کجا بفهمیم یا چه جوری زمان بندی کنیم که این تسکها تو اون ۳ ماه تموم شه؟
این یه تعامل هست بین product owner, technical owner و ما برنامه نویسها. product owner میگه من این فیچرو میخوام پیادهسازی کنم نیازمندیش (sub task) میشه این کارا. technical owner آدمیه که چند سال تو اسپاتیفای بوده، هم خودش خیلی سابقه کار داره هم تیم رو خوب میشناسه هم برنامه نویسهارو، میگه با توجه به تجربم به این تسک میتونیم برسیم یا نه.
وقتی sub taskها مشخص شد مثلا با من صحبت میکنند، میگن ما این کارارو میخوایم بکنیم، تو اسپرینت اول باید به اینا برسیم تو اسپرینت دوم به اینا و … آیا میتونیم انجام بدیم؟
من متناسب با برنامه و کارای خودم میگم آره یا نه. ولی ممکنه یه فیچر انقدر مهم باشه که حتی اگر من نتونم انجامش بدم، اسکواد ما مجبور بشه از یه تیم دیگه یک یا دوتا اندروید انجینیر بگیره؛ موقت بگه شما ۳ یا ۴ ماه بیایید توی تیم ما تا این فیچر رو بتونیم پیاده کنیم. این فیچر انقدر برا شرکت مهم باشه که اسکوادهای دیگه حاضر باشند این فداکاری رو بکنند. بگند اندروید انجینیر ما ۲ ماه بره و ما اندروید دولوپ نکنیم ios یا بکاند دولوپ کنیم، چون باید به اون فیچر برسیم. هدفهایی که خیلی مهم هست هرجور شده باید بهش برسیم حتی اگر شده نیرو از جای دیگه بگیریم.
- هر سطح OKR خودش رو داره؟
دقیقا هر اسکواد و هر ترایب که میشه مجموعهای از OKR اون اسکوادها و هر alliance میشه مجموعهای از OKR اون ترایبها
- اگر به این اهداف نرسیم چی؟
یه سری اهداف هرجور شده باید بهش برسیم. کسایی که این اهداف رو مشخص میکنند آدمهای معقول و عاقلی هستند، میدونند آیا ما اصلا بهش میتونیم برسیم یا نه. اگر هدف انقدر بلند پروازانه باشه که نتونی بهش برسی یعنی اون مدیر واقعا کارش رو بلد نبوده که همچین هدفی تعیین کرده. هرکس باید بتونه تو جایگاه خودش درست تصمیم بگیره؛ اون مدیر کارش اینه که بتونه برنامهریزی درست کنه، مدیری که نتونه تخمین درستی از تیمش داشته باشه که بدرد نمیخوره.
ولی نهایتا پیش میاد که به هدفی نرسی، وسط کار زلزله اومد برنامه نویس مرد. در نهایت یه جلساتی برگزار میشه وقتی به یه هدفی نرسی یا برسی، وقتی sprint رو میبندیم یا quarter یا سال تموم شه، جلساتی داریم به اسم retrospective، تمام اعضایی که تو اون هدف شرکت داشتند مثلا تمام اعضای سه اسکواد میشینند با هم retrospective اسپرینت قبلی رو برگزار میکنند. آیا ما به همه اهداف رسیدیم؟ اگه رسیدیم دممون گرم. اگه نرسیدیم چرا نرسیدیم؟ چه نیازمندیای داشتیم؟ اشتباه برنامه ریزی کرده بودیم؟ نیرو کم داشتیم؟ بلد نبودیم این code base رو؟ یا مثلا code base جدید به ما داده شد نمیدونستیم چیه؟ هرچی هست دلیلش باید مشخص شه اصلا مهم نیست کی اشتباه کرده، دنبال قاتل بروسلی نمیگردند و فقط میخوان علتش مشخص شه که دیگه تکرار نشه. اگه اشتباه برنامهریزی کردیم، اگه زیاد رو خودمون حساب کردیم و رو تواناییهامون بیش از حد معقول حساب باز کردیم باید یاد بگیریم دفعه دیگه این کار رو نکنیم. یا مثلا اگر ما تو این اسپیرینت جای ۲۰ تا تسک ۶۰ تا برداشتیم دفعه دیگه نباید این اشتباه رو بکنیم. یا مثلا اگه engineer با این framework خوب آشنا نیست و نمیدونه باید چیکار کنه براش کلاس بزاریم و بقیه انجینیرها بهش یاد بدن چطور کار کنه، یا نیروی جدید بگیریم. یا ۴ تا pr جدید بود و باید review میکردم کارم سنگین بود نرسیدم در نتیجه از اسپرینت بعد با تیمهای دیگه صحبت میکنیم اگر قرار pr بدند از قبل باهامون هماهنگ کنند که تو زمانبندی حسابش کنیم، یا برای اندروید انجینیر ۱ ساعت اضافه در هفته در نظر بگیریم چون باید pr ریویو کنه. هرچی هست علتش مشخص شه و حلش کنیم. تا جایی که بشه سعی میکنیم یا این اتفاق نیوفته یا اگر افتاد بلافاصله یه retrospective برگزار بشه و یاد بگیریم که چی از این قضیه یاد گرفتیم، چی شد که ما این اشتباه رو کردیم و دیگه این اشتباه رو تکرار نکنیم.
- گفتی با تیم مارکتینگ هم در ارتباط هستید؟ تصور من این بود که باید تو یه الاینس دیگه باشه.
همینطوره که میگی ولی الاینسها باید با هم کار کنن که به اهداف شرکت برسیم! تیم مارکتینگ با ترایب خودش هماهنگ میشه، ترایب ما هم به اونها میگه این کارها لازمه انجام بشه و اونها سعی میکنن انجامش بدن! در واقع Tribe Lead ها باهم توافق میکنن! اینجور تصمیمها تو لایه مدیریتی و بین Product Owner/Tribe Lead اتفاق میوفته.
ما یه سری جلسات بدرد بخور داریم و فکر میکنم برگزار کردنش خیلی راحت هست. برا ماها خیلی میتونه مفید باشه فارغ از اینکه تو چه شرکت و با چه ابعادی کار میکنیم.
ما ۲ تا جلسه داریم که همه افراد تو یه اسپرینت باید توش حضور داشته باشند.
یکیش جلسه برنامهریزی هست که معمولا روز اول اسپرینت هست، چیزی نزدیک ۳ الی ۴ ساعت از زمان اون اسپرینت به برنامه ریزی برای ۲ هفته آینده میگذرونیم. شما لازم نیست تو کل اون جلسه حضور داشته باشید چون ممکنه برای ios، اندروید و بکاند تصمیم بگیریم. تنها افرادی که حتما باید حضور داشته باشند product owner و technical owner هستند، شما میتونی تا آخر بشینی یا فقط بخش مخصوص به خودت رو بری.
جلسه دیگه همون retrospective هست، مخففش میکنیم retro. یه جلسه یک یا ۲ ساعتس که روز آخر اسپرینت برگزار میشه و حتما همه باید حضور داشته باشند، اول تا آخرش. این جلسهای هست که توش اسپرینت قبلی رو بررسی میکنیم؛ به همه تسکها رسیدیم یا نرسیدیم؟ اگه نرسیدیم چرا نرسیدیم؟ معمولا به همه تسکها میرسیم چون سعی میکنیم موقعای که برنامهریزی میکنیم دیدگاهی عاقلانه و منطقی داشته باشیم. رو تواناییهای نداشتمون، یا میرم یاد میگیرم و اینا حساب نمیکنیم، رو چیزی که الان داریم حساب میکنیم. من تا حالا فقط یه اسپرینت بود که تسک انجام نشده داشتم. تازه اومده بودم و از همون اول میدونستیم که احتمالا به یه سری از تسکام نمیرسم. چون تازه داشتم یاد میگرفتم چی به چی بود. بعد از اون تقریبا به همه اسپرینتها میرسیدم.
بلافاصله بعد یه جلسه داریم که بهش میگن demo. باید چیزی که تو این ۲ هفته روش کار کردی رو demo کنی. ممکنه پیور programming باشه و ui هیچ تغییری نداشته باشه، ولی میای demo میکنی مثلا من این رو refactor کردم، جای اینکه از این استفاده کنم از این یکی استفاده میکنم خیلی بهتر شد. یا مثلا unit test coverage رسوندمش به این. تو ui شما هیچی نمیبینی ولی محصولی که دستت هست رو بهبود دادی میای این رو demo میکنی.
جلسات retro planning و demo در سطحهای بالاتر برای کل ترایب و الاینس هم هست ولی لازم نیست شما تو اونا بری، معمولا product owner میره اونجا. مثلا رتروهایی که تو ترایب برگزار میشه میگه تیم سرچ تو ۲ هفته گذشته کار ۱ ۲ ۳ ۴ رو انجام داد. تیم فلان این کار رو کرد و …. این نشون میده که آیا پروژه داره پیشرفت میکنه یا نه؟ آیا جایی گیر کرده یا نه؟ آیا جایی نیاز به کمک داره یا نه؟
یک نقش خیلی جالبی هم داریم اینجا به اسم delivery lead، یکی از مدیرهای نسبتا بالا با سابقه طولانی تو اسپاتیفای که تو هر ترایب هست. این آدم مطمئن میشه آیا تیمهای مختلف با اون OKR که تنظیم شده میرن جلو یا نه؟ ما هر ۲ هفته یک جلسه با این آدم داریم. مثلا از من میپرسه اون تسکی که داشتی روش کار میکردی انجام دادی یا نه؟ (به برد جیرا ما دسترسی داره) خوب انجام دادی عالیه تسک بعدی به موقع بهش مرسی؟ ممکنه من بگم آره میرسم یا بگم تسک بعدی یه هفته بیشتر زمان لازم دارم چون میخوام برم مسافرت این جزو مواقعای هست که ممکنه یه اسپرینت بهم بریزه ولی OK هست. برای اینکه من هم آدم هستم و میخوام برم از زندگیم لذت ببرم. یا ممکنه بهش بگم یه هفته بیشتر زمان لازم دارم چون باید فلان تکنولوژی رو یاد بگیرم باز هم OK هست، چون من دارم برای رسیدن به اون هدف تلاش میکنم. delivery lead کارش این هست که اسکوادهای مختلف به اون آبجکتیوهایی که بهشون اعلام شده و key resultهایی که تعریف کردن برسند. مطمئن شه این اسکوادها سلامت و توانایی لازم برای رسیدن به اونها رو دارن. مثلا آیا لازم هست آدم جدید به این اسکوادها اضافه شه یا نه؟ delivery lead محصولهای که این اسکوادها باید تحویل بدن رو جمع آوری میکنه. دونه به دونه میپرسه این رو انجام دادی؟ هر ۲ هفته تکرار میشه و باهاشون جلسه داره.
یه جلسهای ۱۵ دقیقه توی تیم ما هست که صبح ساعت ۹:۴۵ برگزار میشه همون Stand-up meeting، یه لیستی از موارد رو معمولا بررسی میکنن. یکی اینکه امروز باگی به ما ریپورت شده یا نه و اگر ریپورت شده درجهاش چیه. ما ۵ درجهی اهمیت توی شرکت داریم که بهشون میگن p1 تا p5. اگر باگ p1 به تیم ریپورت بشه، یعنی بخاطر پروژهی شما کدبیس داره کرش میکنه، هرکاری الان دستت داری رو بذار زمین و شروع کن این باگ رو فیکس کن. اگر لازمه یه هفته بمون شرکت این باگ رو درست کن. البته من از وقتی شرکت بودم به پروژهی ما p1 ریپورت نشده ولی با توجه به باگی که بهتون ریپورت شده ممکنه لازم باشه با کسی که ریپورتش کرده صحبت کنی که چیکار کردی کرش کرد، یا یه ورژن جدید براش بسازی که تست بکنه و از اینجور چیزا. البته ممکن هست چند روزی باگ ریپورت نشه.
بعد از اون کارهای روزمرهمون چک میشه مثل TeamCity و اینکه که کی باید چیکار کنه. معمولا کارهارو ریپورت میکنیم که مثلا من فلان کد رو میزنم، بکاند فلان کد رو میزنه، شاید من بگم امروز حتما این اندپوینت بکاند رو لازم دارم اگر میشه اینو زودتر انجام بدید. یه سری هماهنگیهای داخل تیمی هست. و در آخر هم یه سری بحثهای مختلف که یکی مثلا بگه امروز نمیتونم بیام یا فردا کار دارم.
ابزارها
ما تو اسپاتیفای از git برای سورس کنترل استفاده میکنیم، بطور دقیقتر از github. شرکت یه برنچ enterprise از گیتهاب خریده و وقتی میخواید کدی کامیت کنید یا pull requestها رو چک کنید تو گیتهاب شرکت میبینید.
برای issue tracking و چک کردن تسکها از jira استفاده میکنیم.
از crashlytics برای crash reporting استفاده میکنیم. یکی از منابع دقیق چک کردن تعداد یوزرهای اکتیو هست. برام جالبه که crashlytics استفاده میکنیم نه google analytics.
برای دولوپمنت از Android studio 3 beta 2 استفاده میکنیم، چون چند وقت پیش پروژه بخاطر حجم زیادش شروع کرد به کند و کند شدن. برای هر سری بیلد پروژه اندروید استودیو باید یه apk از پروژه بسازه و ببره روی emulator یا دستگاه deploy کنه تا بتونید تستش کنید؛ وقتی کد پروژه خیلی زیاد بشه، کامپایل کردن و ساختن اون apk طولانی میشه. برای همین کل کامیونیتی اندروید (جاوا بیشتر) اومدن یه راه حلی ارائه دادن که کدبیس رو modularize کنید، یعنی کدتون رو ماژولهای مختلف کامپایل شده کنید و وقتی کد میزنید نیاز نباشه همهی برنامه کامپایل شه تا یه apk ساخته شه. اگر دارید روی کلاس یا ماژول جدا کد میزنید فقط همون ماژول کامپایل میشه و بقیه ماژولها byte codeهای آماده جاوا هست و شما فقط قسمت خودتون رو میذارید کنار اون byte codeها و apk میگیرید. این کار رو بهش میگن modularization که الان یه سری شرکتهای نسبتا بزرگ تا حدی درگیرشن، یا انجامش دادن یا میخوان انجامش بدن. خلاصشو بخوام بگم یه ماژولی که شما میخواید روش کار کنید manifest خودشو داره، کدهای جاوای خودشو داره، اطلاعات ماژول در فایلهای yaml جدا میذارید، همه چی تو ماژول خودتون تعریف میشه، انگار کلا با یه پروژه دیگه کار میکنید. زمان بیلد از وقتی که build clean میکردیم و گریدل همه چیو بیلد میکرد قبلا حدود ۱۰ دقیقه طول میکشید، ولی با این روش حدود ۱۰ ثانیه شده، به شکل خیلی خیلی محسوسی زمان بیلدمون پایین اومده. شرکت چند وقت پیش نفر ساعت حساب کرده بود یه رقم خیلی زیادی رو داشت عملا مینداخت دور، فقط چون منتظر گریدل میشدیم. به همین دلیل ما پروژه modularize رو شروع کردیم. چون اندروید استودیو ۲ روی کدهایی که ماژولارایز هستند خیلی بد و کند هست به مشکل خوردیم. بچههای شرکت یه کانال مستقیم با گوگل داشتند و قبل اینکه اندروید استودیو ۳ ریلیز شه یه سری تستها کردند و دیدن جواب میده و خیلی بهتر میشه. در واقع اندروید استودیو ۳ خیلی بهینه شده برای کدهای ماژولارایز. رفتیم روش و دیدیم خیلی خوب جواب میده و ازش استفاده کردیم. حتی از زمانی که canary (قناری) بود استفاده میکردیم. اما بعضی وقتها پایدار نیست، حتی الان که بتا هست به مشکلایی میخوریم. ممکنه کرش کنه یا اتفاقات عجیب بیوفته. تا الان فقط کد بیس اندروید ۱۵۰ ماژول داره و اگر نمیرفتیم روی ماژولارایز کردن دیگه داستان بود و از همه کارهامون عقب میوفتادیم.
ابزار دیگه TeamCity هست، پروژهای که شرکت JetBrains نوشته و برای مدیریت تستها هست. باهاش میتونید چک کنید امروز چندتا تستمون fail شده، Integration testing فیل شده دارید یا نه، End-to-End Test فیل شده دارید یا نه. مثلا ایمولاتور اومده لاگین کرده رفته توی فلان صفحه و روی یه آهنگ کیلک کرده ولی اون آهنگ پخش نشده. این یه تست خیلی خیلی مهمه که fail شده و شما باید همون روز چکش کنید. ممکنه یکی یه جای دیگهی کد، یه تغییری داده باشه که الان پلیر کار نکنه. تیم پلیر باید بره End-to-End تست رو چک کنه ببینه اشکال از کد ما بوده یا از اونا، براشون یه باگ ریپورت کنه که اینو درستش کنید چون پلیر کار نمیکنه. برای همین هر روز باید داشبورد TeamCity چک بشه.
معماری
تو شرکت دو معماری نرمافزار داریم mvp و mvvm. بسته به اینکه چیکار میکنید معمولا یکی از این دو تا استفاده میشه. Flat کلا وجود نداره و اگر شما فلت کار کنید نتیجه میگیرند که کارت رو بلد نیستی و تقریبا باید از شرکت بری. Flat architecture بیمعنی هست و باید پروژه architect بشه و همه سر اون معماری توافق کنند. من کدی که فلت باشه اصلا بهش دست نمیزنم. mvp مزایای خودش رو داره mvvm هم همینطور. برای کدهایی که معمولا ماها میزنیم، مثلا یه بکاند و فرانتاند هست که باید به هم وصل شه و یه اطلاعاتی بخونید و چیزایی تو دیتابیس بریزید از mvp استفاده میکنیم، دلیلشم تست پذیری mvp هست. وقتی برای قسمت رندرینگ بخوایم کدی بنویسیم از معماری mvvm استفاده میکنیم. برای اینکه رندر کردن خیلی راحتتره، درواقع کارهای ui. جدا کردن بخش logic و سپردن interaction به دست observableها و rxjava توی mvvm خیلی راحتتر میشه، برای هابز که کار رندرینگ رو انجام میداد از mvvm استفاده کردیم.
یه بحثی تو معماری mvp هست به اسم multiple presenter. برای مثال بخوام بگم وقتی وارد شرکت شدم، به پروژه سرچ کمک میکردم. وقتی از بیرون به کد بیس بخش سرچ نگاه کنید، یه لایه ویو داره و یه پرزنتر که لاجیک سرچ اونجا انجام میشه و یه مدل و از اینجور داستانها؛ منتها خودش از بخشهای مختلفی تشکیل شده. ما کلا دو تا سرچ اصلی توی اسپاتیفای داریم. یکی دکمهی ذرهبین که میزنید و میری اونجا کاراتون رو میکنید، یکی سرچ قسمت رادیو. بخش رادیو اسپاتیفای هم یه سرچ داره که اون رو هم ما باید مینوشتیم و لاجیکش تا حدی فرق میکرد. وقتی چیزی رو سرچ میکنید و ریسپانس شامل آهنگها آلبومها و … میاد، یه قسمتی نوشته see all، اگر روش بزنید صفحهی همه آهنگها و آلبومها رو میاره، اونجا هم لاجیک خودشو داره. همین برای رادیو هم وجود داره. این فقط بخش معمولی سرچ بود. شرکت بعد از مدتی تصمیم گرفته بود که محصول جدیدی داخل اسپاتیفای ارائه بده، یه لایه جدید از یوزرهای free که داستانی پشتش داره، کاری با بخش بیزینسش نداریم. فکر کنید شرکت یه پروداکت جدید اضافه کرده بود، خود این پروداکت جدید متناسب با نیازش سرچ رو تغییر داده بود، درواقع ما باید برای هر پروداکت که داخل شرکت تعریف میشد یه سرچ متناسب با اون مینوشتیم. مثلا ممکنه سرچ رادیو ورژن جدید با قبلی هم ui، هم endpointهای بکاندش، logic، logging، همه چیش فرق بکنه. یه مفهومی وجود داره توی mvp به اسم multiple presenter که میگه برای هرکدوم از این کارها presenter خودشو بساز و تستهای خودشو بنویس و لاجیک هر کار رو جدا هندل کن. منتها چون اینها یه سری functionality داره که بین هم مشترک هست، طبیعتا از یه سری سوپر کلاس استفاده میشه تا کد duplicate نشه.
مشکل دیگه که تو کد بیسهای بزرگ وجود داره پشتیبانی از ورژنهای مختلفی هست که تا حالا ریلیز کردی. شما حساب کنید این ۶ تا مدل مختلف سرچ تو طول زمان عوض شدن، framework هاشون فرق میکنه، مدل کد بیسش فرق میکنه، اصلا سرچ قبلی تو یه کلاس دیگه وجود داره. مثلا سرچی که اسپاتیفای ۳ سال پیش نوشته هم معماریش فرق داره هم ابزاراش، همه چیش فرق داره ولی چون هنوز تعداد زیادی یوزر دارند و ازش استفاده میکنند و رو ورژنهای قدیمی اسپاتیفای هستند باید اون رو هم ساپورت کنید. در نتیجه وقتی یه فیچر رکوئستی به ما داده میشه، مثلا اضافه کردن فلان دکمه توی سرچ، در ظاهر یه دکمه کوچیکه اما شما باید برا ۶ مدل مختلف سرچ این رو اضافه کنی و برای ورژنهای قبلی backward compatibility داشته باشه. یعنی باید بری تو یه کلاس دیگه که ممکنه dependency injection متفاوتی داشته باشه، mvp نباشه و رو چیز دیگه باشه، به اونم اضافه کنی. همینطور برا تمام اینها باید تست نوشته شه. یعنی شما نمیتونی اینجا یه کد بزنی بگی من خودم دستی تستش کردم کار میکنه. تو شرکت یه استانداردی وجود داره به اسم end to end testing منتها نه به معنی خود end to end یعنی شما باید تمام لایههای تست رو رعایت کنی. وقتی یه کد مینویسی معماریش باید درست باشه، میره تو ریویو و چند نفر میان ریویو میکنند. ممکنه یه سری نظر بدن، معماریش این قسمت اشتباه داره، ممکنه اون قسمتش leak بکنه، اینجا از این ابزار استفاده کن و …. تمام این ریویوها که تموم شد، شما باید تستت قانون ۸۰٪ کد کاوریج رعایت کنه. یعنی کدت باید ۸۰٪ توسط تست کاور شده باشه. لایه پرزنتر توسط unit test باید ۱۰۰٪ کاور شده باشه. بعد از یونیت تست اگر componentهات تغییر کرده باید integration test براشون بنویسی، یعنی دونه دونه کامپوننتها باید جدا تست بشند قبل از اینکه برند با مستر مرج بشند. مثلا اگر یه باتن رو کلیک میکنی قراره یه انیمیشنی اجرا شه و یه کاری بکنه این رو به عنوان یه کامپوننت integration تست براش بنویسی. تازه تو مرحله بعد اگر back end یا end point جدیدی رو دارید تست میکنید، یا اگر کاری که میکنید خیلی برای یوزر critical هست که معمولا پروداکت منیجر و تیم تعیینش میکنه، باید براش end to end test بنویسی، یعنی یه تستی مینویسی که apk میره رو emulator نصب میشه، دیپلوی میشه، بعد لاگین میکنه، میره اون کاری که شما کردید رو انجام میده، بکاند واقعای رو تست میکنه جواب رو میگیره چک میکنه و اگر همه چی کار کرد اون موقع تست pass میشه و میگه شما کارت موفقیت آمیز بود، در غیر این صورت کدت تو مستر مرج نمیشه، چندین بار review میشه هم بخش تستش هم بخش کد نویسیش.
این جا کد نوشتن یه خرده دردسرهایی داره، معمولا چندتا ورژن رو باید ساپورت بکنی، چندتا ورژن تست بنویسی، بعضی ورژنها اصلا باهم همخونی نداره چون معماریش فرق داره یا ممکنه همهچیش فرق داشته باشه.
- چرا هنوز کد بیس ۳ سال پیش باید تغییر کنه؟
برای اینکه تعداد زیادی کاربر ازش استفاده میکنن، در واقع همه بخشهای پروژه از یک تکنولوژی استفاده نمیکنن، ممکنه چند سال پیش نوشته شده باشه و از اون موقع ریفکتور و بروز رسانی نشده باشه!
- مگه آپدیت کنه کلا آپدیت نمیشه؟
نه الزاما! مثلا صفحه Home و Search دست تیم ما هست! و هرکدوم یه مدل و تو یه زمان نوشته شده! مثلا تو Home از یه کتابخونه برای فلان کار استفاده شده و تو Search از یه کتابخونه دیگه! اینه که ممکنه مجبور بشی برای یه کار دوتا کد با Stack کاملا متفاوت رو تغییر بدی ولی جفتشون یه کار رو باید بکنن در نهایت
تایتل این قسمت رو نمیدونم چی انتخاب کنم
از ۶ ماه پیش حتما باید TDD هم بنویسیم. البته نهایتا زمانی که کد رو پوش میکنیم کسی نمیفهمه شما TDD نوشتید یا نه، منتها وقتی با یکی پر پروگمینگ میکنید و همیشه بغل دستتون هست یا یه چیزی رو توضیح میدید مخصوصا اگر ببینند یک لاجیکی تست نشده باشه این نشون میده شما TDD ننوشتید.
مثلا فکر کنید یه پرزنتری داریم که قرار هست کار شماره ۱-۲-۳ رو بکنه که اینا لیست میشه تو داکیومنتی که داریم. برای اینکه TDD بنویسیم، اولین شروع میکنیم براش تست شماره ۱ رو مینویسیم؛ تست رو اجرا میکنیم و faile میشه، بعد شروع میکنیم حل کردن مشکل. چیکار کنیم که این تست پاس شه؟ کدش رو مینویسیم تا تست pass. و میریم سراغ سناریو ۲ تستش رو مینویسیم و تست faile میشه و شروع میکنیم تست رو حل میکنیم تا آخر. اگر لازم باشه کد رو ریفکتور میکنیم و در نهایت زمانی که کد رو submit میکنیم پرزنترها باید annotation خاصی داشته باشند، برای اینکه بات کد review میاد کلاسها رو چک میکنه و اگر پرزنتیشن لاجیک داشته باشه یعنی این کلاس قرار هست pure جاوا باشه و هیچ قابلیتی از اندروید نباید توش استفاده بشه. این کد باید ۱۰۰٪ تست کاوریج داشته باشه، یعنی به اعضای هر خط کدی که اونجا نوشته شده باید یک تست باشه. هر لاجیکی که هست باید تست شده باشه واگرنه به صورت اتوماتیک پول ریکوست شما ریجکت میشه، اصلا نمیتونید مرج کنید. ۴۳ تست مختلف رو prتون ران میشه، رو هر کامیتی که میکنید اگر رو یه پول ریکوست ۵ تا کامیت هم باشه به اعضای هر ۵ تا تمام تستها روش اجرا میشه. این تستها شامل Static analysis میشه یه سری استانداردها که تعریف شده و با فایلهای xml مشخص میشه. مثلا بعد از اینکه اسم کلاس رو نوشتید باید یه اسپیس بزارید، زمان تعریف تابع حتما باید پابلیک پرایویت یا پروتکتد بودنشون مشخص باشه. یه سری قانون داره اینارو چک میکنه رو کامیت. بعد مثلا به این میرسیم که این کد آیا تست به اندازه کافی داره؟ رو ورژن ریلیز کانفلیکت نمیخوره؟ وقتی که تست تموم شد شما یه نفر رو پینگ میکنید میگید بیا کد من رو review کن. کد review میشه ممکنه یه سری نظر بده اعمال میکنید و کد مرج میشه میره تو master. هرکسی هم رو fork خودش کار میکنه پول ریکوست میده رو مستر مثل کاری که تو گیتهاب رو لایبراریهای معروف انجام میشه. به اعضای هر ریلیزی هم که قرار هست اتفاق بیافته یه برنچ ساخته میشه.
rxJava
توی شرکت از rxjava خیلی خیلی زیاد استفاده میکنیم، ۲ تا چیزی که تو مصاحبه من خیلی روش تاکید شد، یکی چقدر رو rxjava مسلطم و چقدر best practiceهای خود جاوا رو بلدم. تقریبا برای همه چیز از rxjava استفاده میشه. البته تو پروژه اصلی به خاطر infrastructure هنوز رو rxjava1 هستیم. چون هنوز یه سری چیزا تو rxjava2 ساپورت نمیشه نمیتونیم بریم روش. ولی از بکاند بخوای با نتورکینگ چیزی بگیرید، یا io انجام بدید، رو دیسک چیزی بزارید، بین پرزنترها مسیج رد و بدل کنید، هرکاری که بخواید بکنید با rxjava انجام میشه و خیلی به دردمون میخوره.
مدل استفاده اینجا از rxjava برای من اوایلش یه مقدار عجیب غریب بود. تجربه قبلی خودم این بود، کدی رو که مینویسید یه observableای هست بعد باهاش یه سری اطلاعات رو subscribe میکنید مثلا map میکنید به یه چیز دیگه، لازم باشه switch map میکنید، لازم باشه compose میکنید، هر کاری که لازم باشه روی زنجیره کارای rxjava انجام میدید. منتها اینجا مدلی که پیاده سازی کردن و باید تبعیت بکنید اینه که هر کدوم از این فانکشنها برای خودش یه کلاس هست. یعنی اگر بخواید ورودی رو بگیرید مپ کنید به یه چیز دیگه، نمیتونید یه rxchain دو - سه تایی پشت هم بنویسید بگید این رو مپ کن به این، بعد سویج مپ کن به اون و …. کاری که باید بکنید اینه که یه کلاس بنویسید بگید ورودیش اینه خروجیش اینه و تابع map رو implement میکنه. مثلا function1 رو ایمپلیمنت میکنه. توی کلاس کد رو مینویسید و کلاس و آبجکت کلاس رو توی rxchain تون پاس میدید بین هم دیگه. نه اینکه یه زنجیره بزرگ از اوپراتورهای rxjava داشته باشید. اولش مفهوم این یه خورده برای من گیج کننده بود، چون پیش میومد مثلا یه زنجیری از rxJava به وجود بیاد که ۱۰ تا اوپراتور داشته باشه و دیباگ کردنش اوایل برای من عجیب بود، مثلا یه باگی ریپورت میشد و لازم بود یه زنجیر rxjava رو چک بکنم و گیج میشدم یهو آبجکت از این کلاس رفت تو اون کلاس، از اون کلاس برگشت پاس داده شد به یه کلاس دیگه، اوایلش مدل متفاوتی برای من بود.
اخیرا از فریمورک شرکت که متن باز شده استفاده میکنیم و اون واقعا رو نحوهی استفاده از rxjava و شکل استفادمون فرق ایجاد کرده، اسمش Mobius هست، کدش رو اگر Clone کنی توش مثال هم هست، میبنی یکم متفاوت معماری rx chain توسعه داده شده.
DI
برای dependency injection تقریبا از یه سال پیش از dagger 2 استفاده میشه. تقریبا الان هر چیز جدیدی که مینویسید باید با دگر ۲ داخلش دیپندسیها اینجکت بشه و قبل از اون هم constructor injection بود. به جز constructor تقریبا جای دیگهای حق نداشتید آبجکتی رو new کنید. نمیتونستید توی فانکشن بگید من یه object احتیاج دارم الان اینجا new کنم. اگر همچین کدی مینوشتید پول ریکوستتون با static check که داشتیم failed میشد. چون new کردن آبجکت داخل scope فانکشن با اصول دیپندنسی اینجکشن solid مغایرت داره، اگر میخواید همچین کاری بکنید باید اجازه بگیرید. یعنی یه سری permission خاص بگیرید که به این دلیل لازمه اینجا باشه، اون موقع فقط برای اون pr خاص اجازه صادر میشه. معمولا نمیبینید هرجای کد یه سری آبجکت new شه، اینجا خیلی روی اصول solid تاکید میشه.
Test
هرم تست اینجا به شکل کامل رعایت میشه، unit test خیلی زیاد داریم، تا جایی که میتونید باید یونیت تست بنویسید. Presenter تو معماری mvp باید ۱۰۰٪ code coverage داشته باشه واگرنه پول ریکوست failed میشه. integration test تا جایی که نیاز باشه. end to end test بنا به نیاز نوشته میشه، چون خیلی زمان گیر هست اجرا کردنشون. critical user journey (مهمترین کاربریهای یک اپ، مثلا در مورد اپ اسپاتیفای بخش گوش دادن موسیقی، جستجو، ثبت نام، خرید اشتراک، موارد اینطوری که خیلی حیاتی هست رو میگن بهشون) رو end to end test براش مینویسیم. آخر هم manual test داریم، هر هفته جمعه تمام تیمهای اسپاتیفای از ساعت ۱۰ تا ۱۱:۳۰ manual test دارند چون هر جمعه ریلیز داریم.
یه داکیومنتی هر جمعه فرستاده میشه برای تیمها و شما باید این داکیومنت رو امضا بکنی که من پروداکتم رو تست کردم داره کار میکنه یا تست کردم باگ داره ریلیز نکنید. تمام تیم تو اون ۱.۵ ساعت جمع میشند و پروداکتی که دستشون هست رو تست میکنند. چیزای مختلف که اون هفته روش کد نوشته شده یا چیزای قبلی رو تست میکنند. استرس تست یا …. خلاصه ۱.۵ ساعت manual testing هست، تا جایی که میتونید باید چیزای مختلف رو تست کنید که یه وقت باگ نداشته باشه.
GLUE
تو این ۶ ماهی که تو شرکت بودم، تا حالا یکبار هم نشده یه فایل xml رو تغییر بدم. یعنی اصلا فایل xml ندیدم، البته توی پروژهها هست ولی نیاز نشده برم استفاده بکنم. از چند سال پیش اسپاتیفای یه مفهومی رو به شکل داخلی معرفی کرد به اسم glue که دقیق یادم نیست مخفف چیه، اگر اشتباه نکنم یه چیزی مثل Global Language for a Unified Experience هست. اومدند تمام کامپوننتهایی که تو اسپاتیفای استفاده میشه رو تو یه زبان مشترکی به اسم گلو تعریف کردند. مثلا button, checkbox, recyclerview یا هر چیزی که به عنوان ریسورس تو ویو استفاده میشه مثل background, image, color، هر المنت ui که داریم و میخوایم به کاربر نشون بدیم، یه بار تعریف کردن و شما از اون به بعد از این المانهای تعریف شده استفاده میکنید و دیگه تو xml نمیگید خوب یه باتن بساز عرضش انقدر باشه طولش انقدر، یا از تم فرگمنت ارث ببر، از تم اکتیوتی ارث ببر، هیچ کدوم از این کارا رو نمیکنید. فقط میگید یه باتن گلو به من بده، خودش میسازه متناظر با استاندارد اسپاتیفای تنظیم و برای شما تو صفحه دیپلوی میکنه. این باعث میشه که شما هر دفعه xml مختلف نسازید و ادیتش نکنید. باعث ui consistency تو تمام پلتفرمها میشه. چون یه تیم پشت گلو هست و کارش اینه که این المانها رو بسازه و بین پلتفرمهای مختلف سینکش کنه. برای همینه که امکان نداره موقعیتی پیش بیاد که یه باتن تو اندروید یه پیکسل بزرگتر از ios باشه. چون تیمی این کارارو انجام میده براش تست مینویسه نگهداری میکنه maintain میکنه. اگر قرار باشه باتن جدید اضافه شه، شکل جدید اضافه بشه شما نمیتونید این کار رو خودتون بکنید، باید feature request بدید به تیم گلو و بگید من این رو احتیاج دارم. دیزاینر طرح رو بزنه آماده بکنه با کل اسپاتیفای استاندارد بشه و بعد برای پیادهسازی تحویل تیم glue بشه. این تیم دیزاینر زیاد لازم داره چون ذاتش دیزاین هست انجینیرهای اندرویدش هم از اینایی هست که فقط دارند با ویو کار میکنند، با xml یا کلاسهایی که از ویو اسکتند شده. اصلا لاجیک نمیزنند.
تیم ما دیزاینر خیلی کم احتیاج داره گاهی یه دیزاینر برای مدت کمی با تیم ما امبد میشه. مثلا برای ریفکتور کردن browse جلسه گذاشت که میخوام این شکلی بکنم این درفت اولیه کار هست چالش داری یا نه؟ نهایی که شد پیاده میکردیم. دیزاین و داکیومنت میداد این باید این شکلی باشه پدینگ و … این باشه. بچههای بکاند هم با glue انجام میدادن ولی یه سری کامپوننتهای کاستومایز شده برا یه پلتفورم هست یا یه فیچر خاص هست معمولا اینارو کلاینت انجام میده.
HUB
یه فریمورکی تو اسپاتیفای وجود داره به اسم HUB که بخش iosش بصورت open source رو گیتهاب شرکت هست، اندرویدش هنوز open source نشده و شاید به خاطر هزینه نگهداری نکنند.
- اوپن سورس شه هزینه نگه داری میره بالا؟
خیلی، چون کدش باید تمیز باشه و مو لای درزش نره. اگر تحت فشار یه کدی رو بزنی میتونی بگی این کامیت رو ۲ هفته دیگه تو اسپرینت بعدی درستش میکنم. ولی اگر open source باشه نمیتونی کد غلط مرج کنی، برای اینکه خیلی راحت ریورسش میکنند و یه سری از نسخههای اپلیکیشن ممکنه هک شه. به خاطر همین دردسر داره نگهداری لایبراریهای open source.
شرکت یه چالشی داشت برای آپدیت نگهداشتن کاربرهای قدیمی که هزینش خیلی زیاد بود. یعنی یه شکل یا ظاهر جدید که قرار بود به اپلیکیشن اضافه شه باید کلی برای کاربرهای قدیمی سرمایهگذاری میکردن و یه سری کد برای گوشیهای قدیمی میزدند «if ورژن کمتر از این بود این کار رو بکن». حالا اگر بخواد یه شکلی توی اپلیکیشن عوض شه شما باید اون if رو بریزید بهم و برای همه ورژنها یه چیزی رو عوض کنید. یا اگه recycleView بخواید داشته باشید و یه سری المان تو لیست نشون بدید باید یه xml میساختید ریسایکلر ویو رو داخلش میذاشتید، بعد adapter میساختید و event handlerهای آداپتر رو هندل میکردید، اگر روی آیتم کلیک شد چیکار کن؟ اگر swipe کرد چیکار کن؟ الی آخر. دردسر نگهداری خیلی زیاد بود، برای همین و همینطور جلوگیری از duplicate شدن کد یه مفهومی تعریف کردن که نمیدونم اولین بار اسپاتیفای داده یا جای دیگه به اسم backend driven ui development-BDD یعنی بکاند مشخص بکنه ui تو اپلیکیشن چه شکلی باشه، یه چیزی مابین Hybrid نوشتن و Native هست. اگر یه dump از خروجی json صفحات اسپاتیفای بگیرید، میبینید بکاند داره استراکچر رندر شدن توی کلاینت رو ارسال میکنه. یه سری چیزها توافق شده بین ۲ تا تیم، مثلا spotify_button, spotify_card, spotify_view, spotify_listview چیزایی که ممکنه یک دیزاینر بخواد توی برنامه رندر شه. یک تیمی وظیفش اینه که این دیزاینهارو تبدیل کنه به کامپوننتهایی که توی اندروید، ios، وب و دسکتاپ قراره رندر شه و نگهداریشون کنه و کافیه ما از کامپوننتهای هابز استفاده میکنیم. هابز به ما این قابلیت رو میده که بکاند بگه این باتن رو با این رنگ رندر کن. توی تیمی که من کار میکنم تا حالا لازم نشده یه دفعه هم یه باتن توی کدم بنویسم، تنها کاری که میکنم جیسانی که بکاند میفرسته رو پاس میدم به هابز و میگم این جیسان رو رندر کن. اون خودش با enumهایی که داره iterate میکنه، اگر recyclerview بهت دادم برو این رو برام بذار، اگر recyclerview item از نوع فلان بود لیست رو این جوری بساز، و در نهایت میگید که به من یه ویو لیست HUB بده، و این تو فریمورک بین اندروید، ios، بکاند و تمام پلتفرمها expose شده. هرچیزی پایین تولبار (به جز تولبار) رو هابز میتونه رندر کنه و بکاند به صورت داینامیک میتونه استراکچر صفحه رو عوض بکنه. خیلی راحت بدرد A/B Test میخوره، مثلا میخوایید بدونید توی یک صفحه اگر کاربر لیستهای ۲ تایی کنار هم ببینه ux بهتری داره یا یه هدر بزرگ با یه سری لیست؟ خیلی راحت با یه کد واحد سمت کلاینت از سمت بکاند میتونیم برای کاربرای مختلف تو یه صفحه چیزای متفاوت رندر کنیم. backward compatibility خوبی هم بهتون میده مثلا اگر یه کمپین تبلیغاتی قرار شد لانچ شه برای یه کاربری که از ۲ سال پیش اسپاتیفایش رو آپدیت نکرده خیلی از کامپوننتهایی که اون موقع تعریف کردیم رو میتونیم استفاده کنیم بدون این که کاربر مجبور شه آپدیت کنه. به این مفهوم میگند backend driven ui development - دولوپ ui توسط بکاند. یا اگر یه تیمی بیاد یه فیچر جدید رو بخواد امتحان کنه، لازم نیست یه ریلیز بدید که اون فیچر جدید امتحان شه. Ui جدید توسط بکاند فرستاده میشه، ایونت هندلرهاش سمت کلاینت از قبل توی هابز نوشته شده که مثلا اگر این دکمه رو زدم اون کار رو بکن، اگر لانگ کلیک کردم اون کار رو بکن و …. خوبیش اینه که اگر به هر دلیلی ریلیزهاتون بلاک شد مثلا گوگل شما رو بلاک کرد گفت ورژن جدید نمیتونید بدید چون یه مشکلی وجود داره، ui تون دیگه قدیمی نمیمونه و میتونه عوض شه.
طبیعتا اگر بخواید چیزای خیلی خیلی کاستومایزی بنویسید حتما باید ریلز بدید ولی تا حد خوبی جلو این قضیه گرفته میشه.
ما برای همچین چیزی داشتیم فکر میکردیم که چطور میتونیم یه معماری استفاده بکنیم که کارمون رو راحت بکنه، mvvm برای این انتخاب شد چون یکی از قواعدی که باید توش رعایت شه اینه که دولوپر دسترسی مستقیم به ویو نباید داشته باشه. یعنی شما به عنوان کسی که داری مدل یه چیزی رو مینویسی یا ViewModel یه چیزی رو مینویسی به خود ویو نباید دسترسی داشته باشی، این برای خودش یه سری چالش میاره. مثلا فکر کن اگر بخوای یه چیزی رو تو این فریمورک تعریف کنی که خارج از تواناییهای عادی این فریمورک هست عملا هیچ کاری نمیتونی بکنی، چون به ویو دسترسی نداری که مثلا یه انیمشنی روی باتن بزاری. اگه فریمورک ساپورت نکنه نمیتونی، چون اولین کاری که باید انجام بدی view.setAnimation یا … هست. در نتیجه با وجود اون دردسرهایی که ایجاد میکرد چون در اسکیل بالا کار خیلی از تیمها و نگهداری خیلی از چیزها رو راحت میکرد تصمیم بر این شد که رو mvvm پیادش کنیم.
Hermes
اگر بخوام یه ذره عمیقتر شم، از چند سال پیش یعنی زمانی که HTTP1 بود و هنوز HTTP2 استاندارد نشده بود، شرکت فریمورکی به اسم Hermes نوشت (فکر کنم اوپن سورس هست). هرمس یه فریمورکی رو HTTP1 بود که قابلیت HTTP2 رو بهمون میداد. خیلی شرکتها این رو نوشته بودن چون HTTP1 از یه زمانی به بعد دیگه جوابگو نیاز بعضی از شرکتها نبود و اسپاتیفای هم برای خودش نوشت. اسپاتیفای به نظر من استاد ساختن چرخ از اول هست، چون خیلی چیزارو میبینید از اول برای خودشون نوشتن، برای من عجیبه شاید نیاز بود بنویسند، شاید پروژههای دیگه جوابگو کارشون نبوده، ولی خیلی چیزارو از اول نوشتن. حتی الانم که HTTP2 اومده به شکل زیر ساختی وارد پروژه شد ولی ما همچنان رو هرمس هستیم. برای ما فرقی نداره که HTTP1 استفاده میکنیم یا HTTP2 چون پروتکل هرمس برای ما همهرو هندل میکنه و یه تیم داره که نگهداریش میکنه. خیلی خوب هست این قضیه چون abstract میشه و دیگه لازم نیست ۱۰۰ تیم مختلف بیان آپدیت بکنند، یه تیم آپدیت میکنه برای تمام پروژه apply میشه.
Core
توی اسپاتیفای به مفهومی وجود داره به اسم هسته یا core. کور اسپاتیفای یه سری فانکشنالیتیهایی هست که بین پلتفرمهای مختلف share شده. مثلا player یا نتورکینگ که با hermes انجام میدیم. core با ++c نوشته شده، پروژه نسبتا بزرگی هست و فکر کنم یه تیم ۲۰ نفره فقط مسئول نگهداری core هستند که شامل پلیر، هرمس و یه سری چیزای دیگه هس، من دقیقا نمیدونم چیکار میکنند چون امکان نداره آدم همیشه بدونه همهی تیمها چیکار میکنند. خیلی شرکت بزرگه، فقط کار خودت رو بتونی خوب انجام بدی هنر کردی. من به شخصه به تیم core خیلی علاقه دارم چون ++c رو خیلی دوست دارم. اگه یه موقع احساس کردم میخوام یه چیز جدید رو امتحان بکنم یکی از گزینههایی که دوست دارم contribute به core هست. همونطور که گفتم پلیر با core هندل میشه و یه پروتکل کاستوم براش نوشته شده. پلیر هم یه کد نسبتا قدیمی هست چون از خیلی وقت پیش ساپورت میشد، ولی آخریا ساپورت رو تا اندروید ۴.۱ آوردیم. به خاطر پروتکلهای مختلفی که بین ورژنهای اندروید ساپورت میشه نمیتونستیم به مدیا پلیر خود اندروید اکتفا کنیم. مجبور بودیم مدیا پلیر خودمون رو بنویسیم که بتونه کدکها و پروتکلهای خودمون رو ساپورت بکنه. و این بود که مجبور شدند یه مقدار low level و با ++C بنویسند تا بتونند توی پلتفرمهای مختلف بصورت مشترک استفاده بکننش. چون نمیشد فقط با جاوا بنویسی، اگر اونجوری میخواستیم بنویسیم باید یکی برا جاوا مینوشتیم، یکی برا ios، یکی برا وب، یدونه برا ps ،xbox و …
CI & CD
ما الان رو continuous integration هستیم و قرار هست تا آخر ۲۰۱۷ continuous delivery بشیم در حال حاضر مشکلی که وجود داره و دردسر ساز میشه اینه که ما تستهای premerge و postmerge داریم. یعنی مثلا شرکت ۱۰۰۰۰ تست داره، از این ۱۰۰۰۰ همش قبل از اینکه کد مرج بشه، اجرا نمیشه یه سری بعد از مرج شدن روی کد اجرا میشه. این باعث باگهای بدی میشه، برای مثال شما ممکنه کدی بنویسید و تستهای premerge بگند کدت OK هست و مرج بشه تو مستر. تستهای postmerge هر چند ساعت یکبار اجرا میشند، به خاطر اینکه خیلی تستهای پر هزینهای هست و طول میکشه بخواد اجرا شه. معمولا هم end to end تستها هستند. بعد از مرج شدن کد و قبل از اینکه تست postmerge روی کد شما اجرا بشه یه نفر دیگه هم یه کدی نوشته برای اون هم تستهای premerge با موفقیت گذرونده میشه و کدش توی مستر مرج میشه. حالا بعد از ۶-۷ ساعت تستهای postmerge اجرا میشند و میبینند این دوتا pr با هم inconsistent هستند و نمیتونند با هم اجرا بشند. یا اصلا باعث crash میشه. اون موقع هست که میگند مستر شکسته -master is broken. کد اصلی مستر ممکنه خراب شه و اون موقع معمولا یه هشداری توی شرکت داده میشه و یکی باید بیاد (نویسنده اون ۲ تا کامیتی که باعث شدن مستر بشکنه، اگر خودش نیست جایگزینش اگر جایگزینش نیست مسئول پروژش) و خیلی سریع با هم مستر رو درست کنند. و اگر نه کل پروژه گیر میکنه. این یکی از مشکلهای عمده ci هست، که همه کامیتها قابل deliver کردن و قابل deploy نیست. به خاطر همین از یه سال پیش شرکت یه تیمی رو تشکیل داد که وظیفش کمک به همه تیمهاست که از ci برسند به cd و هر کامیت قابل deploy باشه. یه خورده هم پروژه زمان بری هست، چون کلی از تستهای شرکت باید تغییر بکنه، خیلیهاش اصلا باید زیر ساختش تغییر کنه ولی هم کار جذابیه و هم نتیجهاش ارزشمنده.
کد گردی
- اسپاتیفای با اینکه قراره بخشهایی از پروژه رو نشونمون بدی مشکلی نداره؟
بهشون گفتم که میخوام یه چیزایی رو برای آموزش نشون بدم.
برای فیچرهایی که از ۱-۲ سال پیش شروع شده همه حتما باید از دگر استفاده کنند. این الان کل پروژه هست و این پکیجی هست که کد سرچ توش وجود داره قبلا این پکیج ۲ تا بود، چون ۲ تا ورژن از سرچ وجود داشت. ما با یه مکافاتی قبلی رو ریفکتور کردیم و آوردیم رو فریمورک جدید و قبلی رو پاک کردیم.
استراکچر اینجوری هست که ما با خودمون توافق کردیم پرزنتر یه جا باشه، کدی که لاگ میکنه یه جا باشه، بخشی که هیستوری سرچ هست یه جا، کالبکها تو یه پکیج هست، کاموننتها (ویوهایی که کاستوم کردیم خارج از هابز، توی فریمورک هابز نبودن و بهش اضافه کردیم) و کامندهایی که ساپورت میکنیم تو پروژه رو هم توی یه پکیج گذاشتیم.
فریمورک هابز برای ما یه سری کارهای جادویی انجام میده، مثلا رندر میکنه یا یه سری کامند که از پیش تعریف شده از سمت بکاند ارسال شه رو خودش هندل میکنه. مثلا شما میتونید با کمتر از یه ساعت کد زدن ورژن ساده صفحه سرچ رو یه بار دیگه از اول درست کنید، یعنی یه پرزنتر ساده مینویسید، بعد یه endpointی رو صدا میزنید و جواب رو به هابز تحویل میدید، خود هابز بقیه چیزارو هندل میکنه و میاره بالا، همه کارهایی که بصورت پیشفرض نیازه مثل click, long click, play و یه سری کامند دیگه رو خودش ساپورت میکنه. منتها یه سری کارهارو لازم هست که به صورت کاستومایز شده انجام بدید مثلا اگر توی سرچ رو چیزی کلیک کردید، بسته به این که چی هست کارهای مختلفی باید انجام شه. مثلا اگر آهنگ باشه باید پلی بکنه، یا اگر آلبوم باشه باید بره تو صفحش و تو هیستوری کاربر هم نگهش دارید، این چیزی بود که بصورت پیش فرض ساپورت نمیشد. مثلا برای این مجبور شدیم یه command handler کاستومایز شده بنویسیم و توی هابز خودمون اضافش کنیم، که فلان کامند رو خودم میخوام هندل کنم؛ یا وقتی رو این کلیک شد دیگه هابز هندلش نکنه من خودم هندلش میکنم.
- فیسبوک هم یه کتاب خونه داره که دیستریتیو ui مینویسی دیدینش؟ (Litho)
ما کتابخونههای فیسبوک رو اکثرا نمیتونیم استفاده کنیم به خاطر لایسنسش که یه مقدار سختگیرانست، چند وقت پیش هم react رو عوض کردند و ما تازه تو دسکتاپ شروع کردیم از react استفاده کردن وگرنه قبلا فکر کنم angular مینوشتند.
این کدی هست که باهاش لاگهای مختلفی که تو پروژه انجام میشه رو مینویسیم، ۲ تا پرزنتر مختلف داره یه پرزنتر برای صفحه سرچ و یکی برای صفحهای که با زدن دکمه see all میرید اون تو.
توی کد مدلهای مختلف ریکوست رو ما به بکاند میزنیم، مثلا همین صفحه سرچ ریکوستهای مختلفی به بکاند میزنه، یکیش صفحه سرچ تو حالت عادی هست که میاید یه کوئری میزنید یه جواب میگیرید، ممکنه از صفحه سرچ تو حالت آفلاین استفاده بکنید که ما به هسته ++C ریکوست میزنیم و اون هم تو مجموعه ریکوستها قرار میگیره، یا صفحه see all هم یه مدل ریکوست میزنیم.
شرکت یه محصول جدیدی تعریف کرد که خوبه در موردش صحبت کنیم. اسپاتیفای بعد از یه مدتی بررسی و نتیجهگیری، بصورت عمومی اعلام کرد که ما یادگرفتیم چطور کاربر پرمیوم بسازیم، یعنی کاربر معمولی رو تبدیل کنیم به کاربر پریمیوم و حتی یاد گرفتیم چطور کاربر پرمیوم رو پرمیوم نگه داریم. در نتیجه خوب داریم پول در میاریم. فقط مشکلی که داریم اینه که نمیتونیم به اندازه کافی کاربر جدید بگیریم و مجبور شدند سراغ کشورهایی که بهشون بازارهای نوظهور (emerging market) میگند مثل چین، هند، اندونزی یا کشورهایی مثل مکزیک، برزیل برند. با توجه به محدودیتهایی که این کشورها دارند، اپ فعلی اسپاتیفای اصلا براشون مناسب نیست. این بود که یه ماموریت جدیدی تو شرکت تعریف شد که یه اپی بنویسیم (داخل خود اپ اسپاتیفای) که برای این مدل کشورها طراحی بشه، یکسال کار کردند و این محصول الان ریلز شده. کلا یه محصول دیگه داخل اپ هست. یعنی وقتی کاربر وارد اپ میشه کلا میره تو یه سری پکیج دیگه. مثلا نویگیشن باتن ۳ تا بود، صفحه اصلی استراکچرش عوض شد، بکاندهایی که باهاش صحبت میکردیم عوض شد، قابلیتهای سرچ تغییر کرد، صفحه browse رو با سرچ یکی کردیم. خلاصه بسته به اینکه چه مدل کاربری هستید، تعداد زیادی ریکوستهای مختلف به بکاند زده میشه.
برای همین وقتی شما یه پروداکتی توی شرکت دستتون باشه، روی همون تعداد زیادی A/B Test داره انجام میشه یا در واقع پروداکتهای مختلفی رو در قالب یه پروداکت مشخص دارید به مردم ارائه میدید (مثل همین اپی که برای بازارهای نوظهور درست شده و توی همون اپ اسپاتیفای هست)، یعنی معمولا سرچ رو یه سری کاربر به یه شکل میبینند یه سری دیگه به یه شکل دیگه و همه اینا جزو زیر مجموعه تیم شما هست. اگه قرار باشه یه چیزی عوض شه یا یه پارامتری به صورت کلی به بکاند ارسال بشه یا یه uiیی اضافه شه، معمولا شما مجبورید کل این پروداکتها ریفکتور کنید. در نتیجه معمولا حجم کاری تو یه فیچر، از چیزی که به نظر میاد بیشتره.
این پکیح rx ما هست، این پکیج مجموعه کارهایی هست که ما با rx java انجام میدیدم.
- اگر برای صفحاتی که A/B test داریند تسک بیاد رو کدومش انجام میدید؟
باید بری همه رو ریفکتور کنی
- یعنی جفتش تو apk هست و سرور میگه کدوم رو لود کنه؟
تو سرچ حتی چالش برانگیزتر بود. صفحه اصلی یه معماری و یه سری فریمورک استفاده میکرد دکمه see all رو که بزنی میره تو یه فرگمنت دیگه تو اون کلا یه چیز دیگه بود. مثلا اگر رو یه ترک کلیک کنی تو صفحه اصلی سرچ و اون صفحه باید یه کار رو بکنه، نمیشه تو یکیش پلی کنه تو اون یکی یه کار دیگه. ۲ تا چیز رو باید همزمان maintain میکردی. یا بدتر تو هر کدوم از این فرگمنتها ۴ تا A/B test وجود داشته باشه باید اونا رو هم حتی ساپورت بکنی بعضی وقتها وقعا چالشی میشد ساپورت کردن چندتا ورژن از یه چیزی. به این مفهوم که چندتا ورژن مختلف و چندتا معماری و سبک کد زدن مختلف توی کدبیس باشه میگن شما Technical debt دارید (بدهکاری فنی)، یعنی شما هزینه نگهداری یه کد قدیمی رو میدید و این رو اگر توی طول زمان درست نکنید به صورت تصاعدی بالا میره و تکنیکال دبت رو توی سطح معینی نگه دارید.
- کی باید درستش کنیم؟
معمولا اینجوری میشه، برای سه ماه بعد میخوای برنامهریزی کنی و یه ab تست گندهای روی پروژه ران بشه، میپرسن چقدر پیاده سازیش طول میکشه؟ که شما میگی دو ماه. میگن چرا دو ماه؟ میگید چون این تکنیکال دبت داره. میگن خیلی خب ab تست رو نگهدارید و اول تکنیکال دبت درست کنید. سه ماه زمان میذارید، کلی کد ریفکتور میکنید، تستهای قدیمی رو حذف میکنید، معماریشو عوض میکنید و باید از اول بنویسید.
- این رو پروداکت اونر میگه یا تکنیکال لید؟
بستگی داره، ممکنه حتی از بالاتر بیاد.
- همه اینا که میگی توی پکیج سرچ و برای سرچ بود؟
آره خارج از سرچ نیست، هر فیچر همه اینارو برای خودش جداگونه داره
- همه تیمها همین شکل پکیجبندی میکنند یا فرق داره؟
کم و بیش همینجوری هست، مخصوصا اسکوادهای که تو یک ترایب باشند، چون با هم جلسه زیاد داریم و با هم زیاد کار میکنیم. برای همین احتمالا کدهای یه اسکواد تو نیویورک رو ببینید خیلی متفاوت هستند. البته معمولا اگر تیمها با هم قرار باشه کار کنند، یه داکیونتی رو با هم رد و بدل میکنند به اسم «چطور میخوایم با هم کار کنیم؟» اگر قرار باشه از تیم شما برای ما پول ریکوست بیاد و ما ریویو بکنیم این باید حداقل از ۲ هفته قبل اطلاع رسانی بشه که ما بتونیم براش برنامه ریزی کنیم یا اگر باگی پیش بیاد که شما کدش رو ادیت کردید خودتون باید رفعش بکنید. یه سری قرارداد میبندیم که ما قرار هست اینجوری با هم کار بکنیم.
خلاصه rx java تو تیم ما خیلی زیاد استفاده میشه مثلا توی فرگمنت سرچ ما بلافاصله یه subscription میسازیم و observableش رو وصل میکنیم به اون EditTextی که اون بالا هست، به محض این که شما شروع میکنید به تایپ کردن، اون EditText یه سری متن emit میکنه. ما میایم یه دونه observable از این استرینگ ها میگیریم و این رو با یه observable دیگه به اسم session state که session رو مانیتور میکنه (الان آفلاین شدم یا الان آنلاین شدم) combine میکنیم و search params ازش در میاریم. داخلش پارامترهای جستجو هست مثل آفلاینم یا الان آنلاینم تو چه وضعیتی هستم، کوئری چیه. بعد برای اینکه بتونیم یه ریکوئستی بسازیم، معمولا میاییم این ۲ تا پارامتر رو میگیریم و تحویل یه کلاس دیگه میدیم به اسم SearchRequestPerformer قبلا تو کلاس SearchRequestCreator بودیم. SearchRequestPerformer پارامترها رو میگیره و یه سری چک انجام بده، آیا کوئری که داریم بهش میدیم، خالی هست یا نه؟ اگه خالی نیست این رو flatmap کن به یه کلاس دیگه و … پارامترها رو میسازه و در نهایت تحویل SearchRequestRunner میده. اتفاقی که اینجا میافته، عملا این هست که ما اومدیم به جای اینکه یه زنجیرهی بزرگ از اوپراتورهای rx java داشته باشیم، برای اینکه خیلی راحت بتونیم براشون تست بنویسیم (چون این کلاسها باید ۱۰۰٪ تست کاوریج میداشتند) اومدیم هرکدوم از کارایی که قرار بوده سرچ بکنه رو شکوندیم به کلاسهای کوچیک، یه کلاس میاد یه observable میگیره باهاش یه پارام هولدر میسازه، یدونه فقط پارامترهایی که باید برای بکاند بسازه رو نگه میداره، وقتی ساخت تحویل یه کلاس دیگه میده فقط چک میکنه که پارامترهاش ولید هست یا نه، وقتی که چک کرد ولید هست تحویل یه کلاس دیگه میده این چک میکنه که سرچ الان آفلاینه یا آنلاین و مثلا تو کدوم استیت هست، مثلا برای صفحه see all دارم سرچ میکنم یا مثلا کسی با پارامتر خاصی من رو لانچ کرده یا نه، این رو که آماده کرد تحویل یه کلاس دیگه میده که فقط تایپ ریزالور هست چک میکنه که این دیوایس چه فیچری ساپورت میکنه آیا من میتونم مثلا از Protobuf استفاده کنم یا مجبورم از Gson استفاده کنم، و برای ارسال این دیتا به بکاند یه سری چیزارو چک میکنه. این rx chain رو شکوندیم به کارای خیلی کوچیک، یعنی وقتی نگاه میکنید، ما تعداد خیلی زیادی کلاس داریم که هرکدومش یه کار خیلی کوچیک رو میکنه.
- یعنی الان لاجیکی که هر اوپراتور rx java میخواد اجرا کنه رو تبدیل به یه کلاس کردید؟
یه جورایی آره، در واقع rx chain ما به این شکل هست هرکسی کارش رو میگیره تحویل اپوراتور بعدی میده
- جنس این کلاس چیه ؟ یه کلاس معمولی جاواست همشون ؟
آره همشون POJO هستند و به همین خاطر هست که میشه ۱۰۰٪ براشون تست نوشت.
اومدیم در واقع این کارارو شکوندیم به یه سری کار خیلی کوچیک که هرکدوم یه کار خیلی کوچیک رو انجام میده و براش تست متناسب با خودش رو نوشتیم. یعنی شما امکان نداره حالتی پیدا کنید که تستی براش نوشه نشده باشه، چون کار خیلی کمی رو داره انجام میده.
مدل کد نوشتنمون تو شرکت معمولا به این شکل هست، اول میریم فرگمنت و پرزنتر رو میسازیم، بعد سنارویوهایی که قرار هست پرزنتر هندل کنه رو با TDD تستش رو مینویسیم و پیاده سازی میکنیم، دونه به دونه میریم جلو. این یه شمای کلی بود از این فیچری که ما تو سرچ پیاده سازیش کرده بودیم. حالا همونطور که گفتم برای هرکدوم از اینا باید دونه به دونه تست بنویسیم، یعنی بنویسیم که این کلاس کاری که باید انجام بده رو انجام میده یا نه، مثلا این تستی هست که برای پرزنترمون نوشتیم، تستها معمولا اینجوری شروع میشه که یه annotation دارن که این فیچر برای کدوم تیم هست. با Robolectric اجرا میشن. یه سری پارامتر رو به صورت پیشفرض با static final و … آماده کردیم، به جز اون چیزی که اتفاق میافته شما توی کلاسها نباید هیچ موقع آبجکتی رو new کنید، هرچیزی که یه کلاس لازم داره رو باید همیشه با dagger و بصورت constructor injection بهش پاس بدید، چون dependency injection باعث میشه تست نوشتن خیلی راحت بشه.
تعداد زیادی آبجکت داریم که کنار همشون خورده mock، علتش اینه که ما میاییم یه کلاسی رو میسازیم توی حالت تست، تمام آبجکتهایی که لازم داره رو mock میکنیم و دونه دونه توش اینجکت میکنیم، یعنی یه کلاس رو با تمام چیزایی که لازم داره به صورت ماک شده میاریم بالا. مثلا کلاسی که میخوایم تست کنیم یه کلاس دیگه رو برای هندل کردن یه باتن نیاز داره، این کلاس رو mock میکنیم و از طریق استراکچر given when then بهش دیتای ماک میدم. این استراکچر اینجوریه:
Given یعنی در شرایط فلان
When اگر این اتفاق افتاد
Then این کار رو انجام بده
مثلا وقتی رو این دکمه کلیک کردم و منتظر برگشت یک استرینگ از یه فانکشن بودم، این استرینگ رو برگردون به فانکشن بده. این آبجکتهای ماکی که داشتیم رو تنظیم میکنم میگم تو این شرایط اگر این رو کلیک کردم این کار رو بکن، اگر این کار کردم این کار بکن و سناریوهایی که واقعا توی اپ داره اتفاق میافته رو تنظیم میکنم و دونه دونه شروع میکنم چک کردن فانکشنها که تو پرزنتر هست، مینویسم اگر این اتفاق افتاد با توجه به این ماکها من منتظرم این جواب رو بگیریم، آیا میگیرم یا نه، اگر گرفتم فانکشن داره درست کار میکنه اگر نگرفتم یه چیزی این وسط خراب شده.
برای سناریوهای مختلف باید یونیت تست بنویسیم. مثلا تعداد خط کد پرزنتر ما ۴۳۴ خط هست ولی تعداد خط کلاس تست پرزنتر ۴۴۵ خط هست. بیشتر از ۱۰۰٪ کد کاوریج داره. یعنی احتمالا یه سری سناریو، دپریکیت شده.
- مثلا برای یه خط ۲ تا تست نوشتید؟
نه نمیشه برای این که یک نفر کدت رو ریویو میکنه
- منظورم اینه که یه متد که نوشتید فقط یه حالت تست مینویسید یا چندتا؟
یک متد باید یک کار رو بکنه، در نتیجه وقتی که برای یه متد ۲ تا تست مینویسی، یعنی متدت یه ایرادی داره. طبق اصول solid باید single responsibility داشته باشه. ولی بعضی جاها ممکنه پیش بیاد، اصلا نمیشه کاریش کرد. ممکنه این فانکشن ذاتا side effect داشته باشه و هیچ کاریش نمیشه کرد ولی به صورت کلی باید اون رو رعایت کنیم.
حالا فکر کنید یک المان ui رو ادیت کردید، برای این که تستتون یا پول ریکوستتون قابل مرج شدن باشه، باید برای اون کامپوننت ui که تغییر دادید integration test بنویسید. یعنی یدونه کامپوننت رو از شرایط واقعی مجزا میکنید، تستهایی که لازم هست رو روش اجرا میکنید، بدون این که مهم باشه در سایر المانهای اطراف اتفاقی میافته یا نه، یعنی در دنیا واقعی نمیخوایم تستش کنیم، فقط خود اون کامپوننت رو تنها میخوایم تست کنیم. مثلا رو یه باتن که کلیک میکنید، میخواید یه انیمیشنی روش اجرا بشه، این رو براش یه کامپوننت تست مینویسید، چطور؟ ما یه ابزار داخلی داریم که باهاش اینتگریشن تستها رو مینویسیم، (اسم فریمورک Caset هست) فکر نمیکنم اوپن سورس شده باشه و فکر کنم که هیچ وقت هم نمیشه، چون خیلی هکی هست و همه چیزش با هک کردن یه سری چیز روی robolectric نوشته شده. مثلا این کلاس اینتگریشن تستی هست که برای صفحه اصلی سرچ وجود داره، یدونه فرگمنت میسازه، فرگمنتی که میخوای توش یه تستی رو انجام بدی، مثلا من فرگمنتم رو کانفیگ میکنم با این شرایط میارم بالا، بهش میگم من یه کاربر free میخوام، یعنی زمانی که این تست رو ران میکنی، یه کاربر free بساز و اینجکت کن تو محیط برنامه و برنامه رو توی حالت پروداکشن بیارش بالا، یه سری فلگ override میکنم برای این کاربر، مثلا تستی که اینجا نوشتم، اسمش اینه testWithSearchResult، دارم تست میکنم که سرچ وقتی که موفقیت آمیز هست، result که من منتظرش هستم باید داشته باشه. چه جوری این کار رو انجام میدم؟ میام یه محیط کانفیگ میکنم، این تست یه جورایی BDD هست یعنی یه جورایی مبتنی بر یه رفتار مشخصی هست. حالا یه محیطی رو کانفیگ میکنم میگم اگر کاربر تو این فرگمنت اومد بالا:
when زمانی که من روی اون TextFiled فکوس کردم، کوئری که اون بالا تعریف کردم رو بذار توش، یه مدت زمانی منتظر باش
then اول چک کن که ریزالتها لود شدن یا نه، که این یه فانکشنی هست که به شما برمیگردونه که ریزالتها لود شدند یا نه، آخر سر چک میکنم که get number of show all تعداد آیتمهای شو آل من بیشتر از ۰ باشه.
این یه تست خیلی عمومی بود، بسته به سناریویی که میخوایم تست بکنیم، دقیقتر از این تست میکنیم. مثلا برای وقتی که چک میکنیم ریزالت وجود داره، تعداد تاپ ریزالتها، ریکوردها یا آرتیستها رو میگیریم. ما برای اون کوئری مشخص، اینجا مشخص کردیم که قرار هست بکاند ۰ تا تاپ ریزالت برگردونه ۴ تا آرتیست ۴ تا آلبوم الی آخر. کامپوننت این فرگمنت باید عین سناریویی که من منتظرش بودم رندر بشه، اگر رندر شد یعنی تست موفقیت آمیز بوده و اگر نشد یا یه مشکلی تو بکاند وجود داره یا تو فرانتاند، این تست همیشه هر ۶ ساعت یک بار روی کد بیس اجرا میشه، فارغ از اینکه کامیت جدیدی وجود داشته باشه یا نه، به ما کمک میکنه که مثلا اگر بکاند اشتباه کرد و به جای ۴ تا آرتیست ۳ تا برگردوند، تست fail میشه. ما سریع متوجه میشیم و براش تیکت مینویسیم و حلش میکنیم. یا مثلا اگر یکی اومد کد مارو ویرایش کرد، این تست ران میشه و متوجه میشیم مثلا کامپوننت ما بعد ویرایش درست رندر میشه یا نه.
- بکاند رو تست میکنید یا بکاند ماک هست؟
هم میتونه بکاند ماک شده رو تست کنه، هم بکاند واقعی بستگی به کانفیگ داره.
- بکاند همیشه دیتا ثابت میده برای این تستها؟ از کجا میفهمیم که بکاند خرابه یا مثلا یه آرتیست به دیتابیس اضافه شده؟
این رو دیگه باید چکش کنیم و ببینیم اشتباه از کجا هست ولی این فلگها که اورراید میشه معمولا برای این هست که همیشه تا حد امکان یه ریسپانس مشخص رو بگیره.
اگه کامپوننت ui رو ادیت بکنید، باید یه دونه اینترگریشن تست مناسب باهاش رو هم بنویسید. بعد از این مرحله، یه مرحله بالاتر هم تو هرم تست وجود داره به اسم end to end testing، تستهایی هستند که با espresso مینویسیم و رو دیوایس واقعی اجرا میشند و همیشه با بکاند واقعی کار میکنند.
- این هرمی که گفتی یونیت تست مشخص هست، اون بالا بالایی هم که end to end test هست مشخصه که با اسپرسو کل یه عملکرد برنامه تست میشه مثلا یوزر چه کارایی میتونه انجام بده. حالا این وسط اینترگریشن تست میشه اکتیویتی با فرگمنت؟ چه جوری محدودش رو مشخص میکنید؟
هر چقدر به سمت بالا هرم تست حرکت بکنی هزینه نگهداری و اجرا کردنش خیلی میره بالا. یعنی ما هر دفعه که end to end تست ران میکنیم، end to end تست میاد یه apk رو برمیداره میبره رو یه دونه دیوایس نصب میکنه، login میکنه و …، هزینه اجرا این تست خیلی زیاده و وقتی ما بخوایم اندتواند تست بخش سرچ رو ران کنیم، نیم ساعت طول میکشه. اما اینترگریشن تستهامون کمتر از ۱ دقیقه و یونیت تست کمتر از ۱۰ ثانیه طول میکشه. در نتیجه اگر قرار باشه یه اندتواند تست بنویسید باید حواستون باشه که آیا واقعا لازمه؟ چون تا جایی که میتونید، همه چیو باید با یونیت تست و اینتگریشن تست کاور بکنید. معمولا end to end تست رو برای جایی مینویسیم که سناریو فوقالعاده حیاتی و critical هست، مثلا لاگین هیچ موقع نباید fail بشه، اگر بشه خیلی افتضاح هست، کاربر جدید نمیتونه استفاده بکنه. یا مثلا توی سرچ این که ریزالتها یکبار لود شه و باتنها کار بکنه رو حتما باید تست کنیم. برای این که هر جمعه ساعت ۱۰ تا ۱۱ صبح regression test داریم. تمام اعضای تیم جمع میشن و نفری یه گوشی رندوم با یه کاربر رندوم برمیدارن و شروع به تست کردن یکی از فیچرهای شرکت میکنند، توی رگریشن تست همیشه همه اعضا از پروداکت اونر، مدیر، دیزاینر، برنامه نویس همه جمع میشند و تست میکنند، خوبیش هم اینه که اپ از زوایای مختلف تست میشه و اینجوری نیست که فقط از زاویه دید برنامه نویس تست شه. ریگریشن تست رو هفتهای یکبار اجرا میکنیم ولی end to end تست رو هر ۶ ساعت یکبار، اینتگریشن تست روی تکتک کامیتها تست میکنیم یعنی مطمئن میشیم چیزی که میخوایم واقعا رندر میشه یا نه.
- چندتا از هر کدوم دارید؟
برای هرکدوم ۲۰-۳۰ تا تست رو در نظر بگیر، تو یه کلاس منظورم هست، البته باید زمان بیلد شدن گریدل رو هم بهش اضافه کرد ولی اون خارج از دست ماست تا حد زیادی و ثابت هست. تعداد کلاس هم متناظر با تعداد کلاسهای که بیزنس لاجیک هست، تو یه پکیج شاید ۴۰-۵۰ تا کلاس هست، برای اینتگریشن تست حدود ۵-۱۰ تا کلاس و اندتواند ۱ دونه کلاس.
- گوگل جدیدا توی داکیومنت اندروید، یه بخشی نوشته، که مثلا end to end تست ۲۰ درصد باشه، یونیت تست ۶۰ درصد و … ولی کلا یه سری مثالها گفتن اینترگریشن تست رو با اسپرسو بنویسید، خیلیها اصلا اسپرسو تو اینتگریشن استفاده نمیکنند یا همش روبوالکتریک استفاده میکنند و … من نمیفهمم مثلا اشکال داره اسپرسو تو اینتگریشن استفاده شه؟ یا چون نیاز نمیشه کسی استفاده نمیکنه؟
اسپرسو یه قابلیت خوبی که به شما میده اینه که میتونید رو دیوایس واقعی اجراش کنید که میشه همون end to end تست، میتونی تو لول انتگریشن هم ازش استفاده کنی. ولی روبو الکتریک روی دیوایس واقعی کار نمیکنه و اندروید رو امولیت میکنه.
اندتواند تست هم معمولا با توافق تیم مشخص میشه «این سناریو خیلی مهم هست پس end to end تست بنویسیم». همه هم میگند تا جایی که میتونید هرم تست رو پایین نگه دارید ولی اینکه درصدش چقدر باشه سناریو چطور باشه تیم به تیم فرق داره. یه سختی دیگه هم که end to end تست داره اینه که باید براش ci یا cd تعریف کنید. مثلا jenkins راه بندازید، اتومیت کنید که اینا کار اندروید دولوپر نیست، اینا یه دوآپس خوب میخواد که این محیطها رو خوب بشناسه، از یه برنامه نویس عادی اندروید نمیشه انتظار داشت که هم کد خوب بنویسه، هم یونیت تست بنویسه، هم end to end تست بنویسه. همه اینا رو باهم از یه تیم کوچیک نمیشه انتظار داشت. اگر بخوای انتظار داشته باشی، سرعت کارت خیلی میاد پایین. ما خیلی از کارامون تو شرکت دلیگیت شده به یه تیم دیگه. مثلا خود تیم ما باتن نمینویسه و دلیگیت شده به تیم دیگه. هر تیمی داره یه کار کوچیکی انجام میده.
- تیمی که تست مینویسه یه تیم دیگست یا خودتی؟
نه خودمم. تست رو خود دولوپر باید بنویسه
- تیمی هم دارید که تست دستی انجام بده؟
نه همون ریگریشن هست که هر جمعه همه باهم تست میکنیم. یه نفر با نقش qa داریم ولی اون یه نفر نمیرسه همه چیز رو تست کنه، معمولا qa داشبورد تست رو maintain میکنه، مثلا صبح به صبح که میگیم این تست fail شد، معمولا اون آدم میره چک میکنه چرا fail شده، اگر سوادش رو داشته باشه ممکنه حلش بکنه اگر نه اساین میکنه به یه دولوپر.
ما کلا ۲ تا ویو تو سرچ نوشتیم، جمعا یدونه اون تولبار اون بالا که کاستومایز شدست و تولبار خود اندروید نیست، یکی هم وقتی که سرچ میکنید و نتیجه خالی باشه اون empty view میاد رو هم خودمون نوشتیم. بقیه چیزایی که تو سرچ نوشتیم لاجیک هست یا تست. ویو نمینویسیم. معمولا یه چیزی هم داریم به اسم ویو بایندر چون لایبراری که استفاده کردیم mvvm بوده، ویو بایندر واسطی هست بین ما و اون لایبراری که با توافق ما و اون تیم نوشته شده. مثلا ما بخوایم یه انیمیشنی اجرا بکنیم به ویو بایندر میگیم با اون لایبراری صحبت میکنه، خیلی چیز خاصی نیست.
بقیه کلاسها هم یا پرزنتر هست یا ماژولهای دگر یا کامپوننت یا فرگمنتها و اینطور چیزها. این کد بیس یکی از تیمهایی هست که داره اونجا کار میکنه.
- کد review مکانیزم خاصی؟ هرکسی میتونه کد کس دیگهای رو ریویو کنه؟
تمام کلاسهایی که نوشته میشه یه annotation داره که برا چه فیچری هست شما اگر کدی رو کامیت بکنی که مثلا یکی از کلاسهای فیچر ما ادیت شده باشه ما به صورت اتوماتیک پینگ میشیم تو اون کد ریویو. ولی الزامی نداره ما حتما تایید کنیم چون طرف ممکنه یه خط کامنت نوشته باشه. اگر بخوان یه آدم خاص ریویو بکنه پینگش میکنند ولی به صورت کلی هر تیم یه استاندارد داره که خود تیم مشخص میکنه. مثلا استاندارد تیم ما اینه که حتما اینتگریشن تست ۱۰۰٪ هست یا naming convention مشخص داریم comment style مشخص داریم اینارو کسی که با کد ما کار میکنه باید رعایت کنه. اگر یه فیچر رو برای یه تیم دیگه ادیت بکنی یه ایمیلی برات میاد و میگه این داکیومنت این تیم هست و باید بخونی و میگه آیا اینا رو رعایت کردی یا نه؟ چون نمیشه همه چیز رو تو استاتیک آنالایز چک کرد.
- ساختار پروژه رو کی تعیین میکنه؟
تو طول زمان عوض شده ولی به صورت کلی هر تیم مسئول حفظ و نگهداری سلامت فیچر خودشه. کس دیگهای نمیاد بهت بگه اینجوری کار کن مثلا از این استفاده کن خوبه یا بده. تماما به اختیار خود تیم هست و تو تیم تصمیم گیری میشه که چه شکلی باشه. این که به صورت کلی پروژه چه شکلی باشه معمولا انجینیرهای قدیمیتر تو لولهای بالاتر، مثلا یه نفر لید ترایب هست که اون جهت گیری فنی ترایب رو مشخص میکنه. معمولا هرچی لول بره بالاتر ضریب نفوذ روی پروژه به شکل high level افزایش پیدا میکنه. مثلا این که ما نمیتونیم از یه سری لایبراریها استفاده بکنیم دلیل اینه ترایب لیدمون نمیتونه اجازه بده این لایسنس رو تو پروژمون داشته باشیم.
سوالهای بچهها
- یه جا گفتی اگر به چندتا بخش پروژه کمک کنی مثل بک اند، دیتا ساینس و … استیتت میره بالاتر و وظایف بیشتری انجام میدی، آیا توی فیلد خاص خودت پیشرفت کنی بهتر نیست و برای شرکت ارزشمندتر نیست تا اینکه سعی کنی توی چندتا فیلد تلاش کنی؟
این سوال خوبیه که یه کار رو خیلی خوب انجام بدی بهتره یا چندتا کارو انجام بدی؟ دو مدل کلی برنامهنویس داریم. برنامهنویس T شکل و اگر اشتباه نکنم I شکل.
برنامهنویس T شکل برنامهنویسایی هستند که مثل حرف انگلیسی T بالاش یه خط داره که به یه خط دیگه عمود هست، یعنی شما توی دو جهت دارید حرکت میکنید. مثلا ممکنه یه سری زبانهای مختلف رو یاد بگیرید. این برنامهنویسا معمولا کسایی هستند که برای کارایی مثل مدیریت پروژه خیلی خوبن، کسایی هستند که معمولا میتونن بین تیمها مشترک باشند و آدمهای ارزشمندی هستند.
در برابر اینا برنامهنویسای I شکل یه خط دارند، معمولا اینا آدمهایی هستند که توی یه زبون خیلی خیلی عمیق میشن. اینا آدمهای کار راه اندازی هستند، یعنی کسایی هستند که وقتی هیشکی نمیتونه یه چیزی رو درست بکنه، اینا میان درست میکنن. سطح کاریشون هم خیلی بالاست و گرون قیمت هستند.
اینکه شما کدوم یکی از اینا بشی دست خودت هست، انتخاب خودت هست چه مدلی پیشرفت بکنی. توی همهی شرکتها به جفتشون نیاز هست. بعضی وقتا واقعا پیش میاد آدم از کاری که میکنه حوصلش سر میره، نیاز داره یه چیز جدیدتری رو امتحان کنه، مثلا شما وقتی دو - سه سال روی یه codebase کار کنی به همه چیزش تسلط داری. خب اون کدبیس چالش جدیدی برات ایجاد نمیکنه. خب اون موقع هست که شما یا باید بگی من از این شرکت برم به شرکت دیگه یا مثلا اگر شرکت امکانش رو داشته باشه بگه بیا برو توی یه تیم دیگه، برو یه زبان دیگه بنویس برو یه چیز دیگه یاد بگیر. چون این آدم آدم ارزشمندی برای شرکت هست، سه چهار سال دانش این آدم توی این شرکت بوده و خیلی حیف هست بذاریم بره. مثلا یا حقوقش رو بیشتر بکنن یا یه چیزی بهش میدن که توی شرکت بمونه. معمولا توی شرکتهای بزرگ سعی میکنن همچین امکانی رو به دولوپرها بدن که اگر بخوان بتونن یه چالش جدیدی داشته باشن برای انجام دادن. من بشخصه ترجیح میدم T شکل باشم.
- چطور میشه یه تست خوب نوشت؟ اگر کتابی هست معرفی کن؟ اصن یه تست خوب به چی میگید؟
یه تست زمانی میتونه یه تست خوب باشه که فانکشنالیتی خوبی رو تست کنه، یعنی شما در درجه اول باید کدی بنویسید که تمیز باشه تا بتونید تست خوبی بنویسید. مثلا یکی از مباحثی که توی شرکت سعی میکنند بهش زیاد رفرنس بدن یا زیاد استفاده کنند میگن فانکشن شما تا حد ممکن (البته بعضی وقتا نمیشه) نباید side effect داشته باشه. فانکشن زمانی ساید افکت داره که به جز ورودی و خروجی که میگیره و داره، یه سری کارهای دیگه هم بکنه. کدی که ساید افکت داشته باشه تست نوشتن براش سخت هست. چون تست نوشتن برای ساید افکت سخته. چند وقت پیش Dan Lew یه مقاله خیلی خوبی نوشته بود در مورد اینکه testability چه جوریه و چه فانکشنالیتی ساید افکت داره و نداره و تست نوشتن برای اینا چه فرقی داره. ولی خلاصشو بخوام بگم اگر شما یه فانکشن خیلی ساده بنویسید که دو تا عدد رو بگیره با هم جمع کنه و خروجی رو برگردونه، تست نوشتن براش خیلی ساده هست ولی حالا اگر به همین فانکشن یه خط اضافه بشه که این دو تا عدد رو بگیره جمع کنه و برگردونه ولی یه پرینت هم بکنه یه چیزی هم توی لاگ کت بیرون بده این میشه ساید افکت این میشه یه فانکشنالیتی دیگه توی اون فانکشن که شما برای اینم باید تست بنویسید، معمولا وقتی pure logic فانکشنالیتون ساید افکت نداشته باشه هم کدتون تمیز تره و هم تست نوشتن براش خیلی کم دردسر تره.
اینجا ممکنه یه کدی بنویسی، یه پول ریکوئستی بزنی، ولی پول ریکوئستت ممکنه مثلا سه چهار روز طول بکشه با مستر مرج بشه. چون آدمهای مختلف میان ریویو میکنن و در اکثر مواقع نظرات خیلی خوبی میدن. چون شما وقتی یه کدی رو مینویسی فقط از دیدگاه خودت نوشتی ولی وقتی چندنفر دیگه میان منتقد کد شما میشن ممکن هست یه سری دیدگاههایی رو به شما بدن که شما اون لحظه نداشتی و داشتی به چیزهای دیگه فکر میکردی باعث میشه کدی که مرج میشه توی مستر خیلی تر و تمیز باشه. اگر لول ساید افکت رو خیلی پایین نگه دارید یونیت تستهای خوبی میتونید بنویسید، البته Integration test و End-to-end test خیلی ربطی به تمیز بودن کد نداره. ولی این خلاصهی چیزی بود که من میتونستم بگم چطور تست بنویسیم. کتاب خاصی یادم نمیاد بذارید eBookهامو نگاه کنم بهتون میگم چیز خاصی خوندم یا نه. من بیشتر یادم میاد در مورد تست مقاله خوندم مثلا power mockito یا mockito رو مجبور شدم داکیومنتشو زیر و رو کنم. ولی اگر کتاب مناسب هم بهم رفرنس دادن یا خودم داشته باشم نگاه میکنم بهتون میگم.
- منظور از ساید افکت اینه که روی ورودیها تغییر ایجاد نشه؟
کنار بحث ساید افکت و اینکه یه فانکشن باید فقط همون کاری که اسمش میگه رو انجام میده، این حرفی که میگی خیلی درسته. و معمولا آبجکتهایی که توی کلاس ساخته میشه (اینجکت میشه یا توسط کلاس دیگه به عنوان ورودی داده میشه) معمولا final هستند همشون، یعنی اکثر ورودیهایی که یه فانکشن داره یه انوتیشن final کنارش نوشته شده که اینا تغییر پذیر نباشن و وسط کار نتونید ورودی رو تغییر بدید که ساید افکت ایجاد بشه. معمولا اکثر مواقع بالای توابع notNull@ وجود داره که بگه خروجی که بهت میدم نال نیست. یعنی توی ران تایم میتونه خیالت راحت باشه و اگر مشکلی باشه من توی کامپایل تایم حل میکنم.
- امکانش هست حقوقتو بگی یا اینکه بگی هزینه زندگیت اونجا چقدر هست؟
خب این سوال واقعا خیلی مرتبط با اندروید و توسعهی نرمافزار نیس و بحث حقوق یه مقدار شخصی هست. اگر یکی دوست داشته باشه منابع آنلاین زیادی هستند که داخلش بتونید متوسط حقوق برنامهنویسا یا هزینهی زندگی رو پیدا کنید. خیلی پیدا کردنش کار سختی نیست. فقط من یه نکته بگم اگر کسی مثلا علاقه داره که بره خارج از ایران کار یا زندگی بکنه. این تصمیم تمام ابعاد زندگیش رو تحت تاثیر قرار میده و تصمیمی نیست که فقط بحث کاری باشه. اصلا بهش به شکل بحث کاری نگاه نکنید.
- اگر ممکنه در مورد بخشهای دیگه هم از لحاظ فنی بگو؟
خب اینو کوتاه میگم، چون اگر قرار باشه همه بحثهای فنی اسپاتیفای رو بگم باید چند روز توضیح بدم. چیزی که من میدونم اینه که درصد خیلی زیادی از بکاند ما با جاوا نوشته شده و از این به بعد هر چیزی هم قرار باشه نوشته بشه با جاوا نوشته میشه. این تصمیم رو سطوح بالا شرکت گرفتند و علتش هزینه نگهداری کد و اینجور چیزاس. به غیر از بخش کوچیکی که با پایتون، سی پلاس پلاس و گو نوشته شده و متناسب با نیازش تصمیم گرفته شده که زبون دیگهای استفاده بشه. به همین دلیل معمولا اندروید انجینیرها رو خیلی تشویق میکنند اگر دوست دارند بکاند یاد بگیرند و بکاند هم بزنن. برای اینکه خیلی کار سختی نیست ماها که جاوا بلدیم، بیایم best practiceهای زبان رو بخونیم، یکی دو تا کورس ببینیم و یکی دو تا کتاب بخونیم تا کد بزنیم. و حتی بعد یه مدت به اصطلاح تاثیر گذار کد بزنیم.
ترجیح میدم بیشتر از این در مورد چیزهای فنی بخشهای دیگه نگم،چون خودمم اطلاع ندارم.
- اونجا چه کتابهایی برای خوندن توصیه میشه؟
از کتابهایی که اینجا روش تاکید میشه کتابهای Martin Fowler هست که اگر اشتباه نکنم یکیش مثلا Enterprise architecture هست، کتاب Effective Java و کتاب Clean Code هم جزء کتابهایی هستند که توی شرکت بهشون زیاد رفرنس داده میشه. چندتا کتاب دیگه هم هست که اسماشون الان در خاطرم نیست.
- شرایط و محیط کار چطوره؟ چه امکاناتی دارید؟
ساعت ورود و خروج به شرکت به اون صورت نداریم. تنها مسالهای که وجود داره بین تیمهای مختلف قرارداد میشه که صبح چه ساعتی stand up meeting داشته باشن.
یکی از خوبیا شرکت اینه خیلی انعطافپذیر هست که از خونه کار کنی یا داخل شرکت کار کنی، البته تا زمانی که ثابت کرده باشی داخل خونه کار کردنتم به شرکت ضرر نمیزنه. در واقع این بصورت کلی مدل کاریمون و رفت و آمدمون هست: ساعت نداریم هر موقع میخوایم میتونیم بریم و بیایم ولی آدمها هم سعی میکنند واقعا متعهد به کار باشند.
بحث امکانات هم مثل شرکتهای خوب هست، مثلا در رابطه با غذا به حساب شرکت میتونی غذا بخوری یا اتاق بازی یا از اینجور چیزا داریم. البته میگم اینا بحثهای فرعی هست و خیلی ربطی به توسعهی نرمافزار نداره.
- شرکت و محیط کار چطور هست؟
دفترمون اخیرا عوض شد اومدیم یه دفتر جدید. شرکت تو استکهلم شعبههای مختلف داشت همشون هم برنامهنویسی نبودند، یه دفتر جدید ساختند ۱۲ طبقه وسط شهر و خیلی خیلی ساختمون تحسین برانگیزی هست. اون دفتر قبلی هم که من از اینجا رفتم توش جا خوردم، این دفتر جدید هم که رفتیم توش قشنگ یه دور دیگه جا خوردیم. خیلی خیلی خوب درآوردند علتش هم اینه که پروداکتیویتی آدمها خیلی براشون مهمه، بینهایت برای این که شما احساس راحتی بکنید هزینه میکنند. هزینههایی که شاید به چشم هم نیاد ولی وقتی میشنوی تعجب میکنی. طبقه ۱۲ کلا کافه تریا هست و خیلی بزرگ. چندتا گیمینگ روم داره، پینگ پونگ، بیلیارد، یخچال پر غذا، اتاق ماساژ، اتاق VR، اتاق کاردستی که لوازم تحریر و خیاطی توش هست برای ساختن مثلا یه چیز فیزیکی، به درد اجایل کوچها میخوره. هر طبقه برای خودش آشپزخونه داره، محیط کار جدا هست، یه چیزی که خیلی به درد میخوره میزایی هست که حالت ایستاده میشند، بغلش ۲ تا دکمه داره میاد بالا و میره پایین. معمولا بعد از اینکه نهار میخورند همه سنگین میشند ۱-۲ ساعت ایستاده کار میکنند و اصلا حالت خواب آلودگی برات پیش نمیاد، به نظرم اینجا هم با هزینه معقول میشه انجام داد و برداشت خیلی خوبی کرد از نیروها. چون نهار که میخوری چایی یا قهوه اونقدر تاثیر نداره ولی وقتی ایستاده کار میکنی قشنگ خون تو بدنت میچرخه و حالت خواب آلودگی تقریبا صفر میشه.
- یه جا کار میکردیم بعد از نهار نیم ساعت خواب اجباری بود تا سر حال شی.
ایده خوبی زده بوده.
پروداکتیویتی براشون خیلی مهم هست معیار کار آدما اون ارزش آفرینی هست که میکنند نه اون ساعت کاری. ساعت کار کلا وجود نداره، ولی محیط کاری که ایجاد میکنند خیلی حس تعلق ایجاد میکنه و آدم خیلی با جون دل تو شرکت کار میکنه، حتی خیلی وقتها اضافه بر زمانی که باید بمونه میمونه چون جای با حالی هست برای کار کردن. مثلا تا ساعت ۷ شب کار میکنی میری یه دست PS میزنی، یه شام بیرون میخوری دوباره یه چیزی به ذهنت میاد میای تو شرکت. این محیط فرهنگی که تو شرکتها ایجاد کردند خیلی قابل تحسین هست و گرنه همه جا آدم با استعداد و پشتکار هست ولی اگر بتونی از این آدما بهره وری بکنی هنر مدیریتی هست که اونور وجود داره.
همه شرکتها اینجوریند؟
اسپاتیفای بخاطر کارهایی که میکنه خیلی تو چشم هست ولی شرکتهای دیگه هم کم و بیش اینجوری هستند. شاید زورشون نرسه دفتر به اون تجهیزات بخرند ولی مثلا هفتهای یه بار بریم بیرون شام مهمون شرکت. یا مثلا ماهی یه بار کل تیم بره اسکی رو یخ. یه شب هتل میگیرن کل تیم رو میبرند مهمونی و بزن برقص. سعی میکنند از آدمها استفاده حداکثری بکنند این چیزیه که اینجا هم انجام دادنش یه آدم خلاق میخواد.
- چه اپهایی دارید؟
بطور کلی اسپاتیفای ۶ تا اپ مختلف داره که از این ۶ تا ۴ تاش اپ اصلی اسپاتیفای هست. یه مفهوم جالبتری که توی اسپاتیفای وجود داره وقتی شما کاربر رایگان اسپاتیفای هستید از یه اپ استفاده میکنید و وقتی پریمیموم میشید از یه اپ دیگه استفاده میکنید. البته به چشم یوزر این چیز متفاوتی نیست همه چیز داخل یه اپ هست ولی داخل اپ دو تا پروژهی مختلف وجود داره که شما وقتی پرمیموم میشید بین این دو تا سوییچ میشید. و اتفاق جالبیه، مراحل اینکه از یه پروژه میرید به یه پروژه، داخل کد بیس بامزه هست. ممکنه یه سری از این اپهارو دیده باشید. مثلا یه اپ دیگه داریم به اسم اسپاتیفای زیرو که برای کشورهایی هست که یه مقدار سرعت اینترنتشون پایینه یا گوشیهای ضعیفتری دارند مثل هند پاکستان و یه سری کشورهای آفریقایی، یه اپ دولوپ شده فقط برای اون کشورها که خیلی resource efficient هست، مدل برنامهنویسیش فرق داره و ابزارهایی که استفاده میکنند فرق داره. درکل یه سری اپهای دیگه هم هست.
- چه job title داری؟
- Software engineer
- چه جاب تایتلهای مختلفی دارید؟
برمیگرده به فرهنگ شرکتها، تو شرکت ما اگر engineer باشی همه Software engineer هستند هیچ فرقی بین lead, senior و … نیست. یه فریمورکی هست نه به معنای برنامهنویسی یه فریمورک هست که رو کاغذه، متناسب با تاثیرگذاریت تو شرکت یه step فارغ از این که چند سال تجربه داشته باشی، قبلا چه کارایی کردی بهت اساین میشه. وارد شرکت که میشی استپت همیشه یک هست، با استپ یک وارد میشی بعد از ۶ ماه دوباره چک میشه. استپ یک یعنی کسی که میتونه کارهای خودش رو هندل کنه و گیر نمیافته. استپ ۲ یعنی کسی که به اسکواد خودش داره کمک میکنه و ارزش آفرینی میکنه. استپ ۳ یعنی کسی که در لول ترایب داره کار میکنه. استپ ۴ یعنی برای کمپانی داره ارزش آفرینی میکنه، که استپ ۴ ما در کل شرکت ۲ یا ۳ تا داریم. یه انجینیر داریم خیلی قدیمیه حدود ۶۰ سالشه و فکر کنم یکی از کانتریبیوترهای اصلی rx java هم هست اون استپ ۳ هست. مفهوم سنیور و جونیور نداریم خیلی راحت میتونی با همه صحبت کنی و نظر همه رو به چالش بکشی.
- ایرانی دیگه هم هست؟
آره تو استکهلم ۳ نفر تو آمریکا هم هستند ولی همشون کسایی بودند که برای درس رفتند و بعد ویزای کار گرفتند.
- مدرک تاثیر داره؟
مدرک تحصیلی تاثیر نداره البته نه که نداشته باشه مثلا اگر علوم انسانی خونده باشی ممکنه یه مقدار به چالش بکشند ببینند چی بلدی، ولی مثلا برای گوگل خیلی مهم هست.
- چند سال سابقه برنامه نویسی داری؟
از ۸۸ برنامه نویسی حرفهای کار میکردم از ۹۱ اندروید. اندروید دولوپر شدنم سر استارت اپ ویکند بود. قبل از اندروید هم اپ Symbian میزدم.
- زندگی چطور هست؟
استکهلم یه مقدار زندگی کردن توش سخته یا باید با سرما و تاریکی خیلی مشکلی نداشته باشی یا اینکه اذیت میشی. جای خیلی قشنگی هست ولی چالشهای خودش رو داره مثلا خورشید ساعت ۸:۳۰ صبح طلوع میکنه ساعت ۳ هم غروب میکنه. ما مشکلی نداشتیم پوست کلفت بودیم ولی بعضیها نمیتونند تحمل کنند. هفته اول پاییز قشنگ احساس میکردیم. یهو هم روز کوتاه میشه هم ساعت هارو یه ساعت میکشند جلو، آخر هفته هم بود مونده بودیم خونه ۴ عصر هم خورشید غروب کرد تا شب بال بال میزدیم. معمولا آخر هفته حتما باید یه برنامه بچینی، تو خونه بمونی دپرس میشی.
از اونور هم تو تابستون روز خیلی طولانیه، تا ساعت ۱۱:۳۰ شب آسمون روشن هست و ساعت ۳ هم دوباره خورشید طلوع میکنه، ۵ ساعت کلا شبه.
- اون بازیای که گفتی رو میتونی توضیح بدی؟
بازی هدفش این بود که زیاد کار کردن رو در برابر درست کار کردن نشون بده. آدمها تقسیم شدند به تیمها مختلف ۳ یا ۴ نفره. به هر تیم ۱۰۰ تا توپ پینگ پنگ دادن تیمی که میتونست بیشترین تعداد توپ رو بزاره تو ظرف برنده میشد. منتهی یه سری قانون داشت مثلا یه توپ باید بین تمام اعضای تیم به گردش در بیاد بعد بره تو سبد، یک نفر در لحظه بیشتر از یه توپ نمیتونه برداره، توپها با قاشق باید برداشته میشد و …. شما میتونستید خیلی سریع کار کنید یا باهوش کار کنید و یه فرمولی پیدا کنید که از بقیه تیمها سریعتر توپها رو بزارید تو ظرف. در واقع خلاقیت آدمها رو به چالش میکشیدند. تیمی هم که برنده میشد راه حلش رو به اشتراک میذاشت. مهم این بود که به آدمها بفهمونند با سریعتر کار کردن یا استرس ممکنه به نتیجه نرسی، اگر قبلش فکر کنید ممکنه بهتر به نتیجه برسید. یه سری بازی اینطوری بود که هزینش فقط خوندن یه کتاب اجایل کوچ و ۴۰۰ تا توپ پینگ پنگ بود.
اونجا این شکلیه که یه بخشی از فرایند آنبردینگ با اجایل کوچ جلسه داری و از دیدگاههای مختلف آموزش میدن، از دیدگاه فنی، از دیدگاه اجایل کوچ، از دیدگاه تیملید، از جنبههای مختف سعی میکنند آدم رو جا بندازن و بگند چه انتظاری از جنبههای مختلف از فرد میره. یکی از کارهای مهمی که اجایل کوچها انجام میدند بررسی سلامت تیم از نگاه تیم بودن هست مثلا اگر بعد از مدتی بچهها صبحها جلسه رو نمیان یا جلسه به جای ۱۰ دقیقه ۴۵ دقیقه طول میکشه اینا coordination انجام میدن، آدمها رو سر جای خودشون نگه میدارن جوری که استفاده حداکثری ازشون بشه. مثلا تو رترواسپکتیو چک میکنند به کارهای اسپرینت رسیدیم یا نه؟ یا در مجموع تو ۲ هفته گذشته خوشحال بودید یا نه؟ راضی بودید از کار کردن یا نه؟ یا میگند دو هفته گذشته خودتون رو در قالب یه حیون بکشید، مثلا لاک پشت ۲ هفته گذشته خیلی کند بودیم؛ خرچنگ انگار چندتا دست داشتم و کلی کار مختلف میکردم. یه جورایی با خلاقیت کمک میکنند محیط کار رو بهتر بکنند چطوری میتونیم بهتر کار بکنیم چه عاملایی حذف و اضافه شه اجایل کوچها بخش عمدهای از کارشون کوردینیشن آدمهاست.
- چه ابزارهایی استفاده میکنید؟
تمام شرکت رو slack هست تیمای مختلف کانال مختلف دارن خیلی کم از stack overflow و … استفاده میکنیم چون سعی میکنیم با هم صحبت کنیم، تیمها کانالای مختلف دارند مثلا rxJava unit test Android و … کانال مخصوص خودش رو داره و اکثر سوالها اون تو پرسیده میشه. ارتباط اصلی شرکت معمولا رو ایمیل هست. شرکت یه اپ پرایویت فیسبوک رو خریده https://spotify.facebook.com سوشال نتورک شرکت هست مثلا بخوایم یه gif بزاریم یا این جور چیزا. تیم ما از جیرا استفاده میکنند ولی تیمهایی هست که از ترلو و … استفاده میکنند. جیرا هم کلی کاستومایز شده معمولا اجایل کوچها این کار رو میکنند. یه باتی داریم که معمولا pr سامبیت میشه میاد تستهای مختلف روش اجرا میکنه. jenkins نیست، فکر کنم خودشون نوشتند. داکیومنتها رو گوگل درایو هست، Confluence داریم ولی من از گوگل درایو استفاده میکنم. یه معماری مبتنی بر Redux داریم که یه خورده دستکاریش کردن برای جاهایی که Event base هست. کلا قرار نیست بریم رو Kotlin چون تمام ریسورسهایی که میخوایم بیشتر و پختهتر رو جاوا هست. برنامه نویسهای اندروید و بکاند رو هم شیفت میدند که فول استک بشند تا جایی که میتونند، چون مایکرو سرویسها هم رو جاوا هست راحتتره. (من از quarter قبل شروع کردم بکاند بزنم و احتمالا کوارتر بعد بیشتر بکاند میزنم.) در نتیجه کاتلین با قاطعیت رد شد هیچ کس نمیخواست بره سراغش ولی شرکتهایی هستند که رفتند خوشحال هم هستند. Hangouts خیلی زیاد استفاده میشه همه جلسات و ارتباطات با هنگوات هست. گوگل کلندر خیلی زیاد استفاده میشه و خیلی جدی گرفته میشه.
- یه جا گفتی رو کلاودیم دیتا سنتر داریم یا … بیشتر بگو
اسپاتیفای الان یه دونه دیتا سنتر تو لندن داره قبلا بیشتر بود تو اروپا آمریکا و … بعد دیدن هزینه نگهداریش خیلی زیاده و ما زاتا یه شرکت موسیقی هستیم و نمیخوایم به اون سمت بریم و درگیر اون لول از نگهداری بشیم. مثلا تجهیزات سخت افزاری داشته باشیم و رفتیم رو گوگل کلاود و خیلی هم به نفعمون شد. یه دونه تو لندن هست به خاطر یه سری مشکلات با گوگل کلاود که قرار هست اونم تو ۳ ماه آینده کلا خاموشش کنند.
- اونجا که گفتی بعد از اینکه وارد اپ میشی کلا ۲ قسمت میشه رو میشه توضیح بدی
وقتی وارد اپ میشی ۲ تا چیز قبل از لود شدن هر کدی فچ میشه یکی user policy که تا وقتی نیاد شما اون پراگرس بار رو میبینی حتی اگر اطلاعات صفحه هوم اومده باشه یه چیز دیگه داریم به اسم aba که فریم ورک a/b test هست و یه سری configuration میفرسته. مثلا ممکنه قرار باشه ۴ تا تب تو نویگیشن داشته باشی جای ۵ تا، ممکنه اون توی aba باشه ولی به aba معمولا ۰.۷ ثانیه فرصت میدیم اگر از سمت بکند اومد که اومد اگر نیومد با یوزر پالیسی میریم جلو. بسته به این که کدوم یکی برای شما بیاد یه کلاسهایی لود میشه به صورت داینامیک که اون تصمیم میگیره بری تو اپ فعلی یا بری توی اپ قدیمی. برای من خیلی جالب بود که پکیجهایی که داری انتخاب میکنی متناسب با چیزی که ران تایم هست انتخاب بشه، یعنی الان من این پکیج رو لود کنم یا این یکی رو. مثلا وقتی بخوای core برنامه رو راه بندازی که با ndk کامپایل شده و شما فقط باید run کنیش بسته به این که چه پکیجی رو داری چیز متفاوتی برات لود میشه
- حجم اپ چقدر هست؟
فکر کنم ۴۰ مگ یا همچین چیزی ولی برای کشورهایی که نت داغونی دارن یه اپ دیگه نوشته شد به اسم اسپاتیفای تاینی و همه چیزش فرق داره هیچ چیش با اپ ما یکی نیست. کلا ۲ مگ حجم هست. فقط رندر میکنه چون هیچ لاجیکی توش وجود نداره. از لحاظ ظاهری تقریباً مو نمیزنه با اپ فعلی خیلی شبیه ولی یه تیم دیگه نوشته و یه عده آدمند که تخصصشون فقط تو بهینه سازی، کم کردن حجم کد و … هست در این حد که تو apk حتی یه دونه کلاس اضافه نره. من کدشون رو کم دیدم ولی اصلا استانداردهای کارشون فرق داره و یه جور دیگه کد میزنند و من از کاری که میکنند سر در نمیارم.
- اپ خودتون انگار ۱۸ مگه
اپ دیباگمون ۴۰ مگ هست.
این اسپاتیفای تاینی هست. ایمیج میدونم اصلا استفاده نشده از فونت استفاده کردند، انیمیشن نداره حجمش کم شده زمان لود شدن ویوها خیلی اومده پایین و…
- یه اپ اندروید اسپاتیفای هست که آیکونش سبز کمرنگ هست و بلافاصله میگه این یکی رو نصب کن، داستانش چیه؟
یه اتفاق چند سال پیش رخ داده بود که بهش میگند insedence (اتفاق) یکی یه ایمیلی فرستاده بود و ایمیلش یه چیزی شبیه daniel@spotify.com بوده که ceo شرکت هست و گفته بچهها این رو براتون میفرستم تستش کنید. یه لینکی بوده با این لینک عملا کلی از اطلاعات شرکت رو دراورده، من دقیقا نمیدونم چه اتفاقی افتاده ولی مجبور شدند در عرض یه هفته کل پکیج برنامه رو عوض کردند برای اینکه طرف دسترسی نداشته باشه به اونجا. ممکنه key store و پسورد رو در آورده باشه.
- دیتابیستون چیه؟
نمیدونم چون ما از یه apiای استفاده میکنیم که یه تیم دیگه داره maintain میکنه. ولی میدونم هم رو فایل سیستم مینویسیم هم یه دیتابیسی هست که نمیدونم چیه و هم بسته به کاری که بخوای ممکنه رو کلاود بنویسند. تنظیمات ستینگ میدونم مثلا رو کلاود هست. ما با یه سریع انوتیشن میگیم چی میخوایم مثلا این پرامری کی هست و … ولی نمیدونم اون پشت چیه
بعضی تیمها هم هستند که اصلا فیچر ندارند مثلا android infrastructure اون تیم فیچر نداره ریپازیتوری رو داره مینتین میکنه. مثلا یه تیم داریم client build ریلیز کردن با اون تیمه زمان بیلد اگر بره بالا اون تیم گزارش میده که چرا؟ اون تیم بود که گفت باید ماژولارایز کنیم کد بیس رو و اگر نه یه ۲ سال دیگه با همین سرعت بخوایم کد جنریت بکنیم ۲۰ دقیقه باید منتظر باشیم که گریدل دونه دونه سینک کنه.
- چندتا تیم دارید؟
اون ترایبی که ما کار میکنیم ۸ اسکواد مختلفه ولی کلا نمیدونم چندتا تیم داریم از اینا ۴ تاش تو استکهلمند ۴ تا تو گوتنبرگ
- چه جوری آپدیت میدید؟
هر هفته جمعه پوش میکنیم تو استور و هر هفته باید ریلیز کنیم. هر تیمی باید جمعه فیچرهای خودش رو ساین آف کنه، یعنی کدم رو تست کردم OK هست. یه داکیومنتی شیر میشه بین همه، تست میکنن اگر OK بود داکیومنت رو ساین میکنن بعد تیم ریلیز میفهمه همه چی OK هست.
- آخر هفته ریلیز میکنید به باگ بخورید چی؟
یه تیمی داریم که on call هست و همیشه کار میکنه ولی اگر نتونی اپ خودت رو هم تست کنی خیلی اوضاع خرابه دیگه
- مثلا تست میکنی ردیفه ولی ریلیز که میکنی میبینی ۲ درصد کرش داره مثلا Firebase رو آپدیت کردم این به کرش میخوره
این اتفاق نباید رخ بده
- برا شما نباید برای ما میشه : )
- وقتی آپدیت میدید relese note چیه؟ باگ فیکسه یا فیچر هدف داریه
تیمی که داره ریلیز میکنه اصلا براش مهم نیست که شما چی داری ریلیز میکنی متنی هم که زیر آپدیتها هست همش ثابته امیدواریم از این تجربه اسپاتیفای لذت ببرید و … در نتیجه شما باید همواره هر باگی هست فیکس بکنید چون برای هفته بعد میره بالا. ۲ تا ویدیو هم داده بود قبلا که چطور کار میکنند اسپاتیفای کالچر یا همچین چیزی تو vimeo دیده بودم.(https://vimeo.com/85490944) تو اون میگه از نظر اسپاتیفای ریلیز کردن مثل یه قطار هست اگر به این رسیدی، رسیدی اگر نرسیدی باید صبر کنی با قطار بعدی، تو این کوارتر هم قرار هست ریلیز هر ۳ روز یکبار بشه و قرار هست تو ۲۰۱۸ به هر روز ریلیز و هر کامیت قابل ریلیز کردن بشه حتی اگر ریلیز ندیم.
- این سیاست منطقش چیه؟
اول که اونجا مشکل محدودیت حجم اینترنت و … نداریم که به چشم بیاد. ولی از لحاظ کیفی میخوان به اونجا برسن که هرچی میذاری رو ریپازیتوریت انقدر خوب باشه که بشه ریلیز کرد. الان استاندارد شرکت بالاست یعنی هر چیزی بزاری بالا تو یه هفته میتونی مطمئن باشی که میشه ریلیزش کرد ولی میخوان به جایی برسند که هرچی میذاری همون لحظه اگر بره دست ۳۰۰ میلیون کاربر بدون مشکل کار بکنه cd هست دیگه.
- الان چندتا لایه کلی دارید توی کدتون؟ که فولی ماژولند؟
اگه بخوام کلی بگم مثلا صفحه براوز رو کلا یه ماژولش کردیم تو کد بیس اصلی بود کنار بقیه فرگمنتها ولی چون داشتیم از اول مینوشتیمش یه ماژولش کردیم همه فرگمنت لاجیک و تست رفت توش، فیچرها مثلا ماژول شدن، Search, Home, Your Library, Core
- بعد توی اون دوباره خودش ماژولارایز نیست؟
نه پکیج بندی کردی ولی یه ماژول هست دیگه اگر circular dependency به وجود بیاد باید بریم اون یکی رو هم ماژولارایز کنیم. کسی که ماژولارایز میکنه باید دیپندنسی رو هم خودش solve بکنه مگر اینکه بخوای پلیر کل برنامه رو ماژولارایز بکنی که باید یه تیم براش بزاری.
- شده کسی اخراج بشه؟ دلیلش چی بوده؟
تا حالا ندیدیم ولی شاید به خاطر مسائل اخلاقی و اینها کسی اخراج بشه، پروسه استخدام از لحاظ فنی انقدری خوب هست که پیش نیاد.
- پاداش یا جریمه دارید؟
کسی رو تا الان ندیدم جریمه بکنن، محیط و آدمهای شرکتخیلی حرفهایتر از این حرفها هست که جریمه و کسر از حقوق و اینها داشته باشیم، نهایتا کسی ناراضی باشه با شرکت خداحافظی میکنه، پروموشن هم برای Exceeding Expectation هست. یعنی از خواستهها و مسئولیتهات فراتر عمل کنی. یه مقدار روی حقوق هست.
- چه کسی stepها رو تعیین میکنه؟
یه فریمورک هست که مطابق با اون بهت یه درجهی ارشدیت داده میشه و برای اینکه درجه بالاتری بگیری باید یه سری تاثیرات رفتاری و تکنیکی از خودت نشون بدی
- چه third partyهایی استفاده میکنید؟
مطمئن نیستم لیست کاملش چیه، ولی مثلا رتروفیت، okhttp Stetho
- مگه نتورک تو core نبود؟
یه سری چیزهارو داریم دیپریکیت میکنیم، میریم روی okhttp و gRPC
- جالب بود که کد رو تونستی بهمون نشون بدی، تو شرکت مکانیزمی هست از دزدیدن کد جلوگیری کنه؟ مثلا دسترسی بسته شه یا …
اعتماد، اگر بهم اعتماد نداریم دلیلی برای کار باهم وجود نداره! و صد البته یه سری بند و قانون هم تو قرارداد هست.
مطلبی دیگر از این انتشارات
آشنایی با Symfony با ساختن یه وبلاگ به صورت پروژه ای
مطلبی دیگر از این انتشارات
متدولوژی پوچ ، تیم تاثیرگذار
مطلبی دیگر از این انتشارات
جدال با پس زمینهی زرد ، یا چطور رنگ پسزمینهٔ زرد کروم برای ورودیهای autocomplete را از بین ببریم