-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.xml
2424 lines (1631 loc) · 482 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="http://pullrequest.ir/feed.xml" rel="self" type="application/atom+xml" /><link href="http://pullrequest.ir/" rel="alternate" type="text/html" /><updated>2018-12-23T13:55:41+00:00</updated><id>http://pullrequest.ir/feed.xml</id><title type="html">پول ریکوئست</title><subtitle>پول ریکوئست، دست نوشته های فنی فارسی زبان</subtitle><entry><title type="html">داستان کشف تایمزون</title><link href="http://pullrequest.ir/%D8%AA%D8%A7%DB%8C%D9%85-%D8%B2%D9%88%D9%86/" rel="alternate" type="text/html" title="داستان کشف تایمزون" /><published>2018-12-23T00:00:00+00:00</published><updated>2018-12-23T00:00:00+00:00</updated><id>http://pullrequest.ir/%D8%AA%D8%A7%DB%8C%D9%85%E2%80%8C%D8%B2%D9%88%D9%86</id><content type="html" xml:base="http://pullrequest.ir/%D8%AA%D8%A7%DB%8C%D9%85-%D8%B2%D9%88%D9%86/"><p>یک روز سرد پاییزی در ساعت پنج عصر، یک سری جوجه دانشمند بیکار که مشغول یادداشت کردن تغییرات روز و شب بودن به یه نکته عجیب برخوردن. این سوال واسشون پیش اومده بود که چرا تا همین شش ماه پیش ساعت پنج عصر هوا آفتابی بود و خورشید تو آسمون بود، ولی الان خورشید رفته پشت کوه و هوا تاریکه؟</p>
<p>بعد از اینکه این مورد رو با دانشمند بزرگ زمانهشون در میون گذاشتن، دانشمند بزرگ تمام شاگردها رو از اتاقش به بیرون پرت کرد و به دیوار خیره شد. داشت به این فکر میکرد که کشف قبلیش که سعی داشت این مشکل رو حل کنه، چرا کار نمیکنه؟ رفت دفترچه کشفیات خودش رو باز کرد و شروع کرد به خوندن داستان کشف قبلیش که همون کشف Timezone بود:</p>
<blockquote>
<p>طی تماس اسکایپی که با خالهام در برلین داشتهم متوجه شدم اینجا هوا تاریک است و آنجا هنوز هوا تاریک نشده و خورشید در آسمانشان است. منطقی هم هست، کره زمین گرد است و میچرخد و خورشید آن طرفتر ثابت ایستاده. خب اگر این طرف زمین آفتاب وسط آسمان باشد، آن طرف دیگر باید نصفه شب باشد دیگر. ولی آیا منطقی است که تعریف ما از ساعت متفاوت باشد؟ من یک عمر در اینجا به شاگردانم دستور دادهام که ساعت شش صبح بیدار شوند و برای من نان سنگک تازه بخرند، اما اگر با یکی از این کودنها به آنجا برویم ساعت شش هوا مثل سگ تاریک است و هنوز نانواییها باز نکردهاند. نمیشود که هر بار به جایی میرویم ساعت کاریمان به هم بخورد.</p>
</blockquote>
<p>وزن خود را از باسن چپش به باسن راست انداخت و ادامه داد:</p>
<blockquote>
<p>برای حل این موضوع به راهحلی رسیدم که میتواند این مشکل را حل کند. این که آن وسط کره زمین که اسمش گرینویچ است و همیشه ساعت دوازده ظهر هوا روشن و دوازده شب هوا تاریک است را ساعت مبدا کره زمین در نظر بگیریم و ما که اینور با فاصله از مبدا قرار داریم، ساعت روزمرهمان را با یک فاصله ثابت از آن ساعت مبدا در نظر بگیریم. خالهام در آلمان هم همین وضعیت، منتها یک فاصله زمانی متفاوت. اینطوری این کودنها هر قبرستانی که بروند باز هم باید ساعت شش صبح بیدار شوند و بروند نان سنگک تازه بخرند. با کمک خطکش و یک کره زمین پلاستیکی و یک ساعت مچی، اکنون به دستاورد بزرگی رسیدهام. لیستی که فاصلهزمانی یا همان تایمزون کشورهای مختلف کره زمین در آن محاسبه شده و باعث میشود همه جای دنیا ساعت شش صبح نانواییها باز باشند. حال این لیست را به یکی از این کودنها میدهم تا در اینترنت آپلود کند و لینک آن را به اشتراک بذارد:
<a href="https://www.timeanddate.com/time/map">https://www.timeanddate.com/time/map</a></p>
</blockquote>
<p>کمی خود را خواراند و دوباره به فکر فرو رفت. چه میشود اگر ما هر شش ماه یکبار بیاییم ساعت را بکشیم جلو تا دوباره ساعت نانواییها به هم نخورد و دوباره بعد از شش ماه بکشانیمش سر جایش؟ فکر خیلی خوبی بود. باعث میشد به هم خوردن ساعت کاری نانواییها و ساعت روز و شب در دنیا به حداقل برسه و حتی از اینی که الان هم هست بهتر بشه. بعد یکی از شاگردها رو صدا کرد و بهش گفت یه نامه بنویسه و این قضیه رو توش توضیح بده، بعد بره تو تمام نقاط دنیا پخش کنه. بعد از اون کشف بزرگ، سالها تمام مردم دنیا تا امروز در خوبی و خوشی زندگی کردند.</p>
<p>در سال فلان، درست سال قبل از فوت این دانشمند بزرگ مراسم تجلیلی از او در یکی از تالارهای بزرگ کشور برگزار شد. در مراسم پس از معرفی و تجلیل او یک جلسه پرسش و پاسخ برگزار شد. اون بخاطر کهولت سن سه گوشه نشسته بود و حضار توی سالن سوالهای خودشون رو از شاگردهای استاد میپرسیدن. یکی از حضار پرسید:</p>
<blockquote>
<p>ما به تازگی یک اپلیکیشن خدمات پرداخت موبایلی نوشتهایم و در آن اطلاعات پرداختهای مشتریانمان را سیو میکنیم. این اطلاعات شامل یک سری چیزها به همراه تاریخ و زمان تراکنش آنها است. ما خیلی نکتهسنج بودیم و از ساعت گرینویچ بجای ساعت محلی استفاده کردیم تا مشکل فاصله زمانی نداشته باشیم، اما اگر به پاییز برسیم و ساعتها تکان بخورند، باید ساعتهای قبلی را آپدیت کنیم؟ ما میخواهیم بتوانیم به اطلاعات قبلی اعتماد کنیم…</p>
</blockquote>
<p>دانشمند بزرگ که انگار عرق سرد از پیشانیاش میریخت و رنگش پریده بود، رو به آن شاگردش که نامه عقب جلو کردن ساعت را نوشته بود کرد و با تمام توان یک پسگردنی محکم به او زد. شاگرد که علت را جویا شد توضیح داد:</p>
<blockquote>
<p>پدرسگ من این همه محاسبات کردهام تا به این دستاورد برسم، آنوقت تو به این شکل اشتباه به مردم توضیحش دادهای؟ من کی گفتهام ساعت گرینویچ عقب جلو میشود؟ من گفتم ساعت محلی. یعنی اینکه مثلا آن مثبت سه و نیم که در ایران به ساعت گرینویچ اضافه میشود تا ساعتش بدست بیاید، در بهار بشود مثبت چهار و نیم تا آن قضیه نانوایی حل شود. آنوقت توی گوساله برداشتهای به مردم گفتهای که گرینویچ را جابهجا کنند؟</p>
</blockquote>
<p>شاگرد که سرش رو پائین گرفته بود، از اعماق دلش ابراز پشیمانی کرد و قول داد دیگه این اشتباه رو نکنه. سپس نامه جدیدی نوشت و به کل دنیا و مخصوصا برنامهنویسهای برنامههای خدمات پرداختی این نامه جدید رو ایمیل کرد تا متوجه بشن ساعت عقب جلو نمیشه، فقط فاصله زمانیه که عقب جلو میشه.</p></content><author><name>امیر مومنیان</name></author><category term="timezone" /><category term="tz" /><category term="timestamp" /><category term="تایمزون" /><category term="گرینویچ" /><summary type="html">یک روز سرد پاییزی در ساعت پنج عصر، یک سری جوجه دانشمند بیکار که مشغول یادداشت کردن تغییرات روز و شب بودن به یه نکته عجیب برخوردن. این سوال واسشون پیش اومده بود که چرا تا همین شش ماه پیش ساعت پنج عصر هوا آفتابی بود و خورشید تو آسمون بود، ولی الان خورشید رفته پشت کوه و هوا تاریکه؟</summary></entry><entry><title type="html">گفتههای آرش خانگلدی از اسپاتیفای</title><link href="http://pullrequest.ir/%DA%AF%D9%81%D8%AA%D9%87-%D9%87%D8%A7%DB%8C-%D8%A2%D8%B1%D8%B4-%D8%AE%D8%A7%D9%86%DA%AF%D9%84%D8%AF%DB%8C-%D8%A7%D8%B2-%D8%A7%D8%B3%D9%BE%D8%A7%D8%AA%DB%8C%D9%81%D8%A7%DB%8C/" rel="alternate" type="text/html" title="گفتههای آرش خانگلدی از اسپاتیفای" /><published>2018-12-21T00:00:00+00:00</published><updated>2018-12-21T00:00:00+00:00</updated><id>http://pullrequest.ir/%DA%AF%D9%81%D8%AA%D9%87%E2%80%8C%D9%87%D8%A7%DB%8C%20%D8%A2%D8%B1%D8%B4%20%D8%AE%D8%A7%D9%86%DA%AF%D9%84%D8%AF%DB%8C%20%D8%A7%D8%B2%20%D8%A7%D8%B3%D9%BE%D8%A7%D8%AA%DB%8C%D9%81%D8%A7%DB%8C</id><content type="html" xml:base="http://pullrequest.ir/%DA%AF%D9%81%D8%AA%D9%87-%D9%87%D8%A7%DB%8C-%D8%A2%D8%B1%D8%B4-%D8%AE%D8%A7%D9%86%DA%AF%D9%84%D8%AF%DB%8C-%D8%A7%D8%B2-%D8%A7%D8%B3%D9%BE%D8%A7%D8%AA%DB%8C%D9%81%D8%A7%DB%8C/"><p>خوندن صحبت کسایی که توی شرکتهای بزرگ دنیا کار کردند به ما کمک میکنه که بدونیم ساز و کار این شرکتها چطوریه، بر اساس چه اصولی مدیریت میشن و پروژههاشون رو چطوری جلو میبرند.
از اینجور مصاحبهها تو اینترنت پیدا میشه ولی این یکی فرق داره؛ چون صحبتهای یه ایرانی هست که مدتها تو ایران بوده و علاوه بر موارد بالا، در مورد نحوهی مهاجرت و تفاوتهای اونجا با ایران هم صحبت کرده.
پیشنهاد میکنم صحبتهای آرش رو که خیلی با دقت گفته شده و جزئیات زیادی از شرکت اسپاتیفای داره رو بخونید.</p>
<h2 id="پیشگفتار">پیشگفتار</h2>
<p>این صحبتها در ۲ جلسه به صورت video conference و یک جلسه حضوری از پاییز ۹۶ تا بهار ۹۷ انجام شده و بعدها قسمتهایی برای انسجام مطلب جابهجا شده یا بهش اضافه شده. امیدواریم براتون مفید باشه.<br />
همینطور تا امروز آرش برامون ۲ جلسه در مورد <a href="https://www.youtube.com/playlist?list=PLT2xIm2X7W7jh6KggjhwTH9s_8XIlSdOs">SOLID</a> و <a href="https://www.youtube.com/playlist?list=PLT2xIm2X7W7jp1OZ_1wVrxeEb-9KHpPDV">Test</a> ارائه داشته که میتونید ببینید و پیشنهاد میدم چنل <a href="https://www.youtube.com/c/irlogcat">YouTube</a> یا <a href="https://www.aparat.com/logcat">آپارات</a> یا <a href="https://t.me/irlogcat">تلگرام</a> ما رو دنبال کنید تا از ارائههای بعدیش هم با خبر شید.</p>
<h2 id="معرفی">معرفی</h2>
<p>سلام<br />
برای اونایی که منو نمیشناسن یه معرفی کوچیک کنم.<br />
من آرشم، از سال ۹۱-۹۲ اندروید کار میکنم. قبل از این تاریخ توی شرکتی به عنوان وب دولوپر کار میکردم. تازه اندروید اومد بود، یه خورده جذبش شدم و sdk رو دانلود کردم، با Eclipse شروع به کار کردم. یه اپ برای شرکت نوشتم و بعد دورهی اول استارتاپ ویکند رو شرکت کردم. بعد اون یه جورایی به سمت اندروید کشیده شدم. اندروید دولوپر خیلی کم بود، یه سری پروژه سمتم اومد و انجام دادم. کارایی که انجام دادم و معروف بودن بیسفون و نواک بودند. این دو تا پروژههایی بود که حداقل یکی دو سال داخلشون بودم. چندتا پروژه کوچیک و بزرگ دیگه هم در مجموع انجام دادم.</p>
<p><img src="https://i.ibb.co/BPwTHvG/photo-2018-12-21-16-38-10.jpg" alt="" /></p>
<p>از ۵ ماه و خوردهای پیش با نقش Android engineer اومدم اسپاتیفای. اینجا کلا senior یا junior خیلی معنی نداره، متناسب با contribution که به سورس کد میکنی و متناسب با مسئولیتهایی که به عهده میگیری حقوقت بالاتر و پایینتر میاد. کسی senior نیست و مفهوم جالبی هم هست. خیلی از این موضوع خوشم اومد. چون با این بحث در ایران که کی senior یا junior هست موافق نبودم. از نظر خودم ما ها هممون تا آخر عمرمون چیز برای یادگیری داریم و خیلی دوست نداشتم بگم من این عنوان رو دارم یا ندارم.</p>
<h4 id="بیشتر-توضیح-میدی-چطور-حقوق-مشخص-میشه">بیشتر توضیح میدی چطور حقوق مشخص میشه؟</h4>
<p>بعدا بیشتر توضیح میدم ولی مثلا بستگی به این داره که روی یه سورس کد contribute کنی یا چند تا، بیشتر بخوام توضیح بدم ما تیمی داریم به اسم core، تیم core با ++c یه سری فیچرهای core اسپاتیفای رو میزنن که توی همه اپهای وب، ios، اندروید و ماشین مشترک هست. اینا هر روز صبح باید شبیه تیمهای دیگه feature release بدن و بگن این کد امروز ما هست. هر موقع core آپدیت میشد، ما هم باید gradle رو آپدیت میکردیم. آپدیت گریدل ۲۰ دقیقه طول میکشید و همه شرکت باید منتظر میموند. اومدن اپ رو modularize کردن و الان اپ اندروید ماژولهای مختلفی داره. اینکه شما توی چند ماژول contribute کنی به عنوان یه اندروید engineer یا حتی بکاند یاد بگیری و به بکاند دولوپرها کمک کنی، پروژهی خودتو بکاندشو بزنی، Machine Learning یاد بگیری یا Data Science و … متناسب با این مشخص میشه تو چه stepای هستی. step یه مقیاسی توی شرکت اسپاتیفای هست که مشخص میکنه آیا فقط تنها به خودت و پروژهی خودت کمک میکنی؟ آیا داری به کل تیمت کمک میکنی (Squad)؟ آیا داری به اعضای چندتا تیمی که با هم به دنبال یک هدف مشترکید کمک میکنی (Tribe)؟ آیا داری به کل شرکت کمک میکنی؟ متناسب با این مشخص میشه stepت چیه، حقوقت متناسب با اون شکل میگیره و به قولی اون درجهی سنیوریتی اونجا مشخص میشه. منتها هرچقدر step بره بالاتر مسئولیتهات بیشتر میشه و طبیعتا باید تجربهی این کار رو هم داشته باشی. اگر میخوای یه step بری بالاتر باید خودتو واقعا ثابت کرده باشی.</p>
<h4 id="رفتن-به-اسپاتیفای">رفتن به اسپاتیفای</h4>
<p>سعی میکنم خلاصه بگم که چی شد اومدم اسپاتیفای.<br />
نواک یه اپ music streaming هست و کاری که میکنه خیلی خیلی شبیه اسپاتیفای هست. در واقع خیلی جاها ما از اسپاتیفای الهام میگرفتیم، چون اسپاتیفای واقعا جزء شرکتهای پیشرو توی این زمینه هست. منم اونجا اندروید انجینیر بودم.<br />
یکی از Recruiterهای اسپاتیفای با من تماس گرفت و گفت اگر دوست داشته باشی میتونیم با هم کار کنیم. منم با خانومم صحبت کردم و گفتم که همچین موقعیتی هست. ما تو فکرمون بود که از ایران بریم ولی جای خاصی توی ذهنمون نبود، بیشتر بصورت ایده و کلی بود.<br />
۴ مرحله مختلف ازم تست گرفتند. ۳ تاش تو ایران و ریموت بود. و آخریش که خیلی طولانی بود دعوتم کردن دفتر مرکزی در استکهلم، on-site interview که باید بری توی دفتر و اونجا باهات صحبت میکنن. از تستها اونایی که توی ایران بود کاملا فنی و کد نویسی بود.</p>
<p>اولیش یه تست چهار جوابی خیلی سریع بود. اگر اشتباه نکنم چیزی نزدیک به بیست سوال رو باید خیلی سریع جواب میدادی، اینقدر سریع که فرصت نمیکردی آنلاین چیزی رو چک کنی، یا باید ولش میکردی و جواب نمیدادی یا غلط جواب میدادی که بدتر بود. هر مرحله بهت ایمیل میزنن که توی این مرحله قبول شدی یا نه.</p>
<p>مرحله بعدی یکی از انجینیرهای اسپاتیفای یه سری سوال فنی ازم پرسید. مثلا در مورد بیس اندروید، چقدر با اکتیویتیها آشنایی؟ چقدر با کامپوننتها آشنایی؟ از چه ابزارهایی استفاده میکنی؟ تو RXJava این رو استفاده کردی؟ تو Dagger اونو استفاده کردی؟ مثلا این رو میدونی چطور باید تنظیم کنی؟ از اینجور بحثها، از چیزای خیلی ابتدایی اندروید شروع کرد رفت بالا تا ببینه چقدر میتونم جواب بدم.<br />
نیم ساعتی به سوال جواب گذشت، بعد گفت یه کد بنویس. آنلاین باید همونجا اسکرینم رو share میکردم و کد مینوشتم. اگه اشتباه نکنم تو یه ساعت میخواست یه اپ خیلی ساده مثل Run Keeper بنویسم که قدمها رو میشماره و حساب میکنه چند دقیقه دوییدید. فقط تفاوتش این بود که ui مهم نبود، مهم این بود که pure چه جور logic مینویسم، و اینکه باید از Thread استفاده میکردم، میخواستند ببینند ipc بلدم؟ بین تردها میتونم دیتا جابهجا کنم؟ که یا باید از RXJava استفاده میکردم یا EventBus و این جور چیزها.<br />
بعد از این مرحله هم یه google doc با من share کرد و گفت ما تو این داک یه کدی نوشتیم هرچقدر میتونی ازش اشتباه بگیر. یعنی اشتباه داره اشتباهاش رو مشخص کن. که از اشتباههای syntax و تایپی، کامنت داشتن-نداشتن، اشتباه Architecture، Unit Test داشتن-نداشتن، اینکه چیزی مثلا NullPointerException تو runtime بگیرم-نگیرم، از هرچیزی که میتونستم باید ایراد میگرفتم.</p>
<p>مرحله بعدی باز با یه اندروید انجینیر دیگه جلسه داشتم و یه نفر دیگه که نمیدونم برنامه نویس اندروید بود یا نه، اونم تست برنامه نویسی بود. بیشتر میخواستند ببینند تو بازه کوتاه چقدر سریع و با دقت میتونم کد بزنم. یا اگر بهم وقت بدن چقدر میتونم تمیز کد بزنم.</p>
<p>وقتی هم از این مرحله قبول شدم گفتند باید بیای اینجا.<br />
وقتی اومدم سوئد یک روز کلا از صبح تا شب فقط مصاحبه بود، تو ۴ تا مصاحبه تقسیم شد. ۲ ساعت اول با ۲ تا از مدیرهای ۲ تا تیم جلسه گذاشتیم برای این که کاندید بودم به یکی از اون ۲ تا تیم اضافه بشم، در واقع مصاحبه فرهنگی بود. اسمش Cultrual Interview بود، خیلی سوالهای کلی میپرسیدند. ربطی به برنامه نویسی نداشت مثلا چه جوری خودت رو از لحاظ تکنولوژی آپدیت نگه میداری؟ چه بلاگهایی میخونی؟ اگر تو محیط کار این مشکل پیش بیاد چطور حلش میکنی؟ اگه این کار اورژانسی پیش بیاد چکار میکنی؟ اگه وقت نباشه ریفکتور کنی ولی فیچرو لازم داشته باشیم چه جور سعی میکنی هم کد رو تمیز نگه داری هم فیچر رو به موقع برسونی؟ از لحاظ شخصیتی چطور آدمی هستی؟<br />
بعد یه مصاحبه داشتم با ۲ تا انجینیر اندروید. بهم گفته بودند یه کدی بنویس بیار و هرچی دوست داری استفاده کن؛ هم architectureای که دوست داری هم ابزارهایی که دوست داری. من یه اپ ساده نوشته بودم و باید از کدم دفاع میکردم. تا جایی که میتونستم باید تمیز مینوشتم، دست خودم بود که چقدر وقت بزارم و تمیز بنویسم. باید دفاع میکردم چرا وقتی که با Lint چک بیلد میگیریم این warningها رو درست نکردم؟ یا مثلا چرا این قسمت تست code coverage خوب نبوده؟ یا چرا این logic رو تست نداره؟ باید دفاع میکردم. بعضی چیزهاشم نمیدونستم که باید این کار رو میکردم. همونجا هم یه چیزایی رو گفتند که باید اضافه میکردم و دوباره شروع کردم کد نوشتن.<br />
یه قسمتی از تست دوباره فرهنگی بود با دو سه نفر از اعضای تیمها نهار خوردیم که فقط ببینند من چه جور آدمی هستم، میتونیم با هم تو یه تیم باشیم یا نه.<br />
آخرین تست بهش میگفتند Problem Solving (حل مساله) که کاملا الگوریتمی بود. یه تخت سیاه دادن دستمون، یه مسئلهای گفتند و باید با pseudocode (شبهکد) حلش میکردم و مرتبه زمانی الگوریتمش رو حساب میکردم. مسئله رو یادم نمیاد چی بود. اون قسمتش برای من چالش برانگیزترینش بود چون تو ایران خیلی شبهکد نمینویسیم و مرتبه زمانی الگوریتم حساب نمیکنیم. البته بهم گفته بودند که همچین تستی ازت میگیریم و من مجبور شده بودم یه دورهی یادآوری از طراحی الگوریتم و دیتا استراکچر بگذرونم که یادم بیاد چیبهچی بود. عملکرد خیلی خوبی نداشتم تو اون تست چون بر خلاف اینجا تو ایران الگوریتم به عنوان چیزی که باید روش مسلط باشی خیلی مطرح نبود.</p>
<p>آخر هم بهم ایمیل زدن که قبول شدی و کی میتونی بیای و مراحل اومدن رو شروع کردم. تو نواک هم کار دستم خیلی زیاد بود همه رو تحویل دادم. کمکم آماده شدم اومدم اینجا.</p>
<h4 id="ورود-به-اسپاتیفای">ورود به اسپاتیفای</h4>
<p>وقتی رسیدم تو ۳ مرحله من رو OnBoard کردند. Onboarding فرایندی هست که وقتی شما وارد شرکت بشید شروع میشه برای اینکه یاد بگیری چه جوری با شرکت کار بکنی و فرآیندهای خاص شرکت رو یاد بگیری. برای همه ۳ مرحله Onboarding انجام میشه. مجموعا چیزی حدود ۲ هفته من تحت آموزش بودم؛ همش یه جا نبود تو زمانهای مختلف بود. تو اون ۲ هفته من یک خط کد هم نمینوشتم چون داشتم یاد میگرفتم.</p>
<p><img src="https://i.ibb.co/MDfzLzT/photo-2018-12-21-16-22-54.jpg" alt="" /></p>
<p>تو مرحله اول یاد گرفتم اسپاتیفای به صورت کلی ساختارش چه جوریه؟ رییس کیه؟ به کی گزارش میدی؟ تیمها چه جوری شکل میگیرن؟ چه جوری دلویر میکنی محصولی که باید دلویر کنی؟ استک کلی پروژه چه جوریه؟ آیا ما رو کلاودیم؟ آیا ما خودمون دیتا سنتر داریم؟ اندروید پروژه کی شروع شد؟ از اینجور چیزا شروع میکنند و بعد بیشتر توضیح میدند. مثلا ما از چه متودولوژیهایی استفاده میکنیم؟ چه جوری اجایل رو مدیریت میکنیم که ازش نتیجه بگیریم؟ مثلا در قالب یه سری بازی فکری این که چطور اجایل کار میکنند رو به ما یاد میدند، که خیلی جالب بود ایدههاش و اصلا هزینه هم نداشت، صفر بود عملا، فقط لازم بود یه نفر اجایل رو خوب بشناسه.</p>
<p>بعد Mobile Onboarding بود که مخصوص موبایل انجینیرها هست. طبیعتا بکاند آنبوردینگ، دیتا آنبوردینگ، و از اینجور چیزها هم دارند. تو موبایل آنبوردینگ مثلا اینکه چه جور از اندروید استادیو استفاده میکنیم یا از چیز دیگه، gradle رو چه جور بیلد میکنیم، مثلا اگه بخوای یه A/B test بنویسی پلتفورمش چیه؟ اگه بخوای کدت رو Modulraize بکنی پلتفورمش چیه؟ اگه بخوای یه کامپوننت جدید تو اسپاتیفای رجیستر کنی چطوره؟ یه فیچر کلا جدید بخوای بنویسی چه جوری باید این کار رو بکنی؟ کجا باید رجیسترش کنی؟ چه جوری میتونی تیمت رو رجیستر کنی به عنوان owner این کد؟ و BestPracticeهای شرکت.</p>
<p>آخرین مرحله آنبوردینگ IntroDays که کاملا اطلاعات سطح مدیریتی اسپاتیفای بود. مثلا چه جوری پول در میاره؟ چه جوری تبلیغات میکنه؟ چه جوری با هنرمندا قرارداد میبنده؟ یا چه اطلاعاتی میتونید پابلیک بگید چیارو نمیتونید بگید؟ یا اگر نمیدونید چی رو نمیتونید بگید از فلان کس بپرسید. IT چیکار میکنه تو شرکت؟ HR چیکار میکنه؟ اطلاعات کلی شرکت بود.<br />
خیلی خیلی آدم زیاد هست تو شرکت و اوایلش گیج میشدم، وقتی یه مشکلی پیش میاد باید چیکار کنم؟ از کی بپرسم؟ یه چیز خیلی خوبی که داشت یک آدمی Assign میشه به تازه واردها به اسم buddy (همون رفیق)؛ کسی هست که role شما رو داره، اونم اندروید انجینیر هست ولی سابقه کار طولانی داره؛ مثلا ۳ ساله اندروید انجینیر هست تو شرکت. تو ماه اول قدم به قدم باهاتون میاد هر سوالی داشته باشید میتونید ازش بپرسید. مثلا از کجا آب بخورم؟ تا اینکه شرکت چه جوری پول در میاره؟ من اگه بخوام به این اطلاعات مالی شرکت دسترسی داشته باشم کجا باید برم؟ اگر بخوام کد رو clone کنم کجا باید برم؟ چون روزهای اول حجم اطلاعاتی که میگرید انقدر زیاد هست که آدم گم میشه تو اون اطلاعات. یه خورده طول میکشه بتونه مدیریتش کنه. حداقل برا من اینجوری بود.</p>
<p>چیزی که برام جالب بود شرکتایی که خارج از ایران کار میکنند، برای همه کارمندها یه دوره آزمایشی دارند. با هر رولی که وارد شرکت بشی حتی رول CEO. این دوره از طرف کشور کلا اعمال میشه. تو سوئد قانون هست؛ همه افرادی که استخدام میشند ۶ ماه دوره آزمایشی دارند. تو کشورهای دیگه هم هست یه خورده کمتر بیشتر. مثلا من هنوز تو دوره آزمایشیمم. تو دوره آزمایشی ممکنه شما انقدر خراب کنی که بگند نمیخوایم باهات کار کنیم. یا خودت به این نتیجه برسی که من نمیخوام اینجا بمونم. ولی بعد از دوره آزمایشی قراردادت اتومات بدون اینکه چیزی امضا کنی تبدیل میشه به کارمند فول تایم شرکت.<br />
این نحوه ورود من به شرکت بود.</p>
<h4 id="اطلاعات-مالی-شرکت-کامل-شفافه">اطلاعات مالی شرکت کامل شفافه؟</h4>
<p>بله</p>
<h4 id="حقوق-بقیه-رو-میشه-دید">حقوق بقیه رو میشه دید؟</h4>
<p>تا حالا دنبالش نرفتم ولی خیلی سخت نباید باشه دیدنش. کلا اینجا اطلاعات مالی خیلی شفافه، نه فقط اسپاتیفای، کلا تو سوئد حتی حساب کتابهای دولت هم میتونید چک کنید. چه برسه به یه شرکت چند ۱۰ هزار نفره.</p>
<h4 id="ساختار-تیمها">ساختار تیمها</h4>
<p>بحث بعدی که دربارهی شرکت خیلی جذاب هست، مدل شکل گیری تیمها و structureشون هست. از پایین به بالا توضیح میدم. از مهندس نرمافزار تا CEO.</p>
<p>در لول پایین squad هست، یه تیم متشکل از یه سری آدم که برای هدف مشترک کار میکنند. مثلا من وارد تیمی شدم که کار سرچ انجام میداد. فیچر و پروداکت سرچ دست این تیم بود. (الان تیمم عوض شده) تیم سرچ از من و یه اندروید engineer دیگه، دو تا ios engineer، یه backend developer، یه product owner، یه designer و آدمی به اسم agile coach و کسی که کار chapter lead رو انجام میده تشکیل شده. یعنی این همه آدم فقط داشتن front end سرچ رو مینوشتند.<br />
ما دو تا تیم سرچ داریم. یه تیم به اسم search experience و یه تیم دیگه به اسم search platform. من تو search experience بودم، ما فقط front end بخش سرچ رو انجام میدادیم. مثلا بخش اندروید دست من بود، باید maintenance میکردم. اگر پروداکت منیجر چیزی میخواست باید انجام میدادم. اگر A/B Test یا … بود باید پیاده میکردم. ورژنهای قبلی رو باید maintenance میکردم. چون چندین ورژن از قبل هست که کد بیس و مدل برنامه نویسیش فرق داره و قدیمی بوده. ابزارهایی که توش استفاده شده متفاوت بوده و هنوز لایو هستند، در نتیجه باید maintenanceشون بکنیم. و یه سری کارهای دیگه روزمره.<br />
backend engineer تیم ما از تیم search platform اطلاعات رو میگرفت aggregate میکرد و به front end میداد. برای مثال وقتی یه سرچ توی اسپاتیفای انجام میدید، ۱۰ مرحله اطلاعات توی سرویسهای مختلف جابهجا میشه تا برسه دست کاربر، این ده مرحله تو search platform انجام میشه مثلا خوندن اطلاعات از دیتابیسهای distributed و رتبهبندی کردنشون، ساختن اطلاعات از microserviceها و FlatBuffer و باینری کردن اینها، optimization برای حداقل کردن زمان. ۱۰ سرویس مختلف هست که این اطلاعات سرچ رو میسازه. backend engineer ما اطلاعات این ده سرویس مختلف رو aggregate میکرد و تحویل front end میداد. کار ما از اینجا شروع میشد، اطلاعات رو از backend خودمون میگرفتیم و نمایشش میدادیم و ….</p>
<p><img src="https://i.ibb.co/TMJz2Q3/ING-agile-1.png" alt="" /></p>
<p>تیم ما یه رولی داره (توی اسکوادمون) به اسم به product owner یا product manager، آدم کاملا غیر فنی هست که نحوهی رشد و اداره کردن این product رو بر عهده داره. این آدم تصمیم میگیره که توی product چه اتفاقاتی بیوفته. مثلا این A/B Test اجرا شه که ما ببینیم میتونیم concussion یوزرمون رو ببریم بالا یا نه، ببینیم میتونیم session یوزر رو بیشتر بکنیم یا نه. یا مثلا براساس یه سری اطلاعات که شرکت بدست آورده اگر اطلاعات رو به جای افقی، عمودی نشون بدیم بهتره؛ حالا اینو زمانبندی میکنیم که این feature یه ماه وقت میگیره و اون میشکونتش به taskهای کوچکتر و ما شروع میکنیم روش کار کردن. یا احتمال داره تیمهای دیگه به ما feature request بدن و بگن این feature رو احتیاج داریم، پروداکت منیجر هست تصمیم میگیره ما توان انجامشو داریم یا نه و اینکه چقدر طول میکشه بخوایم انجامش بدیم، آیا لازم هست کسی از تیم دیگه بیاد کمکمون برای پیاده سازی این feature یا نه.<br />
مثلا شرکت تصمیم میگیره تو شش ماه آینده ۱۰۰ میلیون کاربر جدید بگیریم. اینکه چطور این کاربرها گرفته بشه در قالب یه سری اهداف به تیمهای مختلف اعلام میشه. مثلا برای گرفتن ۱۰۰ میلیون کاربر لازم هست که توی بازار فلان کشور وارد بشیم و یوزرهاشو نگه داریم. برای انجام این کار باید فیچر 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 مشخص میکنه.</p>
<p>نقش جالب دیگه که تو همهی تیمها داریم technical owner هست. معمولا قدیمیترین engineer اون تیم و برخلاف product owner کاملا فنی هست، کد مینویسه همه کار میکنه منتها این نقش رو هم برعهده داره. این دو نفر با هم نقشه راه تیم رو در طول زمانهای مختلف مشخص میکنند. مثلا ممکن هست یه فیچر باحال به ذهنمون بیاد یا یکی بهمون پیشنهاد بده یا اصلا CEO بگه اگر این فیچر اضافه شه خیلی خوب میشه. ولی technical owner بگه ما توانایی انجامشو نداریم یا کار ضروری تری داریم. اینجوری نیست که فقط product owner از دید غیر فنی بگه اینکارو بکنیم یا این کارو نکنیم.</p>
<p>تیمهای ما که بهش میگیم Squad معمولا ۱۰ - ۱۲ نفر هستند، یه فیچر دستشونه و باید اونو توسعه بدن یا نگهداری کنند. شرکت چند طبقه هست و به هر طبقه Tribe میگن. ترایب مجموعهای از چندتا squad هست معمولا ۵ - ۶ تا و حدود ۸۰ - ۱۰۰ نفر که برای یه هدف مشخص کار میکنند. برای مثال من توی ترایبی بودم به اسم core experience. این ترایب از ۵ اسکواد مختلف تشکیل شده و کل ux و ui اپ موبایل اسپاتیفای دست ترایب ما هست؛ تقریبا اکثر فیچرهایی که توی اپ میبینید. صفحه home, your library, search, radio, album, artist همه اینارو ترایب ما زده. ما با هم تعامل نسبتا نزدیکی داریم، مثلا تیمی که صفحه artist رو مینویسه ممکنه بیاد از code base شما استفاده کنه یا یه A/B test بخواد ران کنه که سرچ یه تغییراتی بکنه. هر هفته یه جلسهی مشترک داریم. چیزایی که توسعه میدیم رو با هم share میکنیم. اگر چیزی یاد بگیریم داکیومنت میکنیم و به بقیه میدیم.</p>
<p>بعد از level ترایب یه تیمبندی بزرگتری به اسم Alliance داریم، مجموعهای از tribeها هستند که باز یه کار مشترک ولی در سطح بالاتر انجام میدن. مثلا تمام تیمهای فنی اسپاتیفای توی یه alliance قرار میگیرند. مثل تیم موبایل، دسکتاپ، ماشین یا data science. تعداد هم خیلی زیاد هست مثلا alliance ما ۱۵۰۰ نفر هستند. توی alliance معمولا خیلی ارتباط نزدیک معنا نداره. چون بعضی از تیمها اصلا توی یه کشور نیستند. مثلا تیم رادیو توی آمریکا هست و سوئد نیست. ولی خب بفرض من مجبور بودم برای یه A/B test که خودم مینوشتم با یه تیم توی بوستون هماهنگ میشدم که بخاطر محدودیت زمانی که داشتیم کلا دو سه ساعت مشترک میتونیستم کار کنیم. یا اونا بیرون شرکت بودن یا ما. سعی میکنند خیلی مجبور نشید با تیمهای یه کشور دیگه کار کنید چون زمان از دست میدید.</p>
<p>سطح بالای alliance میشه خود شرکت، که مثلا ceo, cto و نقشهای دیگه داخلش هست.</p>
<p>این نحوهی تیمبندی اسپاتیفای هست. سطح اول اسکواد با تیمهای ۱۰-۱۲ نفره، بالای اون ترایب معمولا شامل ۵-۶ اسوکاد، بالای اون alliance با ۷-۸ ترایب مختلف که معمولا تعداد افرادشون خیلی زیاد میشه.</p>
<p><img src="https://i.ibb.co/854KstX/spotifygraphic.png" alt="" /></p>
<h4 id="مدیریت-پروژه">مدیریت پروژه</h4>
<p>توی اسپاتیفای یه داکیومنتی share شده بین همه اعضا و با اون هدف گذاری میکنند. این داکیومنتها رو معمولا مدیرهای رده بالا-C level engineer یا خود CEO میسازند. برای مثال یه مفهومی توی اسپاتیفای وجود داره به اسم north star goal (هدف ستاره قطبی). ستاره قطبی یه مفهوم هست، چیزی که باهاش مسیرمون رو پیدا کنیم. اهداف ستاره قطبی رو CEO میسازه. اینا اهدافی هستند که آینده موسیقی یا صنعت رو قراره شکل بدن. خیلی سطح بالا هستند و ربطی به کارهایی که الان میکنیم نداره و شاید اصلا هیچوقت هم بهش نرسیم. فقط با اون اهداف جهت گیری تیمها مشخص میشه. برای مثال یکی از اهداف اسپاتیفای رسیدن به یک بیلیون کاربر فعال هست. این یک بیلیون کاربر فعال عدد بزرگی هست و طبیعتا طول میکشه بخوایم بهش برسیم. ولی کاربردهایی داره، شما میتونی متناسب با این هدف کار خودت رو بسنجی و بفهمی در راستای این هدف میری جلو یا نه. برای مثال ما میخوایم به یک بیلیون کاربر برسیم و هدف x, y, z. متناسب با این اهداف سالیانه رو میسازیم. مثلا برای رسیدن به یک بیلیون امسال باید ۱۰۰ میلیون کاربر بگیریم. حالا هدف امسال میشه ۱۰۰ میلیون کاربر. بعد اهداف امسال رو میشکونیم به فصلهای مختلف که بهش میگن quarter مثلا q1, q2, q3, q4. مشخص میکنیم تو هر کوارتر برای رسیدن به هدف چیکار میتونیم بکنیم.</p>
<p>با توجه به اهداف مشخص شده با product owner برای یه فصل برنامهریزی میکنیم، بفرض ۴ ۵ ۶ تا اسپرینت میبندیم. توی اسپرینت ۱ به اینا میرسیم توی ۲ اونا رو انجام میدیم و توی ۳ اینا. به همین ترتیب اسپرینتها رو میچینیم. البته دونه دونه، یعنی برای ۴ تا اسپرینت بعدی برنامه ریزی نمیکینم، برای یه اسپرینت بعدی برنامه میریزیم. منتها تو backlog (از jira استفاده میکنیم) تمام تسکهایی که باید توی یه کوارتر بهش برسیم هست. اگر توی این کوارتر بهش رسیدیم که عالی دممون گرم، میریم بیرون شام میخوریم. اگر نرسیدیم یه جلسه میذاریم که چرا نرسیدیم؟ چه مشکلی هست؟ آیا باید آدم بیشتری بگیریم؟ آیا درست برنامه ریزی نکردیم؟<br />
تسکهای جیرا رو به این شکل صفر میکنیم و به اونجا میرسونیم که بگیم به اهداف این کوارتر رسیدیم، ایول حالا بریم کوارتر بعدی. این مدلی ما تسک بندی میکنیم.</p>
<h4 id="یک-بیلیون-کاربر-فعال-رو-درست-گفتی-فکر-کنم-چند-برابر-جمعیت-زمین-هست">یک بیلیون کاربر فعال رو درست گفتی؟ فکر کنم چند برابر جمعیت زمین هست!</h4>
<p>نه درست گفتم! Billion تو فارسی میشه یک میلیارد! :دی</p>
<p>شکل رسیدن اهداف به تیمها، در قالب یه 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ها از تیمهای مختلف جمع میشه تا مشخص شه ما توی کوارتر بعدی یا سال بعد قراره چیکار کنیم تا به این هدف برسیم.</p>
<h2 id="به-key-result-نمره-میدید">به key result نمره میدید؟</h2>
<p>بله</p>
<h4 id="به-اون-تیکه-که-گفتی-قراره-۵-بشه-۷-نمره-میدید">به اون تیکه که گفتی قراره ۵ بشه ۷ نمره میدید؟</h4>
<p>آره درجه اولویت داره و یه سری از بقیه مهمتر هستند. مثلا ما تصمیم میگیریم بریم وارد بازار چین بشیم و شرکت میگه این هدف شماره یک هست. متناسب با اون چند هدف دیگه هم اعلام میشه ولی هدف شماره یک مهمترین هست و برا همه درجه اولویتش بالاست. key result که متناسب با اون هدف یا آبجکتیو اعلام میکنی هم ردهبندی داره و میگی مثلا من برا objective شماره ۱ این key result رو مشخص میکنم برا objective شماره ۲ اینارو و ممکنه به objective شماره ۳ نرسم چون هدف شماره ۳ هست و انقدر هم مهم نیست ولی هدف ۱ و ۲ اولویت بالا داره و باید بهش برسیم.</p>
<h4 id="با-توجه-به-اولویتی-که-داره-ضریب-میدید">با توجه به اولویتی که داره ضریب میدید؟</h4>
<p>تقریبا درصدی میریم جلو و زمان درصدی تقسیم میشه، مثلا تا آخر ۳ هفته بعد باید به objective شماره یک برسیم، بکلاگمون رو نگاه میکنیم، میبینیم این آبجکتیو ۱۰ تا تسک داره که هنوز انجام نشده در نتیجه میایم با برنامه نویسها یا آدمهایی که باید پیادهسازی کنند صحبت میکنیم و میگیم که چقدر زمان میخوای که این رو انجام بدی؟ میگه من این ۱۰ تا تسک رو تو ۲ هفته انجام میدم. برا اون یه هفته باقی مانده برا objective شماره ۲ تصمیم گیری میکنیم، خوب تو این هفته چندتا تسک میتونی انجام بدی؟ میگه مثلا از objective شماره ۲ این ۲ تا رو میتونم انجام بدم. اول باید به objective شماره یک برسی در کنارش باید برای بقیه هم حرکت کنی.</p>
<h4 id="okr-چطور-با-اسکرام-هماهنگ-میکنید">OKR چطور با اسکرام هماهنگ میکنید؟</h4>
<p>OKR اول از C level manager اعلام میشه و به alliance منیجرها ابلاق میشه (تیم بزرگ که همه تیمهای فنی توش بودن، همه HR، همه ریکروتر و … همه اینها برا خودشون alliance دارند. برای ما تیم دسکتاپ، وب، موبایل و … توشند) اینا پروداکتهایی که دستشون هست رو خوب میشناسند، alliance میگه مثلا برای اینکه به ۱۰۰ میلیون کاربر برسیم پروداکت موبایل ۶۰، دسکتاپ ۲۰، اتومبیل ۵ و … میلیون کاربر جدید جذب کنه.<br />
آبجکتیو که تو alliance مشخص شد، alliance منیجر میاد به ترایب منیجر (ترایب همون چندتا اسکواد کنار هم بود و ترایب منیجر مدیر بالا سر همه اسکوادهایی هست که تو این ترایب کار میکنند) میگه شما به عنوان مدیر ارشد بخش موبایل باید تضمین کنی سال بعد ۶۰ میلیون کاربر بگیریم. حالا ترایب منیجر تقسیمبندی میکنه، برای این کار باید این مارکت رو بگیریم، اونکار رو کنیم و …. یا اگر بگن session کاربر افزایش بدیم از ۱ ساعت بکنیم ۱.۵ ساعت، یه تقسیمبندی میکنه میگه تیم home شما باید انقدر افزایش بدید، تیم سرچ انقدر، تیم آرتیست انقدر، میشکونتش به اسکوادهای مختلف و اون موقع هست که به تیم ما به عنوان پایینترین سطح هرم مدیریتی محول میشه. مشخص میشه OKR ما برای ۳ ماه بعد یا سال بعد ۱۵ دقیقه افزایش session کاربر توی جستجو هست. حالا ما به عنوان تیم سرچ این توانایی داریم و تصمیم میگیریم این کار رو بکنیم، اون فیچر اضافه کنیم و به این شکل افزایش میدیم. وقتی همه تیمها sessionشون رو افزایش بدن در نهایت کل اسپاتیفای سشنش از ۱ ساعت میشه یه ساعت و نیم چون هر کدوم از تیمها جدا این کار رو میکنه.</p>
<h4 id="تو-تیمهایی-که-xp-یا-اسکرام-کار-میکنند-بعد-از-تصویب-okr-کجا-نوبت-اسکرام-و-xp-میشه">تو تیمهایی که XP یا اسکرام کار میکنند، بعد از تصویب OKR کجا نوبت اسکرام و XP میشه؟</h4>
<p>این رو product owner تصمیم میگیره، با توجه به چیزایی که بهش اعلام شده و آبجکتیوها و توانایی تیم شروع میکنه و فیچرهای ۳ ماه بعد رو مشخص میکنه. مثلا این A/B Test رو ران کنیم یا … توی backlog جیرا میذاره، متناسب با اون اسپرینت میبنده، زمان بندی میکنه، تسکها محول میکنه و …</p>
<h4 id="تو-xp-که-اکثرا-تسکها-روزانست-و-تایم-کمتر-و-اسپرینت-نداریم-مشکلی-پیش-میاد-از-کجا-بفهمیم-یا-چه-جوری-زمان-بندی-کنیم-که-این-تسکها-تو-اون-۳-ماه-تموم-شه">تو xp که اکثرا تسکها روزانست و تایم کمتر و اسپرینت نداریم مشکلی پیش میاد، از کجا بفهمیم یا چه جوری زمان بندی کنیم که این تسکها تو اون ۳ ماه تموم شه؟</h4>
<p>این یه تعامل هست بین product owner, technical owner و ما برنامه نویسها. product owner میگه من این فیچرو میخوام پیادهسازی کنم نیازمندیش (sub task) میشه این کارا. technical owner آدمیه که چند سال تو اسپاتیفای بوده، هم خودش خیلی سابقه کار داره هم تیم رو خوب میشناسه هم برنامه نویسهارو، میگه با توجه به تجربم به این تسک میتونیم برسیم یا نه.<br />
وقتی sub taskها مشخص شد مثلا با من صحبت میکنند، میگن ما این کارارو میخوایم بکنیم، تو اسپرینت اول باید به اینا برسیم تو اسپرینت دوم به اینا و … آیا میتونیم انجام بدیم؟<br />
من متناسب با برنامه و کارای خودم میگم آره یا نه. ولی ممکنه یه فیچر انقدر مهم باشه که حتی اگر من نتونم انجامش بدم، اسکواد ما مجبور بشه از یه تیم دیگه یک یا دوتا اندروید انجینیر بگیره؛ موقت بگه شما ۳ یا ۴ ماه بیایید توی تیم ما تا این فیچر رو بتونیم پیاده کنیم. این فیچر انقدر برا شرکت مهم باشه که اسکوادهای دیگه حاضر باشند این فداکاری رو بکنند. بگند اندروید انجینیر ما ۲ ماه بره و ما اندروید دولوپ نکنیم ios یا بکاند دولوپ کنیم، چون باید به اون فیچر برسیم. هدفهایی که خیلی مهم هست هرجور شده باید بهش برسیم حتی اگر شده نیرو از جای دیگه بگیریم.</p>
<h4 id="هر-سطح-okr-خودش-رو-داره">هر سطح OKR خودش رو داره؟</h4>
<p>دقیقا هر اسکواد و هر ترایب که میشه مجموعهای از OKR اون اسکوادها و هر alliance میشه مجموعهای از OKR اون ترایبها</p>
<h4 id="اگر-به-این-اهداف-نرسیم-چی">اگر به این اهداف نرسیم چی؟</h4>
<p>یه سری اهداف هرجور شده باید بهش برسیم. کسایی که این اهداف رو مشخص میکنند آدمهای معقول و عاقلی هستند، میدونند آیا ما اصلا بهش میتونیم برسیم یا نه. اگر هدف انقدر بلند پروازانه باشه که نتونی بهش برسی یعنی اون مدیر واقعا کارش رو بلد نبوده که همچین هدفی تعیین کرده. هرکس باید بتونه تو جایگاه خودش درست تصمیم بگیره؛ اون مدیر کارش اینه که بتونه برنامهریزی درست کنه، مدیری که نتونه تخمین درستی از تیمش داشته باشه که بدرد نمیخوره.<br />
ولی نهایتا پیش میاد که به هدفی نرسی، وسط کار زلزله اومد برنامه نویس مرد. در نهایت یه جلساتی برگزار میشه وقتی به یه هدفی نرسی یا برسی، وقتی sprint رو میبندیم یا quarter یا سال تموم شه، جلساتی داریم به اسم retrospective، تمام اعضایی که تو اون هدف شرکت داشتند مثلا تمام اعضای سه اسکواد میشینند با هم retrospective اسپرینت قبلی رو برگزار میکنند. آیا ما به همه اهداف رسیدیم؟ اگه رسیدیم دممون گرم. اگه نرسیدیم چرا نرسیدیم؟ چه نیازمندیای داشتیم؟ اشتباه برنامه ریزی کرده بودیم؟ نیرو کم داشتیم؟ بلد نبودیم این code base رو؟ یا مثلا code base جدید به ما داده شد نمیدونستیم چیه؟ هرچی هست دلیلش باید مشخص شه اصلا مهم نیست کی اشتباه کرده، دنبال قاتل بروسلی نمیگردند و فقط میخوان علتش مشخص شه که دیگه تکرار نشه. اگه اشتباه برنامهریزی کردیم، اگه زیاد رو خودمون حساب کردیم و رو تواناییهامون بیش از حد معقول حساب باز کردیم باید یاد بگیریم دفعه دیگه این کار رو نکنیم. یا مثلا اگر ما تو این اسپیرینت جای ۲۰ تا تسک ۶۰ تا برداشتیم دفعه دیگه نباید این اشتباه رو بکنیم. یا مثلا اگه engineer با این framework خوب آشنا نیست و نمیدونه باید چیکار کنه براش کلاس بزاریم و بقیه انجینیرها بهش یاد بدن چطور کار کنه، یا نیروی جدید بگیریم. یا ۴ تا pr جدید بود و باید review میکردم کارم سنگین بود نرسیدم در نتیجه از اسپرینت بعد با تیمهای دیگه صحبت میکنیم اگر قرار pr بدند از قبل باهامون هماهنگ کنند که تو زمانبندی حسابش کنیم، یا برای اندروید انجینیر ۱ ساعت اضافه در هفته در نظر بگیریم چون باید pr ریویو کنه. هرچی هست علتش مشخص شه و حلش کنیم. تا جایی که بشه سعی میکنیم یا این اتفاق نیوفته یا اگر افتاد بلافاصله یه retrospective برگزار بشه و یاد بگیریم که چی از این قضیه یاد گرفتیم، چی شد که ما این اشتباه رو کردیم و دیگه این اشتباه رو تکرار نکنیم.</p>
<h4 id="گفتی-با-تیم-مارکتینگ-هم-در-ارتباط-هستید-تصور-من-این-بود-که-باید-تو-یه-الاینس-دیگه-باشه">گفتی با تیم مارکتینگ هم در ارتباط هستید؟ تصور من این بود که باید تو یه الاینس دیگه باشه.</h4>
<p>همینطوره که میگی ولی الاینسها باید با هم کار کنن که به اهداف شرکت برسیم! تیم مارکتینگ با ترایب خودش هماهنگ میشه، ترایب ما هم به اونها میگه این کارها لازمه انجام بشه و اونها سعی میکنن انجامش بدن! در واقع Tribe Lead ها باهم توافق میکنن! اینجور تصمیمها تو لایه مدیریتی و بین Product Owner/Tribe Lead اتفاق میوفته.</p>
<p>ما یه سری جلسات بدرد بخور داریم و فکر میکنم برگزار کردنش خیلی راحت هست. برا ماها خیلی میتونه مفید باشه فارغ از اینکه تو چه شرکت و با چه ابعادی کار میکنیم.
ما ۲ تا جلسه داریم که همه افراد تو یه اسپرینت باید توش حضور داشته باشند.</p>
<p>یکیش جلسه برنامهریزی هست که معمولا روز اول اسپرینت هست، چیزی نزدیک ۳ الی ۴ ساعت از زمان اون اسپرینت به برنامه ریزی برای ۲ هفته آینده میگذرونیم. شما لازم نیست تو کل اون جلسه حضور داشته باشید چون ممکنه برای ios، اندروید و بکاند تصمیم بگیریم. تنها افرادی که حتما باید حضور داشته باشند product owner و technical owner هستند، شما میتونی تا آخر بشینی یا فقط بخش مخصوص به خودت رو بری.</p>
<p>جلسه دیگه همون retrospective هست، مخففش میکنیم retro. یه جلسه یک یا ۲ ساعتس که روز آخر اسپرینت برگزار میشه و حتما همه باید حضور داشته باشند، اول تا آخرش. این جلسهای هست که توش اسپرینت قبلی رو بررسی میکنیم؛ به همه تسکها رسیدیم یا نرسیدیم؟ اگه نرسیدیم چرا نرسیدیم؟ معمولا به همه تسکها میرسیم چون سعی میکنیم موقعای که برنامهریزی میکنیم دیدگاهی عاقلانه و منطقی داشته باشیم. رو تواناییهای نداشتمون، یا میرم یاد میگیرم و اینا حساب نمیکنیم، رو چیزی که الان داریم حساب میکنیم. من تا حالا فقط یه اسپرینت بود که تسک انجام نشده داشتم. تازه اومده بودم و از همون اول میدونستیم که احتمالا به یه سری از تسکام نمیرسم. چون تازه داشتم یاد میگرفتم چی به چی بود. بعد از اون تقریبا به همه اسپرینتها میرسیدم.</p>
<p>بلافاصله بعد یه جلسه داریم که بهش میگن demo. باید چیزی که تو این ۲ هفته روش کار کردی رو demo کنی. ممکنه پیور programming باشه و ui هیچ تغییری نداشته باشه، ولی میای demo میکنی مثلا من این رو refactor کردم، جای اینکه از این استفاده کنم از این یکی استفاده میکنم خیلی بهتر شد. یا مثلا unit test coverage رسوندمش به این. تو ui شما هیچی نمیبینی ولی محصولی که دستت هست رو بهبود دادی میای این رو demo میکنی.</p>
<p>جلسات retro planning و demo در سطحهای بالاتر برای کل ترایب و الاینس هم هست ولی لازم نیست شما تو اونا بری، معمولا product owner میره اونجا. مثلا رتروهایی که تو ترایب برگزار میشه میگه تیم سرچ تو ۲ هفته گذشته کار ۱ ۲ ۳ ۴ رو انجام داد. تیم فلان این کار رو کرد و …. این نشون میده که آیا پروژه داره پیشرفت میکنه یا نه؟ آیا جایی گیر کرده یا نه؟ آیا جایی نیاز به کمک داره یا نه؟</p>
<p>یک نقش خیلی جالبی هم داریم اینجا به اسم delivery lead، یکی از مدیرهای نسبتا بالا با سابقه طولانی تو اسپاتیفای که تو هر ترایب هست. این آدم مطمئن میشه آیا تیمهای مختلف با اون OKR که تنظیم شده میرن جلو یا نه؟ ما هر ۲ هفته یک جلسه با این آدم داریم. مثلا از من میپرسه اون تسکی که داشتی روش کار میکردی انجام دادی یا نه؟ (به برد جیرا ما دسترسی داره) خوب انجام دادی عالیه تسک بعدی به موقع بهش مرسی؟ ممکنه من بگم آره میرسم یا بگم تسک بعدی یه هفته بیشتر زمان لازم دارم چون میخوام برم مسافرت این جزو مواقعای هست که ممکنه یه اسپرینت بهم بریزه ولی OK هست. برای اینکه من هم آدم هستم و میخوام برم از زندگیم لذت ببرم. یا ممکنه بهش بگم یه هفته بیشتر زمان لازم دارم چون باید فلان تکنولوژی رو یاد بگیرم باز هم OK هست، چون من دارم برای رسیدن به اون هدف تلاش میکنم. delivery lead کارش این هست که اسکوادهای مختلف به اون آبجکتیوهایی که بهشون اعلام شده و key resultهایی که تعریف کردن برسند. مطمئن شه این اسکوادها سلامت و توانایی لازم برای رسیدن به اونها رو دارن. مثلا آیا لازم هست آدم جدید به این اسکوادها اضافه شه یا نه؟ delivery lead محصولهای که این اسکوادها باید تحویل بدن رو جمع آوری میکنه. دونه به دونه میپرسه این رو انجام دادی؟ هر ۲ هفته تکرار میشه و باهاشون جلسه داره.</p>
<p>یه جلسهای ۱۵ دقیقه توی تیم ما هست که صبح ساعت ۹:۴۵ برگزار میشه همون Stand-up meeting، یه لیستی از موارد رو معمولا بررسی میکنن. یکی اینکه امروز باگی به ما ریپورت شده یا نه و اگر ریپورت شده درجهاش چیه. ما ۵ درجهی اهمیت توی شرکت داریم که بهشون میگن p1 تا p5. اگر باگ p1 به تیم ریپورت بشه، یعنی بخاطر پروژهی شما کدبیس داره کرش میکنه، هرکاری الان دستت داری رو بذار زمین و شروع کن این باگ رو فیکس کن. اگر لازمه یه هفته بمون شرکت این باگ رو درست کن. البته من از وقتی شرکت بودم به پروژهی ما p1 ریپورت نشده ولی با توجه به باگی که بهتون ریپورت شده ممکنه لازم باشه با کسی که ریپورتش کرده صحبت کنی که چیکار کردی کرش کرد، یا یه ورژن جدید براش بسازی که تست بکنه و از اینجور چیزا. البته ممکن هست چند روزی باگ ریپورت نشه.<br />
بعد از اون کارهای روزمرهمون چک میشه مثل TeamCity و اینکه که کی باید چیکار کنه. معمولا کارهارو ریپورت میکنیم که مثلا من فلان کد رو میزنم، بکاند فلان کد رو میزنه، شاید من بگم امروز حتما این اندپوینت بکاند رو لازم دارم اگر میشه اینو زودتر انجام بدید. یه سری هماهنگیهای داخل تیمی هست. و در آخر هم یه سری بحثهای مختلف که یکی مثلا بگه امروز نمیتونم بیام یا فردا کار دارم.</p>
<p><img src="https://i.ibb.co/nfTxVnT/kylie-minogue.jpg" alt="" /></p>
<h4 id="ابزارها">ابزارها</h4>
<p>ما تو اسپاتیفای از git برای سورس کنترل استفاده میکنیم، بطور دقیقتر از github. شرکت یه برنچ enterprise از گیتهاب خریده و وقتی میخواید کدی کامیت کنید یا pull requestها رو چک کنید تو گیتهاب شرکت میبینید.</p>
<p>برای issue tracking و چک کردن تسکها از jira استفاده میکنیم.</p>
<p>از crashlytics برای crash reporting استفاده میکنیم. یکی از منابع دقیق چک کردن تعداد یوزرهای اکتیو هست. برام جالبه که crashlytics استفاده میکنیم نه google analytics.</p>
<p>برای دولوپمنت از Android studio 3 beta 2 استفاده میکنیم، چون چند وقت پیش پروژه بخاطر حجم زیادش شروع کرد به کند و کند شدن. برای هر سری بیلد پروژه اندروید استودیو باید یه apk از پروژه بسازه و ببره روی emulator یا دستگاه deploy کنه تا بتونید تستش کنید؛ وقتی کد پروژه خیلی زیاد بشه، کامپایل کردن و ساختن اون apk طولانی میشه. برای همین کل کامیونیتی اندروید (جاوا بیشتر) اومدن یه راه حلی ارائه دادن که کدبیس رو modularize کنید، یعنی کدتون رو ماژولهای مختلف کامپایل شده کنید و وقتی کد میزنید نیاز نباشه همهی برنامه کامپایل شه تا یه apk ساخته شه. اگر دارید روی کلاس یا ماژول جدا کد میزنید فقط همون ماژول کامپایل میشه و بقیه ماژولها byte codeهای آماده جاوا هست و شما فقط قسمت خودتون رو میذارید کنار اون byte codeها و apk میگیرید. این کار رو بهش میگن modularization که الان یه سری شرکتهای نسبتا بزرگ تا حدی درگیرشن، یا انجامش دادن یا میخوان انجامش بدن. خلاصشو بخوام بگم یه ماژولی که شما میخواید روش کار کنید manifest خودشو داره، کدهای جاوای خودشو داره، اطلاعات ماژول در فایلهای yaml جدا میذارید، همه چی تو ماژول خودتون تعریف میشه، انگار کلا با یه پروژه دیگه کار میکنید. زمان بیلد از وقتی که build clean میکردیم و گریدل همه چیو بیلد میکرد قبلا حدود ۱۰ دقیقه طول میکشید، ولی با این روش حدود ۱۰ ثانیه شده، به شکل خیلی خیلی محسوسی زمان بیلدمون پایین اومده. شرکت چند وقت پیش نفر ساعت حساب کرده بود یه رقم خیلی زیادی رو داشت عملا مینداخت دور، فقط چون منتظر گریدل میشدیم. به همین دلیل ما پروژه modularize رو شروع کردیم. چون اندروید استودیو ۲ روی کدهایی که ماژولارایز هستند خیلی بد و کند هست به مشکل خوردیم. بچههای شرکت یه کانال مستقیم با گوگل داشتند و قبل اینکه اندروید استودیو ۳ ریلیز شه یه سری تستها کردند و دیدن جواب میده و خیلی بهتر میشه. درواقع اندروید استودیو ۳ خیلی بهینه شده برای کدهای ماژولارایز. رفتیم روش و دیدیم خیلی خوب جواب میده و ازش استفاده کردیم. حتی از زمانی که canary (قناری) بود استفاده میکردیم. اما بعضی وقتها پایدار نیست، حتی الان که بتا هست به مشکلایی میخوریم. ممکنه کرش کنه یا اتفاقات عجیب بیوفته. تا الان فقط کد بیس اندروید ۱۵۰ ماژول داره و اگر نمیرفتیم روی ماژولارایز کردن دیگه داستان بود و از همه کارهامون عقب میوفتادیم.</p>
<p>ابزار دیگه TeamCity هست، پروژهای که شرکت JetBrains نوشته و برای مدیریت تستها هست. باهاش میتونید چک کنید امروز چندتا تستمون fail شده، Integration testing فیل شده دارید یا نه، End-to-End Test فیل شده دارید یا نه. مثلا ایمولاتور اومده لاگین کرده رفته توی فلان صفحه و روی یه آهنگ کیلک کرده ولی اون آهنگ پخش نشده. این یه تست خیلی خیلی مهمه که fail شده و شما باید همون روز چکش کنید. ممکنه یکی یه جای دیگهی کد، یه تغییری داده باشه که الان پلیر کار نکنه. تیم پلیر باید بره End-to-End تست رو چک کنه ببینه اشکال از کد ما بوده یا از اونا، براشون یه باگ ریپورت کنه که اینو درستش کنید چون پلیر کار نمیکنه. برای همین هر روز باید داشبورد TeamCity چک بشه.</p>
<h4 id="معماری">معماری</h4>
<p>تو شرکت دو معماری نرمافزار داریم mvp و mvvm. بسته به اینکه چیکار میکنید معمولا یکی از این دو تا استفاده میشه. Flat کلا وجود نداره و اگر شما فلت کار کنید نتیجه میگیرند که کارت رو بلد نیستی و تقریبا باید از شرکت بری. Flat architecture بیمعنی هست و باید پروژه architect بشه و همه سر اون معماری توافق کنند. من کدی که فلت باشه اصلا بهش دست نمیزنم. mvp مزایای خودش رو داره mvvm هم همینطور. برای کدهایی که معمولا ماها میزنیم، مثلا یه بکاند و فرانتاند هست که باید به هم وصل شه و یه اطلاعاتی بخونید و چیزایی تو دیتابیس بریزید از mvp استفاده میکنیم، دلیلشم تست پذیری mvp هست. وقتی برای قسمت رندرینگ بخوایم کدی بنویسیم از معماری mvvm استفاده میکنیم. برای اینکه رندر کردن خیلی راحتتره، درواقع کارهای ui. جدا کردن بخش logic و سپردن interaction به دست observableها و rxjava توی mvvm خیلی راحتتر میشه، برای هابز که کار رندرینگ رو انجام میداد از mvvm استفاده کردیم.</p>
<p>یه بحثی تو معماری mvp هست به اسم multiple presenter. برای مثال بخوام بگم وقتی وارد شرکت شدم، به پروژه سرچ کمک میکردم. وقتی از بیرون به کدبیس بخش سرچ نگاه کنید، یه لایه ویو داره و یه پرزنتر که لاجیک سرچ اونجا انجام میشه و یه مدل و از اینجور داستانها؛ منتها خودش از بخشهای مختلفی تشکیل شده. ما کلا دو تا سرچ اصلی توی اسپاتیفای داریم. یکی دکمهی ذرهبین که میزنید و میری اونجا کاراتون رو میکنید، یکی سرچ قسمت رادیو. بخش رادیو اسپاتیفای هم یه سرچ داره که اون رو هم ما باید مینوشتیم و لاجیکش تا حدی فرق میکرد. وقتی چیزی رو سرچ میکنید و ریسپانس شامل آهنگها آلبومها و … میاد، یه قسمتی نوشته see all، اگر روش بزنید صفحهی همه آهنگها و آلبومها رو میاره، اونجا هم لاجیک خودشو داره. همین برای رادیو هم وجود داره. این فقط بخش معمولی سرچ بود. شرکت بعد از مدتی تصمیم گرفته بود که محصول جدیدی داخل اسپاتیفای ارائه بده، یه لایه جدید از یوزرهای free که داستانی پشتش داره، کاری با بخش بیزینسش نداریم. فکر کنید شرکت یه پروداکت جدید اضافه کرده بود، خود این پروداکت جدید متناسب با نیازش سرچ رو تغییر داده بود، درواقع ما باید برای هر پروداکت که داخل شرکت تعریف میشد یه سرچ متناسب با اون مینوشتیم. مثلا ممکنه سرچ رادیو ورژن جدید با قبلی هم ui، هم endpointهای بکاندش، logic، logging، همه چیش فرق بکنه. یه مفهومی وجود داره توی mvp به اسم multiple presenter که میگه برای هرکدوم از این کارها presenter خودشو بساز و تستهای خودشو بنویس و لاجیک هرکار رو جدا هندل کن. منتها چون اینها یه سری functionality داره که بین هم مشترک هست، طبیعتا از یه سری سوپر کلاس استفاده میشه تا کد duplicate نشه.<br />
مشکل دیگه که تو کد بیسهای بزرگ وجود داره پشتیبانی از ورژنهای مختلفی هست که تا حالا ریلیز کردی. شما حساب کنید این ۶ تا مدل مختلف سرچ تو طول زمان عوض شدن، framework هاشون فرق میکنه، مدل کد بیسش فرق میکنه، اصلا سرچ قبلی تو یه کلاس دیگه وجود داره. مثلا سرچی که اسپاتیفای ۳ سال پیش نوشته هم معماریش فرق داره هم ابزاراش، همه چیش فرق داره ولی چون هنوز تعداد زیادی یوزر دارند و ازش استفاده میکنند و رو ورژنهای قدیمی اسپاتیفای هستند باید اون رو هم ساپورت کنید. در نتیجه وقتی یه فیچر رکوئستی به ما داده میشه، مثلا اضافه کردن فلان دکمه توی سرچ، در ظاهر یه دکمه کوچیکه اما شما باید برا ۶ مدل مختلف سرچ این رو اضافه کنی و برای ورژنهای قبلی backward compatibility داشته باشه. یعنی باید بری تو یه کلاس دیگه که ممکنه dependency injection متفاوتی داشته باشه، mvp نباشه و رو چیز دیگه باشه، به اونم اضافه کنی. همینطور برا تمام اینها باید تست نوشته شه. یعنی شما نمیتونی اینجا یه کد بزنی بگی من خودم دستی تستش کردم کار میکنه. تو شرکت یه استانداردی وجود داره به اسم end to end testing منتها نه به معنی خود end to end یعنی شما باید تمام لایههای تست رو رعایت کنی. وقتی یه کد مینویسی معماریش باید درست باشه، میره تو ریویو و چند نفر میان ریویو میکنند. ممکنه یه سری نظر بدن، معماریش این قسمت اشتباه داره، ممکنه اون قسمتش لیک بکنه، اینجا از این ابزار استفاده کن و …. تمام این ریویوها که تموم شد، شما باید تستت قانون ۸۰٪ کد کاوریج رعایت کنه. یعنی کدت باید ۸۰٪ توسط تست کاور شده باشه. لایه پرزنتر توسط unit test باید ۱۰۰٪ کاور شده باشه. بعد از یونیت تست اگر componentهات تغییر کرده باید integration test براشون بنویسی، یعنی دونه دونه کامپوننتها باید جدا تست بشند قبل از اینکه برند با مستر مرج بشند. مثلا اگر یه باتن رو کلیک میکنی قراره یه انیمیشنی اجرا شه و یه کاری بکنه این رو به عنوان یه کامپوننت integration تست براش بنویسی. تازه تو مرحله بعد اگر back end یا end point جدیدی رو دارید تست میکنید، یا اگر کاری که میکنید خیلی برای یوزر critical هست که معمولا پروداکت منیجر و تیم تعیینش میکنه، باید براش end to end test بنویسی، یعنی یه تستی مینویسی که apk میره رو emulator نصب میشه، دیپلوی میشه، بعد لاگین میکنه، میره اون کاری که شما کردید رو انجام میده، بکاند واقعای رو تست میکنه جواب رو میگیره چک میکنه و اگر همه چی کار کرد اون موقع تست pass میشه و میگه شما کارت موفقیت آمیز بود، در غیر این صورت کدت تو مستر مرج نمیشه، چندین بار review میشه هم بخش تستش هم بخش کد نویسیش.<br />
این جا کد نوشتن یه خرده دردسرهایی داره، معمولا چندتا ورژن رو باید ساپورت بکنی، چندتا ورژن تست بنویسی، بعضی ورژنها اصلا باهم همخونی نداره چون معماریش فرق داره یا ممکنه همهچیش فرق داشته باشه.</p>
<h4 id="چرا-هنوز-کد-بیس-۳-سال-پیش-باید-تغییر-کنه">چرا هنوز کد بیس ۳ سال پیش باید تغییر کنه؟</h4>
<p>برای اینکه تعداد زیادی کاربر ازش استفاده میکنن، در واقع همه بخش های پروژه از یک تکنولوژی استفاده نمیکنن، ممکنه چند سال پیش نوشته شده باشه و از اون موقع ریفکتور و بروز رسانی نشده باشه!</p>
<h4 id="مگه-آپدیت-کنه-کلا-آپدیت-نمیشه">مگه آپدیت کنه کلا آپدیت نمیشه؟</h4>
<p>نه الزاما! مثلا صفحه Home و Search دست تیم ما هست! و هرکدوم یه مدل و تو یه زمان نوشته شده! مثلا تو تو Home از یه کتابخونه برای فلان کار استفاده شده و تو Search از یه کتابخونه دیگه! اینه که ممکنه مجبور بشی برای یه کار دوتا کد با Stack کاملا متفاوت رو تغییر بدی ولی جفتشون یه کار رو باید بکنن در نهایت</p>
<h5 id="تایتل-این-قسمت-رو-نمیدونم-چی-انتخاب-کنم">تایتل این قسمت رو نمیدونم چی انتخاب کنم</h5>
<p>از ۶ ماه پیش حتما باید TDD هم بنویسیم. البته نهایتا زمانی که کد رو پوش میکنیم کسی نمیفهمه شما TDD نوشتید یا نه، منتها وقتی با یکی پر پروگمینگ میکنید و همیشه بغل دستتون هست یا یه چیزی رو توضیح میدید مخصوصا اگر ببینند یک لاجیکی تست نشده باشه این نشون میده شما TDD ننوشتید.<br />
مثلا فکر کنید یه پرزنتری داریم که قرار هست کار شماره ۱-۲-۳ رو بکنه که اینا لیست میشه تو داکیومنتی که داریم. برای اینکه TDD بنویسیم، اولین شروع میکنیم براش تست شماره ۱ رو مینویسیم؛ تست رو اجرا میکنیم و faile میشه، بعد شروع میکنیم حل کردن مشکل. چیکار کنیم که این تست پاس شه؟ کدش رو مینویسیم تا تست pass. و میریم سراغ سناریو ۲ تستش رو مینویسیم و تست faile میشه و شروع میکنیم تست رو حل میکنیم تا آخر. اگر لازم باشه کد رو ریفکتور میکنیم و در نهایت زمانی که کد رو submit میکنیم پرزنترها باید annotation خاصی داشته باشند، برای اینکه بات کد review میاد کلاسها رو چک میکنه و اگر پرزنتیشن لاجیک داشته باشه یعنی این کلاس قرار هست pure جاوا باشه و هیچ قابلیتی از اندروید نباید توش استفاده بشه. این کد باید ۱۰۰٪ تست کاوریج داشته باشه، یعنی به اعضای هر خط کدی که اونجا نوشته شده باید یک تست باشه. هر لاجیکی که هست باید تست شده باشه واگرنه به صورت اتوماتیک پول ریکوست شما ریجکت میشه، اصلا نمیتونید مرج کنید. ۴۳ تست مختلف رو prتون ران میشه، رو هر کامیتی که میکنید اگر رو یه پول ریکوست ۵ تا کامیت هم باشه به اعضای هر ۵ تا تمام تستها روش اجرا میشه. این تستها شامل Static analysis میشه یه سری استانداردها که تعریف شده و با فایلهای xml مشخص میشه. مثلا بعد از اینکه اسم کلاس رو نوشتید باید یه اسپیس بزارید، زمان تعریف تابع حتما باید پابلیک پرایویت یا پروتکتد بودنشون مشخص باشه. یه سری قانون داره اینارو چک میکنه رو کامیت. بعد مثلا به این میرسیم که این کد آیا تست به اندازه کافی داره؟ رو ورژن ریلیز کانفلیکت نمیخوره؟ وقتی که تست تموم شد شما یه نفر رو پینگ میکنید میگید بیا کد من رو review کن. کد review میشه ممکنه یه سری نظر بده اعمال میکنید و کد مرج میشه میره تو master. هرکسی هم رو fork خودش کار میکنه پول ریکوست میده رو مستر مثل کاری که تو گیتهاب رو لایبراریهای معروف انجام میشه. به اعضای هر ریلیزی هم که قرار هست اتفاق بیافته یه برنچ ساخته میشه.</p>
<h4 id="rxjava">rxJava</h4>
<p>توی شرکت از rxjava خیلی خیلی زیاد استفاده میکنیم، ۲ تا چیزی که تو مصاحبه من خیلی روش تاکید شد، یکی چقدر رو rxjava مسلطم و چقدر best practiceهای خود جاوا رو بلدم. تقریبا برای همه چیز از rxjava استفاده میشه. البته تو پروژه اصلی به خاطر infrastructure هنوز رو rxjava1 هستیم. چون هنوز یه سری چیزا تو rxjava2 ساپورت نمیشه نمیتونیم بریم روش. ولی از بکاند بخوای با نتورکینگ چیزی بگیرید، یا io انجام بدید، رو دیسک چیزی بزارید، بین پرزنترها مسیج رد و بدل کنید، هرکاری که بخواید بکنید با rxjava انجام میشه و خیلی به دردمون میخوره.<br />
مدل استفاده اینجا از rxjava برای من اوایلش یه مقدار عجیب غریب بود. تجربه قبلی خودم این بود، کدی رو که مینویسید یه observableای هست بعد باهاش یه سری اطلاعات رو subscribe میکنید مثلا map میکنید به یه چیز دیگه، لازم باشه switch map میکنید، لازم باشه compose میکنید، هر کاری که لازم باشه روی زنجیره کارای rxjava انجام میدید. منتها اینجا مدلی که پیاده سازی کردن و باید تبعیت بکنید اینه که هر کدوم از این فانکشنها برای خودش یه کلاس هست. یعنی اگر بخواید ورودی رو بگیرید مپ کنید به یه چیز دیگه، نمیتونید یه rxchain دو - سه تایی پشت هم بنویسید بگید این رو مپ کن به این، بعد سویج مپ کن به اون و …. کاری که باید بکنید اینه که یه کلاس بنویسید بگید ورودیش اینه خروجیش اینه و تابع map رو implement میکنه. مثلا function1 رو ایمپلیمنت میکنه. توی کلاس کد رو مینویسید و کلاس و آبجکت کلاس رو توی rxchain تون پاس میدید بین هم دیگه. نه اینکه یه زنجیره بزرگ از اوپراتورهای rxjava داشته باشید. اولش مفهوم این یه خورده برای من گیج کننده بود، چون پیش میومد مثلا یه زنجیری از rxJava به وجود بیاد که ۱۰ تا اوپراتور داشته باشه و دیباگ کردنش اوایل برای من عجیب بود، مثلا یه باگی ریپورت میشد و لازم بود یه زنجیر rxjava رو چک بکنم و گیج میشدم یهو آبجکت از این کلاس رفت تو اون کلاس، از اون کلاس برگشت پاس داده شد به یه کلاس دیگه، اوایلش مدل متفاوتی برای من بود.</p>
<h4 id="di">DI</h4>
<p>برای dependency injection تقریبا از یه سال پیش از dagger 2 استفاده میشه. تقریبا الان هر چیز جدیدی که مینویسید باید با دگر ۲ داخلش دیپندسیها اینجک بشه و قبل از اون هم constructor injection بود. به جز constructor تقریبا جای دیگهای حق نداشتید آبجکتی رو new کنید. نمیتونستید توی فانکشن بگید من یه object احتیاج دارم الان اینجا new کنم. اگر همچین کدی مینوشتید پول ریکوستتون با static check که داشتیم failed میشد. چون new کردن آبجکت داخل scope فانکشن با اصول دیپندنسی اینجکشن solid مغایرت داره، اگر میخواید همچین کاری بکنید باید اجازه بگیرید. یعنی یه سری permission خاص بگیرید که به این دلیل لازمه اینجا باشه، اون موقع فقط برای اون pr خاص اجازه صادر میشه. معمولا نمیبینید هرجای کد یه سری آبجکت new شه، اینجا خیلی روی اصول solid تاکید میشه.</p>
<h4 id="test">Test</h4>
<p>هرم تست اینجا به شکل کامل رعایت میشه، unit test خیلی زیاد داریم، تا جایی که میتونید باید یونیت تست بنویسید. Presenter تو معماری mvp باید ۱۰۰٪ code coverage داشته باشه واگرنه پول ریکوست failed میشه. integration test تا جایی که نیاز باشه. end to end test بنا به نیاز نوشته میشه، چون خیلی زمان گیر هست اجرا کردنشون. critical user journey (مهمترین کاربری های یک اپ، مثلا در مورد اپ اسپاتیفای بخش گوش دادن موسیقی، جستجو، ثبت نام، خرید اشتراک، موارد اینطوری که خیلی حیاتی هست رو میگن بهشون) رو end to end test براش مینویسیم. آخر هم manual test داریم، هر هفته جمعه تمام تیمهای اسپاتیفای از ساعت ۱۰ تا ۱۱:۳۰ manual test دارند چون هر جمعه ریلیز داریم.<br />
یه داکیومنتی هر جمعه فرستاده میشه برای تیمها و شما باید این داکیومنت رو امضا بکنی که من پروداکتم رو تست کردم داره کار میکنه یا تست کردم باگ داره ریلیز نکنید. تمام تیم تو اون ۱.۵ ساعت جمع میشند و پروداکتی که دستشون هست رو تست میکنند. چیزای مختلف که اون هفته روش کد نوشته شده یا چیزای قبلی رو تست میکنند. استرس تست یا …. خلاصه ۱.۵ ساعت manual testing هست، تا جایی که میتونید باید چیزای مختلف رو تست کنید که یه وقت باگ نداشته باشه.</p>
<h4 id="glue">GLUE</h4>
<p>تو این ۶ ماهی که تو شرکت بودم، تا حالا یکبار هم نشده یه فایل 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 یا کلاسهایی که از ویو اسکتند شده. اصلا لاجیک نمیزنند.<br />
تیم ما دیزاینر خیلی کم احتیاج داره گاهی یه دیزاینر برای مدت کمی با تیم ما امبد میشه. مثلا برای ریفکتور کردن browse جلسه گذاشت که میخوام این شکلی بکنم این درفت اولیه کار هست چالش داری یا نه؟ نهایی که شد پیاده میکردیم. دیزاین و داکیومنت میداد این باید این شکلی باشه پدینگ و … این باشه. بچههای بکاند هم با glue انجام میدادن ولی یه سری کامپوننتهای کاستومایز شده برا یه پلتفورم هست یا یه فیچر خاص هست معمولا اینارو کلاینت انجام میده.</p>
<p><img src="https://i.ibb.co/w7jv4Q2/screen3.png" alt="" /></p>
<h4 id="hub">HUB</h4>
<p>یه فریمورکی تو اسپاتیفای وجود داره به اسم HUB که بخش iosش بصورت open source رو گیتهاب شرکت هست، اندرویدش هنوز open source نشده و شاید به خاطر هزینه نگهداری نکنند.</p>
<h4 id="اوپن-سورس-شه-هزینه-نگه-داری-میره-بالا">اوپن سورس شه هزینه نگه داری میره بالا؟</h4>
<p>خیلی، چون کدش باید تمیز باشه و مو لای درزش نره. اگر تحت فشار یه کدی رو بزنی میتونی بگی این کامیت رو ۲ هفته دیگه تو اسپرینت بعدی درستش میکنم. ولی اگر open source باشه نمیتونی کد غلط مرج کنی، برای اینکه خیلی راحت ریورسش میکنند و یه سری از نسخههای اپلیکیشن ممکنه هک شه. به خاطر همین دردسر داره نگهداری لایبراریهای open source.</p>
<p>شرکت یه چالشی داشت برای آپدیت نگهداشتن کابرهای قدیمی که هزینش خیلی زیاد بود. یعنی یه شکل یا ظاهر جدید که قرار بود به اپلیکیشن اضافه شه باید کلی برای کاربرهای قدیمی سرمایهگذاری میکردن و یه سری کد برای گوشیهای قدیمی میزدند «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 تون دیگه قدیمی نمیمونه و میتونه عوض شه.
طبیعتا اگر بخواید چیزای خیلی خیلی کاستومایزی بنویسید حتما باید ریلز بدید ولی تا حد خوبی جلو این قضیه گرفته میشه.<br />
ما برای همچین چیزی داشتیم فکر میکردیم که چطور میتونیم یه معماری استفاده بکنیم که کارمون رو راحت بکنه، mvvm برای این انتخاب شد چون یکی از قواعدی که باید توش رعایت شه اینه که دولوپر دسترسی مستقیم به ویو نباید داشته باشه. یعنی شما به عنوان کسی که داری مدل یه چیزی رو مینویسی یا viewModel یه چیزی رو مینویسی به خود ویو نباید دسترسی داشته باشی، این برای خودش یه سری چالش میاره. مثلا فکر کن اگر بخوای یه چیزی رو تو این فریمورک تعریف کنی که خارج از تواناییهای عادی این فریمورک هست عملا هیچ کاری نمیتونی بکنی، چون به ویو دسترسی نداری که مثلا یه انیمشنی روی باتن بزاری. اگه فریمورک ساپورت نکنه نمیتونی، چون اولین کاری که باید انجام بدی view.setanimation یا … هست. در نتیجه با وجود اون دردسرهایی که ایجاد میکرد چون در اسکیل بالا کار خیلی از تیمها و نگهداری خیلی از چیزها رو راحت میکرد تصمیم بر این شد که رو mvvm پیادش کنیم.</p>
<h4 id="hermes">Hermes</h4>
<p>اگر بخوام یه ذره عمیقتر شم، از چند سال پیش یعنی زمانی که HTTP1 بود و هنوز HTTP2 استاندارد نشده بود، شرکت فریمورکی به اسم Hermes نوشت (فکر کنم اوپن سورس هست). هرمس یه فریمورکی رو HTTP1 بود که قابلیت HTTP2 رو بهمون میداد. خیلی شرکتها این رو نوشته بودن چون HTTP1 از یه زمانی به بعد دیگه جوابگو نیاز بعضی از شرکتها نبود و اسپاتیفای هم برای خودش نوشت. اسپاتیفای به نظر من استاد ساختن چرخ از اول هست، چون خیلی چیزارو میبینید از اول برای خودشون نوشتن، برای من عجیبه شاید نیاز بود بنویسند، شاید پروژههای دیگه جوابگو کارشون نبوده، ولی خیلی چیزارو از اول نوشتن. حتی الانم که HTTP2 اومده به شکل زیر ساختی وارد پروژه شد ولی ما همچنان رو هرمس هستیم. برای ما فرقی نداره که HTTP1 استفاده میکنیم یا HTTP2 چون پروتکل هرمس برای ما همهرو هندل میکنه و یه تیم داره که نگهداریش میکنه. خیلی خوب هست این قضیه چون abstract میشه و دیگه لازم نیست ۱۰۰ تیم مختلف بیان آپدیت بکنند، یه تیم آپدیت میکنه برای تمام پروژه apply میشه.</p>
<h4 id="core">Core</h4>
<p>توی اسپاتیفای به مفهومی وجود داره به اسم هسته یا core. کور اسپاتیفای یه سری فانکشنالیتیهایی هست که بین پلتفرمهای مختلف share شده. مثلا player یا نتورکینگ که با hermes انجام میدیم. core با ++c نوشته شده، پروژه نسبتا بزرگی هست و فکر کنم یه تیم ۲۰ نفره فقط مسئول نگهداری core هستند که شامل پلیر، هرمس و یه سری چیزای دیگه هس، من دقیقا نمیدونم چیکار میکنند چون امکان نداره آدم همیشه بدونه همهی تیمها چیکار میکنند. خیلی شرکت بزرگه، فقط کار خودت رو بتونی خوب انجام بدی هنر کردی. من به شخصه به تیم core خیلی علاقه دارم چون ++c رو خیلی دوست دارم. اگه یه موقع احساس کردم میخوام یه چیز جدید رو امتحان بکنم یکی از گزینههایی که دوست دارم contribute به core هست. همونطور که گفتم پلیر با core هندل میشه و یه پروتکل کاستوم براش نوشته شده. پلیر هم یه کد نسبتا قدیمی هست چون از خیلی وقت پیش ساپورت میشد، ولی آخریا ساپورت رو تا اندروید ۴.۱ آوردیم. به خاطر پروتکلهای مختلفی که بین ورژنهای اندروید ساپورت میشه نمیتونستیم به مدیا پلیر خود اندروید اکتفا کنیم. مجبور بودیم مدیا پلیر خودمون رو بنویسیم که بتونه کدکها و پروتکلهای خودمون رو ساپورت بکنه. و این بود که مجبور شدند یه مقدار low level و با ++C بنویسند تا بتونند توی پلتفرمهای مختلف بصورت مشترک استفاده بکننش. چون نمیشد فقط با جاوا بنویسی، اگر اونجوری میخواستیم بنویسیم باید یکی برا جاوا مینوشتیم، یکی برا ios، یکی برا وب، یدونه برا ps ،xbox و …</p>
<h4 id="ci--cd">CI &amp; CD</h4>
<p>ما الان رو 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 باشه. یه خورده هم پروژه زمان بری هست، چون کلی از تستهای شرکت باید تغییر بکنه، خیلیهاش اصلا باید زیر ساختش تغییر کنه ولی هم کار جذابیه و هم نتیجهاش ارزشمنده.</p>
<h4 id="کد-گردی">کد گردی</h4>
<ul>
<li>اسپاتیفای با اینکه قراره بخشهایی از پروژه رو نشونمون بدی مشکلی نداره؟</li>
</ul>
<p>بهشون گفتم که میخوام یه چیزایی رو برای آموزش نشون بدم.<br />
برای فیچرهایی که از ۱-۲ سال پیش شروع شده همه حتما باید از دگر استفاده کنند. این الان کل پروژه هست و این پکیجی هست که کد سرچ توش وجود داره قبلا این پکیج ۲ تا بود، چون ۲ تا ورژن از سرچ وجود داشت. ما با یه مکافاتی قبلی رو ریفکتور کردیم و آوردیم رو فریمورک جدید و قبلی رو پاک کردیم.<br />
استراکچر اینجوری هست که ما با خودمون توافق کردیم پرزنتر یه جا باشه، کدی که لاگ میکنه یه جا باشه، بخشی که هیستوری سرچ هست یه جا، کالبکها تو یه پکیج هست، کاموننتها (ویوهایی که کاستوم کردیم خارج از هابز، توی فریمورک هابز نبودن و بهش اضافه کردیم) و کامندهایی که ساپورت میکنیم تو پروژه رو هم توی یه پکیج گذاشتیم.<br />
فریمورک هابز برای ما یه سری کارهای جادویی انجام میده، مثلا رندر میکنه یا یه سری کامند که از پیش تعریف شده از سمت بکاند ارسال شه رو خودش هندل میکنه. مثلا شما میتونید با کمتر از یه ساعت کد زدن ورژن ساده صفحه سرچ رو یه بار دیگه از اول درست کنید، یعنی یه پرزنتر ساده مینویسید، بعد یه endpointی رو صدا میزنید و جواب رو به هابز تحویل میدید، خود هابز بقیه چیزارو هندل میکنه و میاره بالا، همه کارهایی که بصورت پیشفرض نیازه مثل click, long click, play و یه سری کامند دیگه رو خودش ساپورت میکنه. منتها یه سری کارهارو لازم هست که به صورت کاستومایز شده انجام بدید مثلا اگر توی سرچ رو چیزی کلیک کردید، بسته به این که چی هست کارهای مختلفی باید انجام شه. مثلا اگر آهنگ باشه باید پلی بکنه، یا اگر آلبوم باشه باید بره تو صفحش و تو هیستوری کاربر هم نگهش دارید، این چیزی بود که بصورت پیش فرض ساپورت نمیشد. مثلا برای این مجبور شدیم یه command handler کاستومایز شده بنویسیم و توی هابز خودمون اضافش کنیم، که فلان کامند رو خودم میخوام هندل کنم؛ یا وقتی رو این کلیک شد دیگه هابز هندلش نکنه من خودم هندلش میکنم.</p>
<h4 id="فیسبوک-هم-یه-کتاب-خونه-داره-که-دیستریتیو-ui-مینویسی-دیدینش-یا-نه-litho">فیسبوک هم یه کتاب خونه داره که دیستریتیو ui مینویسی دیدینش یا نه؟ (Litho)</h4>
<p>ما کتابخونههای فیسبوک رو اکثرا نمیتونیم استفاده کنیم به خاطر لایسنسش که یه مقدار سختگیرانست، چند وقت پیش هم react رو عوض کردند و ما تازه تو دسکتاپ شروع کردیم از react استفاده کردن وگرنه قبلا فکر کنم angular مینوشتند.<br />
این کدی هست که باهاش لاگهای مختلفی که تو پروژه انجام میشه رو مینویسیم، ۲ تا پرزنتر مختلف داره یه پرزنتر برای صفحه سرچ و یکی برای صفحهای که با زدن دکمه see all میرید اون تو.
توی کد مدلهای مختلف ریکوست رو ما به بکاند میزنیم، مثلا همین صفحه سرچ ریکوستهای مختلفی به بکاند میزنه، یکیش صفحه سرچ تو حالت عادی هست که میاید یه کوئری میزنید یه جواب میگیرید، ممکنه از صفحه سرچ تو حالت آفلاین استفاده بکنید که ما به هسته ++C ریکوست میزنیم و اون هم تو مجموعه ریکوستها قرار میگیره، یا صفحه see all هم یه مدل ریکوست میزنیم.<br />
شرکت یه محصول جدیدی تعریف کرد که خوبه در موردش صحبت کنیم. اسپاتیفای بعد از یه مدتی بررسی و نتیجهگیری، بصورت عمومی اعلام کرد که ما یادگرفتیم چطور کاربر پرمیوم بسازیم، یعنی کاربر معمولی رو تبدیل کنیم به کاربر پریمیوم و حتی یاد گرفتیم چطور کاربر پرمیوم رو پرمیوم نگه داریم. در نتیجه خوب داریم پول در میاریم. فقط مشکلی که داریم اینه که نمیتونیم به اندازه کافی کاربر جدید بگیریم و مجبور شدند سراغ کشورهایی که بهشون بازارهای نوظهور (emerging market) میگند مثل چین، هند، اندونزی یا کشورهایی مثل مکزیک، برزیل برند. با توجه به محدودیتهایی که این کشورها دارند، اپ فعلی اسپاتیفای اصلا براشون مناسب نیست. این بود که یه ماموریت جدیدی تو شرکت تعریف شد که یه اپی بنویسیم (داخل خود اپ اسپاتیفای) که برای این مدل کشورها طراحی بشه، یکسال کار کردند و این محصول الان ریلز شده. کلا یه محصول دیگه داخل اپ هست. یعنی وقتی کاربر وارد اپ میشه کلا میره تو یه سری پکیج دیگه. مثلا نویگیشن باتن ۳ تا بود، صفحه اصلی استراکچرش عوض شد، بکاندهایی که باهاش صحبت میکردیم عوض شد، قابلیتهای سرچ تغییر کرد، صفحه browse رو با سرچ یکی کردیم. خلاصه بسته به اینکه چه مدل کاربری هستید، تعداد زیادی ریکوستهای مختلف به بکاند زده میشه.
برای همین وقتی شما یه پروداکتی توی شرکت دستتون باشه، روی همون تعداد زیادی A/B Test داره انجام میشه یا در واقع پروداکتهای مختلفی رو در قالب یه پروداکت مشخص دارید به مردم ارائه میدید (مثل همین اپی که برای بازارهای نوظهور درست شده و توی همون اپ اسپاتیفای هست)، یعنی معمولا سرچ رو یه سری کاربر به یه شکل میبینند یه سری دیگه به یه شکل دیگه و همه اینا جزو زیر مجموعه تیم شما هست. اگه قرار باشه یه چیزی عوض شه یا یه پارامتری به صورت کلی به بکاند ارسال بشه یا یه uiیی اضافه شه، معمولا شما مجبورید کل این پروداکتها ریفکتور کنید. در نتیجه معمولا حجم کاری تو یه فیچر، از چیزی که به نظر میاد بیشتره.<br />
این پکیح rx ما هست، این پکیج مجموعه کارهایی هست که ما با rx java انجام میدیدم.</p>
<h4 id="اگر-برای-صفحاتی-که-ab-test-داریند-تسک-بیاد-رو-کدومش-انجام-میدید">اگر برای صفحاتی که A/B test داریند تسک بیاد رو کدومش انجام میدید؟</h4>
<p>باید بری همه رو ریفکتور کنی</p>
<h4 id="یعنی-جفتش-تو-apk-هست-و-سرور-میگه-کدوم-رو-لود-کنه">یعنی جفتش تو apk هست و سرور میگه کدوم رو لود کنه؟</h4>
<p>تو سرچ حتی چالش برانگیزتر بود. صفحه اصلی یه معماری و یه سری فریمورک استفاده میکرد دکمه see all رو که بزنی میره تو یه فرگمنت دیگه تو اون کلا یه چیز دیگه بود. مثلا اگر رو یه ترک کلیک کنی تو صفحه اصلی سرچ و اون صفحه باید یه کار رو بکنه، نمیشه تو یکیش پلی کنه تو اون یکی یه کار دیگه. ۲ تا چیز رو باید همزمان maintain میکردی. یا بدتر تو هر کدوم از این فرگمنتها ۴ تا A/B test وجود داشته باشه باید اونا رو هم حتی ساپورت بکنی بعضی وقتها وقعا چالشی میشد ساپورت کردن چندتا ورژن از یه چیزی. به این مفهوم که چندتا ورژن مختلف و چندتا معماری و سبک کد زدن مختلف توی کدبیس باشه میگن شما Technical debt دارید (بدهکاری فنی)، یعنی شما هزینه نگهداری یه کد قدیمی رو میدید و این رو اگر توی طول زمان درست نکنید به صورت تصاعدی بالا میره و تکنیکال دبت رو توی سطح معینی نگه دارید.</p>
<h4 id="کی-باید-درستش-کنیم">کی باید درستش کنیم؟</h4>
<p>معمولا اینجوری میشه، برای سه ماه بعد میخوای برنامهریزی کنی و یه ab تست گندهای روی پروژه ران بشه، میپرسن چقدر پیاده سازیش طول میکشه؟ که شما میگی دو ماه. میگن چرا دو ماه؟ میگید چون این تکنیکال دبت داره. میگن خیلی خب ab تست رو نگهدارید و اول تکنیکال دبت درست کنید. سه ماه زمان میذارید، کلی کد ریفکتور میکنید، تستهای قدیمی رو حذف میکنید، معماریشو عوض میکنید و باید از اول بنویسید.</p>
<h4 id="این-رو-پروداکت-اونر-میگه-یا-تکنیکال-لید">این رو پروداکت اونر میگه یا تکنیکال لید؟</h4>
<p>بستگی داره، ممکنه حتی از بالاتر بیاد.</p>
<h4 id="همه-اینا-که-میگی-توی-پکیج-سرچ-و-برای-سرچ-بود">همه اینا که میگی توی پکیج سرچ و برای سرچ بود؟</h4>
<p>آره خارج از سرچ نیست، هر فیچر همه اینارو برای خودش جداگونه داره</p>
<h4 id="همه-تیمها-همین-شکل-پکیجبندی-میکنند-یا-فرق-داره">همه تیمها همین شکل پکیجبندی میکنند یا فرق داره؟</h4>
<p>کم و بیش همینجوری هست، مخصوصا اسکوادهای که تو یک ترایب باشند، چون با هم جلسه زیاد داریم و با هم زیاد کار میکنیم. برای همین احتمالا کدهای یه اسکواد تو نیویورک رو ببینید خیلی متفاوت هستند. البته معمولا اگر تیمها با هم قرار باشه کار کنند، یه داکیونتی رو با هم رد و بدل میکنند به اسم «چطور میخوایم با هم کار کنیم؟» اگر قرار باشه از تیم شما برای ما پول ریکوست بیاد و ما ریویو بکنیم این باید حداقل از ۲ هفته قبل اطلاع رسانی بشه که ما بتونیم براش برنامه ریزی کنیم یا اگر باگی پیش بیاد که شما کدش رو ادیت کردید خودتون باید رفعش بکنید. یه سری قرارداد میبندیم که ما قرار هست اینجوری با هم کار بکنیم.</p>
<p>خلاصه 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 رو شکوندیم به کارای خیلی کوچیک، یعنی وقتی نگاه میکنید، ما تعداد خیلی زیادی کلاس داریم که هرکدومش یه کار خیلی کوچیک رو میکنه.</p>
<h4 id="یعنی-الان-لاجیکی-که-هر-اوپراتور-rx-java-میخواد-اجرا-کنه-رو-تبدیل-به-یه-کلاس-کردید">یعنی الان لاجیکی که هر اوپراتور rx java میخواد اجرا کنه رو تبدیل به یه کلاس کردید؟</h4>
<p>یه جورایی آره، در واقع rx chain ما به این شکل هست هرکسی کارش رو میگیره تحویل اپوراتور بعدی میده</p>
<h4 id="جنس-این-کلاس-چیه--یه-کلاس-معمولی-جاواست-همشون-">جنس این کلاس چیه ؟ یه کلاس معمولی جاواست همشون ؟</h4>
<p>آره همشون POJO هستند و به همین خاطر هست که میشه ۱۰۰٪ براشون تست نوشت.<br />
اومدیم در واقع این کارارو شکوندیم به یه سری کار خیلی کوچیک که هرکدوم یه کار خیلی کوچیک رو انجام میده و براش تست متناسب با خودش رو نوشتیم. یعنی شما امکان نداره حالتی پیدا کنید که تستی براش نوشه نشده باشه، چون کار خیلی کمی رو داره انجام میده.</p>
<p>مدل کد نوشتنمون تو شرکت معمولا به این شکل هست، اول میریم فرگمنت و پرزنتر رو میسازیم، بعد سنارویوهایی که قرار هست پرزنتر هندل کنه رو با TDD تستش رو مینویسیم و پیاده سازی میکنیم، دونه به دونه میریم جلو. این یه شمای کلی بود از این فیچری که ما تو سرچ پیاده سازیش کرده بودیم. حالا همونطور که گفتم برای هرکدوم از اینا باید دونه به دونه تست بنویسیم، یعنی بنویسیم که این کلاس کاری که باید انجام بده رو انجام میده یا نه، مثلا این تستی هست که برای پرزنترمون نوشتیم، تستها معمولا اینجوری شروع میشه که یه annotation دارن که این فیچر برای کدوم تیم هست. با Robolectric اجرا میشن. یه سری پارامتر رو به صورت پیشفرض با static final و … آماده کردیم، به جز اون چیزی که اتفاق میافته شما توی کلاسها نباید هیچ موقع آبجکتی رو new کنید، هرچیزی که یه کلاس لازم داره رو باید همیشه با dagger و بصورت constructor injection بهش پاس بدید، چون dependency injection باعث میشه تست نوشتن خیلی راحت بشه.<br />
تعداد زیادی آبجکت داریم که کنار همشون خورده mock، علتش اینه که ما میاییم یه کلاسی رو میسازیم توی حالت تست، تمام آبجکتهایی که لازم داره رو mock میکنیم و دونه دونه توش اینجکت میکنیم، یعنی یه کلاس رو با تمام چیزایی که لازم داره به صورت ماک شده میاریم بالا. مثلا کلاسی که میخوایم تست کنیم یه کلاس دیگه رو برای هندل کردن یه باتن نیاز داره، این کلاس رو mock میکنیم و از طریق استراکچر given when then بهش دیتای ماک میدم. این استراکچر اینجوریه:<br />
Given یعنی در شرایط فلان<br />
When اگر این اتفاق افتاد<br />
Then این کار رو انجام بده<br />
مثلا وقتی رو این دکمه کلیک کردم و منتظر برگشت یک استرینگ از یه فانکشن بودم، این استرینگ رو برگردون به فانکشن بده. این آبجکتهای ماکی که داشتیم رو تنظیم میکنم میگم تو این شرایط اگر این رو کلیک کردم این کار رو بکن، اگر این کار کردم این کار بکن و سناریوهایی که واقعا توی اپ داره اتفاق میافته رو تنظیم میکنم و دونه دونه شروع میکنم چک کردن فانکشنها که تو پرزنتر هست، مینویسم اگر این اتفاق افتاد با توجه به این ماکها من منتظرم این جواب رو بگیریم، آیا میگیرم یا نه، اگر گرفتم فانکشن داره درست کار میکنه اگر نگرفتم یه چیزی این وسط خراب شده.</p>
<p>برای سناریوهای مختلف باید یونیت تست بنویسیم. مثلا تعداد خط کد پرزنتر ما ۴۳۴خط هست ولی تعداد خط کلاس تست پرزنتر ۴۴۵ خط هست. بیشتر از ۱۰۰٪ کد کاوریج داره. یعنی احتمالا یه سری سناریو، دیپریکیت شده.</p>
<h4 id="مثلا-برای-یه-خط-۲-تا-تست-نوشتید">مثلا برای یه خط ۲ تا تست نوشتید؟</h4>
<p>نه نمیشه برای این که یک نفر کدت رو ریویو میکنه</p>
<h4 id="منظورم-اینه-که-یه-متد-که-نوشتید-فقط-یه-حالت-تست-مینویسید-یا-چندتا">منظورم اینه که یه متد که نوشتید فقط یه حالت تست مینویسید یا چندتا؟</h4>
<p>یک متد باید یک کار رو بکنه، در نتیجه وقتی که برای یه متد ۲ تا تست مینویسی، یعنی متدت یه ایرادی داره. طبق اصول solid باید single responsibility داشته باشه. ولی بعضی جاها ممکنه پیش بیاد، اصلا نمیشه کاریش کرد. ممکنه این فانکشن ذاتا side effect داشته باشه و هیچ کاریش نمیشه کرد ولی به صورت کلی باید اون رو رعایت کنیم.<br />
حالا فکر کنید یک المان ui رو ادیت کردید، برای این که تستتون یا پول ریکوستتون قابل مرج شدن باشه، باید برای اون کامپوننت ui که تغییر دادید integration test بنویسید. یعنی یدونه کامپوننت رو از شرایط واقعی مجزا میکنید، تستهایی که لازم هست رو روش اجرا میکنید، بدون این که مهم باشه در سایر المانهای اطراف اتفاقی میافته یا نه، یعنی در دنیا واقعی نمیخوایم تستش کنیم، فقط خود اون کامپوننت رو تنها میخوایم تست کنیم. مثلا رو یه باتن که کلیک میکنید، میخواید یه انیمیشنی روش اجرا بشه، این رو براش یه کامپوننت تست مینویسید، چطور؟ ما یه ابزار داخلی داریم که باهاش اینتگریشن تستها رو مینویسیم، (اسم فریمورک Caset هست) فکر نمیکنم اوپن سورس شده باشه و فکر کنم که هیچ وقت هم نمیشه، چون خیلی هکی هست و همه چیزش با هک کردن یه سری چیز روی robolectric نوشته شده. مثلا این کلاس اینتگریشن تستی هست که برای صفحه اصلی سرچ وجود داره، یدونه فرگمنت میسازه، فرگمنتی که میخوای توش یه تستی رو انجام بدی، مثلا من فرگمنتم رو کانفیگ میکنم با این شرایط میارم بالا، بهش میگم من یه کاربر free میخوام، یعنی زمانی که این تست رو ران میکنی، یه کاربر free بساز و اینجکت کن تو محیط برنامه و برنامه رو توی حالت پروداکشن بیارش بالا، یه سری فلگ override میکنم برای این کاربر، مثلا تستی که اینجا نوشتم، اسمش اینه testWithSearchResult، دارم تست میکنم که سرچ وقتی که موفقیت آمیز هست، result که من منتظرش هستم باید داشته باشه. چه جوری این کار رو انجام میدم؟ میام یه محیط کانفیگ میکنم، این تست یه جورایی BDD هست یعنی یه جورایی مبتنی بر یه رفتار مشخصی هست. حالا یه محیطی رو کانفیگ میکنم میگم اگر کاربر تو این فرگمنت اومد بالا:<br />
when زمانی که من روی اون TextFiled فکوس کردم، کوئری که اون بالا تعریف کردم رو بذار توش، یه مدت زمانی منتظر باش<br />
then اول چک کن که ریزالتها لود شدن یا نه، که این یه فانکشنی هست که به شما برمیگردونه که ریزالتها لود شدند یا نه، آخر سر چک میکنم که get number of show all تعداد آیتمهای شو آل من بیشتر از ۰ باشه.<br />
این یه تست خیلی عمومی بود، بسته به سناریویی که میخوایم تست بکنیم، دقیقتر از این تست میکنیم. مثلا برای وقتی که چک میکنیم ریزالت وجود داره، تعداد تاپ ریزالتها، ریکوردها یا آرتیستها رو میگیریم. ما برای اون کوئری مشخص، اینجا مشخص کردیم که قرار هست بکاند ۰ تا تاپ ریزالت برگردونه ۴ تا آرتیست ۴ تا آلبوم الی آخر. کامپوننت این فرگمنت باید عین سناریویی که من منتظرش بودم رندر بشه، اگر رندر شد یعنی تست موفقیت آمیز بوده و اگر نشد یا یه مشکلی تو بکاند وجود داره یا تو فرانتاند، این تست همیشه هر ۶ ساعت یک بار روی کد بیس اجرا میشه، فارغ از اینکه کامیت جدیدی وجود داشته باشه یا نه، به ما کمک میکنه که مثلا اگر بکاند اشتباه کرد و به جای ۴ تا آرتیست ۳ تا برگردوند، تست fail میشه. ما سریع متوجه میشیم و براش تیکت مینویسیم و حلش میکنیم. یا مثلا اگر یکی اومد کد مارو ویرایش کرد، این تست ران میشه و متوجه میشیم مثلا کامپوننت ما بعد ویرایش درست رندر میشه یا نه.</p>
<h4 id="بکاند-رو-تست-میکنید-یا-بکاند-ماک-هست">بکاند رو تست میکنید یا بکاند ماک هست؟</h4>
<p>هم میتونه بکاند ماک شده رو تست کنه، هم بکاند واقعی بستگی به کانفیگ داره.</p>
<h4 id="بکاند-همیشه-دیتا-ثابت-میده-برای-این-تستها-از-کجا-میفهمیم-که-بکاند-خرابه-یا-مثلا-یه-آرتیست-به-دیتابیس-اضافه-شده">بکاند همیشه دیتا ثابت میده برای این تستها؟ از کجا میفهمیم که بکاند خرابه یا مثلا یه آرتیست به دیتابیس اضافه شده؟</h4>
<p>این رو دیگه باید چکش کنیم و ببینیم اشتباه از کجا هست ولی این فلگها که اورراید میشه معمولا برای این هست که همیشه تا حد امکان یه ریسپانس مشخص رو بگیره.<br />
اگه کامپوننت ui رو ادیت بکنید، باید یه دونه اینترگریشن تست مناسب باهاش رو هم بنویسید. بعد از این مرحله، یه مرحله بالاتر هم تو هرم تست وجود داره به اسم end to end testing، تستهایی هستند که با espresso مینویسیم و رو دیوایس واقعی اجرا میشند و همیشه با بکاند واقعی کار میکنند.</p>
<h4 id="این-هرمی-که-گفتی-یونیت-تست-مشخص-هست-اون-بالا-بالایی-هم-که-end-to-end-test-هست-مشخصه-که-با-اسپرسو-کل-یه-عملکرد-برنامه-تست-میشه-مثلا-یوزر-چه-کارایی-میتونه-انجام-بده-حالا-این-وسط-اینترگریشن-تست-میشه-اکتیویتی-با-فرگمنت-چه-جوری-محدودش-رو-مشخص-میکنید">این هرمی که گفتی یونیت تست مشخص هست، اون بالا بالایی هم که end to end test هست مشخصه که با اسپرسو کل یه عملکرد برنامه تست میشه مثلا یوزر چه کارایی میتونه انجام بده. حالا این وسط اینترگریشن تست میشه اکتیویتی با فرگمنت؟ چه جوری محدودش رو مشخص میکنید؟</h4>
<p>هر چقدر به سمت بالا هرم تست حرکت بکنی هزینه نگهداری و اجرا کردنش خیلی میره بالا. یعنی ما هر دفعه که end to end تست ران میکنیم، end to end تست میاد یه apk رو برمیداره میبره رو یه دونه دیوایس نصب میکنه، login میکنه و …، هزینه اجرا این تست خیلی زیاده و وقتی ما بخوایم اندتواند تست بخش سرچ رو ران کنیم، نیم ساعت طول میکشه. اما اینترگریشن تستهامون کمتر از ۱ دقیقه و یونیت تست کمتر از ۱۰ ثانیه طول میکشه. در نتیجه اگر قرار باشه یه اندتواند تست بنویسید باید حواستون باشه که آیا واقعا لازمه؟ چون تا جایی که میتونید، همه چیو باید با یونیت تست و اینتگریشن تست کاور بکنید. معمولا end to end تست رو برای جایی مینویسیم که سناریو فوقالعاده حیاتی و critical هست، مثلا لاگین هیچ موقع نباید fail بشه، اگر بشه خیلی افتضاح هست، کاربر جدید نمیتونه استفاده بکنه. یا مثلا توی سرچ این که ریزالتها یکبار لود شه و باتنها کار بکنه رو حتما باید تست کنیم. برای این که هر جمعه ساعت ۱۰ تا ۱۱ صبح regression test داریم. تمام اعضای تیم جمع میشن و نفری یه گوشی رندوم با یه کاربر رندوم برمیدارن و شروع به تست کردن یکی از فیچرهای شرکت میکنند، توی رگریشن تست همیشه همه اعضا از پروداکت اونر، مدیر، دیزاینر، برنامه نویس همه جمع میشند و تست میکنند، خوبیش هم اینه که اپ از زوایای مختلف تست میشه و اینجوری نیست که فقط از زاویه دید برنامه نویس تست شه. ریگریشن تست رو هفتهای یکبار اجرا میکنیم ولی end to end تست رو هر ۶ ساعت یکبار، اینتگریشن تست روی تکتک کامیتها تست میکنیم یعنی مطمئن میشیم چیزی که میخوایم واقعا رندر میشه یا نه.</p>
<h4 id="چندتا-از-هر-کدوم-دارید">چندتا از هر کدوم دارید؟</h4>
<p>برای هرکدوم ۲۰-۳۰ تا تست رو در نظر بگیر، تو یه کلاس منظورم هست، البته باید زمان بیلد شدن گریدل رو هم بهش اضافه کرد ولی اون خارج از دست ماست تا حد زیادی و ثابت هست. تعداد کلاس هم متناظر با تعداد کلاسهای که بیزنس لاجیک هست، تو یه پکیج شاید ۴۰-۵۰ تا کلاس هست، برای اینتگریشن تست حدود ۵-۱۰ تا کلاس و اندتواند ۱ دونه کلاس.</p>
<h4 id="گوگل-جدیدا-توی-داکیومنت-اندروید-یه-بخشی-نوشته-که-مثلا-end-to-end-تست-۲۰-درصد-باشه-یونیت-تست-۶۰-درصد-و--ولی-کلا-یه-سری-مثالها-گفتن-اینترگریشن-تست-رو-با-اسپرسو-بنویسید-خیلیها-اصلا-اسپرسو-تو-اینتگریشن-استفاده-نمیکنند-یا-همش-روبوالکتریک-استفاده-میکنند-و--من-نمیفهمم-مثلا-اشکال-داره-اسپرسو-تو-اینتگریشن-استفاده-شه-یا-چون-نیاز-نمیشه-کسی-استفاده-نمیکنه">گوگل جدیدا توی داکیومنت اندروید، یه بخشی نوشته، که مثلا end to end تست ۲۰ درصد باشه، یونیت تست ۶۰ درصد و … ولی کلا یه سری مثالها گفتن اینترگریشن تست رو با اسپرسو بنویسید، خیلیها اصلا اسپرسو تو اینتگریشن استفاده نمیکنند یا همش روبوالکتریک استفاده میکنند و … من نمیفهمم مثلا اشکال داره اسپرسو تو اینتگریشن استفاده شه؟ یا چون نیاز نمیشه کسی استفاده نمیکنه؟</h4>
<p>اسپرسو یه قابلیت خوبی که به شما میده اینه که میتونید رو دیوایس واقعی اجراش کنید که میشه همون end to end تست، میتونی تو لول انتگریشن هم ازش استفاده کنی. ولی روبو الکتریک روی دیوایس واقعی کار نمیکنه و اندروید رو امولیت میکنه.<br />
اندتواند تست هم معمولا با توافق تیم مشخص میشه «این سناریو خیلی مهم هست پس end to end تست بنویسیم». همه هم میگند تا جایی که میتونید هرم تست رو پایین نگه دارید ولی اینکه درصدش چقدر باشه سناریو چطور باشه تیم به تیم فرق داره. یه سختی دیگه هم که end to end تست داره اینه که باید براش ci یا cd تعریف کنید. مثلا jenkins راه بندازید، اتومیت کنید که اینا کار اندروید دولوپر نیست، اینا یه دوآپس خوب میخواد که این محیطها رو خوب بشناسه، از یه برنامه نویس عادی اندروید نمیشه انتظار داشت که هم کد خوب بنویسه، هم یونیت تست بنویسه، هم end to end تست بنویسه. همه اینا رو باهم از یه تیم کوچیک نمیشه انتظار داشت. اگر بخوای انتظار داشته باشی، سرعت کارت خیلی میاد پایین. ما خیلی از کارامون تو شرکت دلیگیت شده به یه تیم دیگه. مثلا خود تیم ما باتن نمینویسه و دلیگیت شده به تیم دیگه. هر تیمی داره یه کار کوچیکی انجام میده.</p>
<h4 id="تیمی-که-تست-مینویسه-یه-تیم-دیگست-یا-خودتی">تیمی که تست مینویسه یه تیم دیگست یا خودتی؟</h4>
<p>نه خودمم. تست رو خود دولوپر باید بنویسه</p>
<h4 id="تیمی-هم-دارید-که-تست-دستی-انجام-بده">تیمی هم دارید که تست دستی انجام بده؟</h4>
<p>نه همون ریگریشن هست که هر جمعه همه باهم تست میکنیم. یه نفر با نقش qa داریم ولی اون یه نفر نمیرسه همه چیز رو تست کنه، معمولا qa داشبورد تست رو maintain میکنه، مثلا صبح به صبح که میگیم این تست fail شد، معمولا اون آدم میره چک میکنه چرا fail شده، اگر سوادش رو داشته باشه ممکنه حلش بکنه اگر نه اساین میکنه به یه دولوپر.<br />
ما کلا ۲ تا ویو تو سرچ نوشتیم، جمعا یدونه اون تولبار اون بالا که کاستومایز شدست و تولبار خود اندروید نیست، یکی هم وقتی که سرچ میکنید و نتیجه خالی باشه اون empty view میاد رو هم خودمون نوشتیم. بقیه چیزایی که تو سرچ نوشتیم لاجیک هست یا تست. ویو نمینویسیم. معمولا یه چیزی هم داریم به اسم ویو بایندر چون لایبراری که استفاده کردیم mvvm بوده، ویو بایندر واسطی هست بین ما و اون لایبراری که با توافق ما و اون تیم نوشته شده. مثلا ما بخوایم یه انیمیشنی اجرا بکنیم به ویو بایندر میگیم با اون لایبراری صحبت میکنه، خیلی چیز خاصی نیست.<br />
بقیه کلاسها هم یا پرزنتر هست یا ماژولهای دگر یا کامپوننت یا فرگمنتها و اینطور چیزها. این کد بیس یکی از تیمهایی هست که داره اونجا کار میکنه.</p>
<p>کد review مکانیزم خاصی؟ هرکسی میتونه کد کس دیگهای رو ریویو کنه؟</p>
<p>تمام کلاسهایی که نوشته میشه یه annotation داره که برا چه فیچری هست شما اگر کدی رو کامیت بکنی که مثلا یکی از کلاسهای فیچر ما ادیت شده باشه ما به صورت اتوماتیک پینگ میشیم تو اون کد ریویو. ولی الزامی نداره ما حتما تایید کنیم چون طرف ممکنه یه خط کامنت نوشته باشه. اگر بخوان یه آدم خاص ریویو بکنه پینگش میکنند ولی به صورت کلی هر تیم یه استاندارد داره که خود تیم مشخص میکنه. مثلا استاندارد تیم ما اینه که حتما اینتگریشن تست ۱۰۰٪ هست یا naming convention مشخص داریم comment style مشخص داریم اینارو کسی که با کد ما کار میکنه باید رعایت کنه. اگر یه فیچر رو برای یه تیم دیگه ادیت بکنی یه ایمیلی برات میاد و میگه این داکیومنت این تیم هست و باید بخونی و میگه آیا اینا رو رعایت کردی یا نه؟ چون نمیشه همه چیز رو تو استاتیک آنالایز چک کرد.</p>
<h4 id="ساختار-پروژه-رو-کی-تعیین-میکنه">ساختار پروژه رو کی تعیین میکنه؟</h4>
<p>تو طول زمان عوض شده ولی به صورت کلی هر تیم مسئول حفظ و نگهداری سلامت فیچر خودشه. کس دیگهای نمیاد بهت بگه اینجوری کار کن مثلا از این استفاده کن خوبه یا بده. تماما به اختیار خود تیم هست و تو تیم تصمیم گیری میشه که چه شکلی باشه. این که به صورت کلی پروژه چه شکلی باشه معمولا انجینیرهای قدیمیتر تو لولهای بالاتر، مثلا یه نفر لید ترایب هست که اون جهت گیری فنی ترایب رو مشخص میکنه. معمولا هرچی لول بره بالاتر ضریب نفوذ روی پروژه به شکل high level افزایش پیدا میکنه. مثلا این که ما نمیتونیم از یه سری لایبراریها استفاده بکنیم دلیل اینه ترایب لیدمون نمیتونه اجازه بده این لایسنس رو تو پروژمون داشته باشیم.</p>
<h3 id="سوالهای-بچهها">سوالهای بچهها</h3>
<h4 id="یه-جا-گفتی-اگر-به-چندتا-بخش-پروژه-کمک-کنی-مثل-بک-اند-دیتا-ساینس-و--استیتت-میره-بالاتر-و-وظایف-بیشتری-انجام-میدی-آیا-توی-فیلد-خاص-خودت-پیشرفت-کنی-بهتر-نیست-و-برای-شرکت-ارزشمندتر-نیست-تا-اینکه-سعی-کنی-توی-چندتا-فیلد-تلاش-کنی">یه جا گفتی اگر به چندتا بخش پروژه کمک کنی مثل بک اند، دیتا ساینس و … استیتت میره بالاتر و وظایف بیشتری انجام میدی، آیا توی فیلد خاص خودت پیشرفت کنی بهتر نیست و برای شرکت ارزشمندتر نیست تا اینکه سعی کنی توی چندتا فیلد تلاش کنی؟</h4>
<p>این سوال خوبیه که یه کار رو خیلی خوب انجام بدی بهتره یا چندتا کارو انجام بدی؟ دو مدل کلی برنامهنویس داریم. برنامهنویس T شکل و اگر اشتباه نکنم I شکل.<br />
برنامهنویس T شکل برنامهنویسایی هستند که مثل حرف انگلیسی T بالاش یه خط داره که به یه خط دیگه عمود هست، یعنی شما توی دو جهت دارید حرکت میکنید. مثلا ممکنه یه سری زبانهای مختلف رو یاد بگیرید. این برنامهنویسا معمولا کسایی هستند که برای کارایی مثل مدیریت پروژه خیلی خوبن، کسایی هستند که معمولا میتونن بین تیمها مشترک باشند و آدمهای ارزشمندی هستند.<br />
در برابر اینا برنامهنویسای I شکل یه خط دارند، معمولا اینا آدمهایی هستند که توی یه زبون خیلی خیلی عمیق میشن. اینا آدمهای کار راه اندازی هستند، یعنی کسایی هستند که وقتی هیشکی نمیتونه یه چیزی رو درست بکنه، اینا میان درست میکنن. سطح کاریشون هم خیلی بالاست و گرون قیمت هستند.<br />
اینکه شما کدوم یکی از اینا بشی دست خودت هست، انتخاب خودت هست چه مدلی پیشرفت بکنی. توی همهی شرکتها به جفتشون نیاز هست. بعضی وقتا واقعا پیش میاد آدم از کاری که میکنه حوصلش سر میره، نیاز داره یه چیز جدیدتری رو امتحان کنه، مثلا شما وقتی دو - سه سال روی یه codebase کار کنی به همه چیزش تسلط داری. خب اون کدبیس چالش جدیدی برات ایجاد نمیکنه. خب اون موقع هست که شما یا باید بگی من از این شرکت برم به شرکت دیگه یا مثلا اگر شرکت امکانش رو داشته باشه بگه بیا برو توی یه تیم دیگه، برو یه زبان دیگه بنویس برو یه چیز دیگه یاد بگیر. چون این آدم آدم ارزشمندی برای شرکت هست، سه چهار سال دانش این آدم توی این شرکت بوده و خیلی حیف هست بذاریم بره. مثلا یا حقوقش رو بیشتر بکنن یا یه چیزی بهش میدن که توی شرکت بمونه. معمولا توی شرکتهای بزرگ سعی میکنن همچین امکانی رو به دولوپرها بدن که اگر بخوان بتونن یه چالش جدیدی داشته باشن برای انجام دادن. من بشخصه ترجیح میدم T شکل باشم.</p>
<h4 id="چطور-میشه-یه-تست-خوب-نوشت-اگر-کتابی-هست-معرفی-کن-اصن-یه-تست-خوب-به-چی-میگید">چطور میشه یه تست خوب نوشت؟ اگر کتابی هست معرفی کن؟ اصن یه تست خوب به چی میگید؟</h4>
<p>یه تست زمانی میتونه یه تست خوب باشه که فانکشنالیتی خوبی رو تست کنه، یعنی شما در درجه اول باید کدی بنویسید که تمیز باشه تا بتونید تست خوبی بنویسید. مثلا یکی از مباحثی که توی شرکت سعی میکنند بهش زیاد رفرنس بدن یا زیاد استفاده کنند میگن فانکشن شما تا حد ممکن (البته بعضی وقتا نمیشه) نباید side effect داشته باشه. فانکشن زمانی ساید افکت داره که به جز ورودی و خروجی که میگیره و داره، یه سری کارهای دیگه هم بکنه. کدی که ساید افکت داشته باشه تست نوشتن براش سخت هست. چون تست نوشتن برای ساید افکت سخته. چند وقت پیش Dan Lew یه مقاله خیلی خوبی نوشته بود در مورد اینکه testability چه جوریه و چه فانکشنالیتی ساید افکت داره و نداره و تست نوشتن برای اینا چه فرقی داره. ولی خلاصشو بخوام بگم اگر شما یه فانکشن خیلی ساده بنویسید که دو تا عدد رو بگیره با هم جمع کنه و خروجی رو برگردونه، تست نوشتن براش خیلی ساده هست ولی حالا اگر به همین فانکشن یه خط اضافه بشه که این دو تا عدد رو بگیره جمع کنه و برگردونه ولی یه پرینت هم بکنه یه چیزی هم توی لاگ کت بیرون بده این میشه ساید افکت این میشه یه فانکشنالیتی دیگه توی اون فانکشن که شما برای اینم باید تست بنویسید، معمولا وقتی pure logic فانکشنالیتون ساید افکت نداشته باشه هم کدتون تمیز تره و هم تست نوشتن براش خیلی کم دردسر تره.<br />
اینجا ممکنه یه کدی بنویسی، یه پول ریکوئستی بزنی، ولی پول ریکوئستت ممکنه مثلا سه چهار روز طول بکشه با مستر مرج بشه. چون آدمهای مختلف میان ریویو میکنن و بعضا در اکثر مواقع نظرات خیلی خوبی میدن. چون شما وقتی یه کدی رو مینویسی فقط از دیدگاه خودت نوشتی ولی وقتی چندنفر دیگه میان منتقد کد شما میشن ممکن هست یه سری دیدگاههایی رو به شما بدن که شما اون لحظه نداشتی و داشتی به چیزهای دیگه فکر میکردی باعث میشه کدی که مرج میشه توی مستر خیلی تر و تمیز باشه. اگر لول ساید افکت رو خیلی پایین نگه دارید یونیت تستهای خوبی میتونید بنویسید، البته Integration test و End-to-end test خیلی ربطی به تمیز بودن کد نداره. ولی این خلاصهی چیزی بود که من میتونستم بگم چطور تست بنویسیم. کتاب خاصی یادم نمیاد بذارید eBookهامو نگاه کنم بهتون میگم چیز خاصی خوندم یا نه. من بیشتر یادم میاد در مورد تست مقاله خوندم مثلا power mockito یا mockito رو مجبور شدم داکیومنتشو زیر و رو کنم. ولی اگر کتاب مناسب هم بهم رفرنس دادن یا خودم داشته باشم نگاه میکنم بهتون میگم.</p>
<h4 id="منظور-از-ساید-افکت-اینه-که-روی-ورودیها-تغییر-ایجاد-نشه">منظور از ساید افکت اینه که روی ورودیها تغییر ایجاد نشه؟</h4>
<p>کنار بحث ساید افکت و اینکه یه فانکشن باید فقط همون کاری که اسمش میگه رو انجام میده، این حرفی که میگی خیلی درسته. و معمولا آبجکتهایی که توی کلاس ساخته میشه (اینجکت میشه یا توسط کلاس دیگه به عنوان ورودی داده میشه) معمولا final هستند همشون، یعنی اکثر ورودیهایی که یه فانکشن داره یه انوتیشن final کنارش نوشته شده که اینا تغییر پذیر نباشن و وسط کار نتونید ورودی رو تغییر بدید که ساید افکت ایجاد بشه. معمولا اکثر مواقع بالای توابع notNull@ وجود داره که بگه خروجی که بهت میدم نال نیست. یعنی توی ران تایم میتونه خیالت راحت باشه و اگر مشکلی باشه من توی کامپایل تایم حل میکنم.</p>
<h4 id="امکانش-هست-حقوقتو-بگی-یا-اینکه-بگی-هزینه-زندگیت-اونجا-چقدر-هست">امکانش هست حقوقتو بگی یا اینکه بگی هزینه زندگیت اونجا چقدر هست؟</h4>
<p>خب این سوال واقعا خیلی مرتبط با اندروید و توسعهی نرمافزار نیس و بحث حقوق یه مقدار شخصی هست. اگر یکی دوست داشته باشه منابع آنلاین زیادی هستند که داخلش بتونید متوسط حقوق برنامهنویسا یا هزینهی زندگی رو پیدا کنید. خیلی پیدا کردنش کار سختی نیست. فقط من یه نکته بگم اگر کسی مثلا علاقه داره که بره خارج از ایران کار یا زندگی بکنه. این تصمیم تمام ابعاد زندگیش رو تحت تاثیر قرار میده و تصمیمی نیست که فقط بحث کاری باشه. اصلا بهش به شکل بحث کاری نگاه نکنید.</p>
<h4 id="اگر-ممکنه-در-مورد-بخشهای-دیگه-هم-از-لحاظ-فنی-بگو">اگر ممکنه در مورد بخشهای دیگه هم از لحاظ فنی بگو؟</h4>
<p>خب اینو کوتاه میگم، چون اگر قرار باشه همه بحثهای فنی اسپاتیفای رو بگم باید چند روز توضیح بدم. چیزی که من میدونم اینه که درصد خیلی زیادی از بکاند ما با جاوا نوشته شده و از این به بعد هر چیزی هم قرار باشه نوشته بشه با جاوا نوشته میشه. این تصمیم رو سطوح بالا شرکت گرفتند و علتش هزینه نگهداری کد و اینجور چیزاس. به غیر از بخش کوچیکی که با پایتون، سی پلاس پلاس و گو نوشته شده و متناسب با نیازش تصمیم گرفته شده که زبون دیگهای استفاده بشه. به همین دلیل معمولا اندروید انجینیرها رو خیلی تشویق میکنند اگر دوست دارند بکاند یاد بگیرند و بکاند هم بزنن. برای اینکه خیلی کار سختی نیست ماها که جاوا بلدیم، بیایم best practiceهای زبان رو بخونیم، یکی دو تا کورس ببینیم و یکی دو تا کتاب بخونیم تا کد بزنیم. و حتی بعد یه مدت به اصطلاح تاثیر گذار کد بزنیم.<br />
ترجیح میدم بیشتر از این در مورد چیزهای فنی بخشهای دیگه نگم،چون خودمم اطلاع ندارم.</p>
<h4 id="اونجا-چه-کتابهایی-برای-خوندن-توصیه-میشه">اونجا چه کتابهایی برای خوندن توصیه میشه؟</h4>
<p>از کتابهایی که اینجا روش تاکید میشه کتابهای Martin Fowler هست که اگر اشتباه نکنم یکیش مثلا Enterprise architecture هست، کتاب Effective Java و کتاب Clean Code هم جزء کتابهایی هستند که توی شرکت بهشون زیاد رفرنس داده میشه. چندتا کتاب دیگه هم هست که اسماشون الان در خاطرم نیست.</p>
<h4 id="شرایط-و-محیط-کار-چطوره-چه-امکاناتی-دارید">شرایط و محیط کار چطوره؟ چه امکاناتی دارید؟</h4>
<p>ساعت ورود و خروج به شرکت به اون صورت نداریم. تنها مسالهای که وجود داره بین تیمهای مختلف قرارداد میشه که صبح چه ساعتی stand up meeting داشته باشن.<br />
یکی از خوبیا شرکت اینه خیلی انعطافپذیر هست که از خونه کار کنی یا داخل شرکت کار کنی، البته تا زمانی که ثابت کرده باشی داخل خونه کار کردنتم به شرکت ضرر نمیزنه. در واقع این بصورت کلی مدل کاریمون و رفت و آمدمون هست: ساعت نداریم هر موقع میخوایم میتونیم بریم و بیایم ولی آدمها هم سعی میکنند واقعا متعهد به کار باشند.<br />
بحث امکانات هم مثل شرکتهای خوب هست، مثلا در رابطه با غذا به حساب شرکت میتونی غذا بخوری یا اتاق بازی یا از اینجور چیزا داریم. البته میگم اینا بحثهای فرعی هست و خیلی ربطی به توسعهی نرمافزار نداره.</p>
<h4 id="شرکت-و-محیط-کار-چطور-هست">شرکت و محیط کار چطور هست؟</h4>
<p>دفترمون اخیرا عوض شد اومدیم یه دفتر جدید. شرکت تو استکهلم شعبههای مختلف داشت همشون هم برنامهنویسی نبودند، یه دفتر جدید ساختند ۱۲ طبقه وسط شهر و خیلی خیلی ساختمون تحسین برانگیزی هست. اون دفتر قبلی هم که من از اینجا رفتم توش جا خوردم، این دفتر جدید هم که رفتیم توش قشنگ یه دور دیگه جا خوردیم. خیلی خیلی خوب درآوردند علتش هم اینه که پروداکتیویتی آدمها خیلی براشون مهمه، بینهایت برای این که شما احساس راحتی بکنید هزینه میکنند. هزینههایی که شاید به چشم هم نیاد ولی وقتی میشنوی تعجب میکنی. طبقه ۱۲ کلا کافه تریا هست و خیلی بزرگ. چندتا گیمینگ روم داره، پینگ پونگ، بیلیارد، یخچال پر غذا، اتاق ماساژ، اتاق VR، اتاق کاردستی که لوازم تحریر و خیاطی توش هست برای ساختن مثلا یه چیز فیزیکی، به درد اجایل کوچها میخوره. هر طبقه برای خودش آشپزخونه داره، محیط کار جدا هست، یه چیزی که خیلی به درد میخوره میزایی هست که حالت ایستاده میشند، بغلش ۲ تا دکمه داره میاد بالا و میره پایین. معمولا بعد از اینکه نهار میخورند همه سنگین میشند ۱-۲ ساعت ایستاده کار میکنند و اصلا حالت خواب آلودگی برات پیش نمیاد، به نظرم اینجا هم با هزینه معقول میشه انجام داد و برداشت خیلی خوبی کرد از نیروها. چون نهار که میخوری چایی یا قهوه اونقدر تاثیر نداره ولی وقتی ایستاده کار میکنی قشنگ خون تو بدنت میچرخه و حالت خواب آلودگی تقریبا صفر میشه.</p>
<p><img src="https://i.ibb.co/qnqCfb8/urban-escape1.jpg" alt="" /></p>
<h4 id="یه-جا-کار-میکردیم-بعد-از-نهار-نیم-ساعت-خواب-اجباری-بود-تا-سر-حال-شی">یه جا کار میکردیم بعد از نهار نیم ساعت خواب اجباری بود تا سر حال شی.</h4>
<p>ایده خوبی زده بوده.<br />
پروداکتیویتی براشون خیلی مهم هست معیار کار آدما اون ارزش آفرینی هست که میکنند نه اون ساعت کاری. ساعت کار کلا وجود نداره، ولی محیط کاری که ایجاد میکنند خیلی حس تعلق ایجاد میکنه و آدم خیلی با جون دل تو شرکت کار میکنه، حتی خیلی وقتها اضافه بر زمانی که باید بمونه میمونه چون جای با حالی هست برای کار کردن. مثلا تا ساعت ۷ شب کار میکنی میری یه دست PS میزنی، یه شام بیرون میخوری دوباره یه چیزی به ذهنت میاد میای تو شرکت. این محیط فرهنگی که تو شرکتها ایجاد کردند خیلی قابل تحسین هست و گرنه همه جا آدم با استعداد و پشتکار هست ولی اگر بتونی از این آدما بهره وری بکنی هنر مدیریتی هست که اونور وجود داره.</p>
<h4 id="چه-اپهایی-دارید">چه اپهایی دارید؟</h4>
<p>بطور کلی اسپاتیفای ۶ تا اپ مختلف داره که از این ۶ تا ۴ تاش اپ اصلی اسپاتیفای هست. یه مفهوم جالبتری که توی اسپاتیفای وجود داره وقتی شما کاربر رایگان اسپاتیفای هستید از یه اپ استفاده میکنید و وقتی پریمیموم میشید از یه اپ دیگه استفاده میکنید. البته به چشم یوزر این چیز متفاوتی نیست همه چیز داخل یه اپ هست ولی داخل اپ دو تا پروژهی مختلف وجود داره که شما وقتی پرمیموم میشید بین این دو تا سوییچ میشید. و اتفاق جالبیه، مراحل اینکه از یه پروژه میرید به یه پروژه، داخل کد بیس بامزه هست. ممکنه یه سری از این اپهارو دیده باشید. مثلا یه اپ دیگه داریم به اسم اسپاتیفای زیرو که برای کشورهایی هست که یه مقدار سرعت اینترنتشون پایینه یا گوشیهای ضعیفتری دارند مثل هند پاکستان و یه سری کشورهای آفریقایی، یه اپ دولوپ شده فقط برای اون کشورها که خیلی resource efficient هست، مدل برنامهنویسیش فرق داره و ابزارهایی که استفاده میکنند فرق داره. درکل یه سری اپهای دیگه هم هست.</p>
<h4 id="job-title-شما-چیه">job title شما چیه؟</h4>
<p>Software engineer</p>
<h4 id="چه-جاب-تایتلهای-مختلفی-دارید">چه جاب تایتلهای مختلفی دارید؟</h4>
<p>برمیگرده به فرهنگ شرکتها، تو شرکت ما اگر engineer باشی همه Software engineer هستند هیچ فرقی بین lead, senior و … نیست. یه فریمورکی هست نه به معنای برنامهنویسی یه فریمورک هست که رو کاغذه، متناسب با تاثیرگذاریت تو شرکت یه step فارغ از این که چند سال تجربه داشته باشی، قبلا چه کارایی کردی بهت اساین میشه. وارد شرکت که میشی استپت همیشه یک هست، با استپ یک وارد میشی بعد از ۶ ماه دوباره چک میشه. استپ یک یعنی کسی که میتونه کارهای خودش رو هندل کنه و گیر نمیافته. استپ ۲ یعنی کسی که به اسکواد خودش داره کمک میکنه و ارزش آفرینی میکنه. استپ ۳ یعنی کسی که در لول ترایب داره کار میکنه. استپ ۴ یعنی برای کمپانی داره ارزش آفرینی میکنه، که استپ ۴ ما در کل شرکت ۲ یا ۳ تا داریم. یه انجینیر داریم خیلی قدیمیه حدود ۶۰ سالشه و فکر کنم یکی از کانتریبیوترهای اصلی rx java هم هست اون استپ ۳ هست. مفهوم سنیور و جونیور نداریم خیلی راحت میتونی با همه صحبت کنی و نظر همه رو به چالش بکشی.</p>
<h4 id="ایرانی-دیگه-هم-هست">ایرانی دیگه هم هست؟</h4>
<p>آره تو استکهلم ۳ نفر تو آمریکا هم هستند ولی همشون کسایی بودند که برای درس رفتند و بعد ویزای کار گرفتند.</p>
<h4 id="مدرک-تاثیر-داره">مدرک تاثیر داره؟</h4>
<p>مدرک تحصیلی تاثیر نداره البته نه که نداشته باشه مثلا اگر علوم انسانی خونده باشی ممکنه یه مقدار به چالش بکشند ببینند چی بلدی، ولی مثلا برای گوگل خیلی مهم هست.</p>
<h4 id="چند-سال-سابقه-برنامه-نویسی-داری">چند سال سابقه برنامه نویسی داری؟</h4>
<p>از ۸۸ برنامه نویسی حرفهای کار میکردم از ۹۱ اندروید. اندروید دولوپر شدنم سر استارت اپ ویکند بود. قبل از اندروید هم اپ Symbian میزدم.</p>
<h4 id="زندگی-چطور-هست">زندگی چطور هست؟</h4>
<p>استکهلم یه مقدار زندگی کردن توش سخته یا باید با سرما و تاریکی خیلی مشکلی نداشته باشی یا اینکه اذیت میشی. جای خیلی قشنگی هست ولی چالشهای خودش رو داره مثلا خورشید ساعت ۸:۳۰ صبح طلوع میکنه ساعت ۳ هم غروب میکنه. ما مشکلی نداشتیم پوست کلفت بودیم ولی بعضیها نمیتونند تحمل کنند. هفته اول پاییز قشنگ احساس میکردیم. یهو هم روز کوتاه میشه هم ساعت هارو یه ساعت میکشند جلو، آخر هفته هم بود مونده بودیم خونه ۴ عصر هم خورشید غروب کرد تا شب بال بال میزدیم. معمولا آخر هفته حتما باید یه برنامه بچینی، تو خونه بمونی دپرس میشی.<br />
از اونور هم تو تابستون روز خیلی طولانیه، تا ساعت ۱۱:۳۰ شب آسمون روشن هست و ساعت ۳ هم دوباره خورشید طلوع میکنه، ۵ ساعت کلا شبه.</p>
<h4 id="همه-شرکتها-اینجوریند">همه شرکتها اینجوریند؟</h4>
<p>اسپاتیفای بخاطر کارهایی که میکنه خیلی تو چشم هست ولی شرکتهای دیگه هم کم و بیش اینجوری هستند. شاید زورشون نرسه دفتر به اون تجهیزات بخرند ولی مثلا هفتهای یه بار بریم بیرون شام مهمون شرکت. یا مثلا ماهی یه بار کل تیم بره اسکی رو یخ. یه شب هتل میگیرن کل تیم رو میبرند مهمونی و بزن برقص. سعی میکنند از آدمها استفاده حداکثری بکنند این چیزیه که اینجا هم انجام دادنش یه آدم خلاق میخواد.</p>
<h4 id="اون-بازیای-که-گفتی-رو-میتونی-توضیح-بدی">اون بازیای که گفتی رو میتونی توضیح بدی؟</h4>
<p>بازی هدفش این بود که زیاد کار کردن رو در برابر درست کار کردن نشون بده. آدمها تقسیم شدند به تیمها مختلف ۳ یا ۴ نفره. به هر تیم ۱۰۰ تا توپ پینگ پنگ دادن تیمی که میتونست بیشترین تعداد توپ رو بزاره تو ظرف برنده میشد. منتهی یه سری قانون داشت مثلا یه توپ باید بین تمام اعضای تیم به گردش در بیاد بعد بره تو سبد، یک نفر در لحظه بیشتر از یه توپ نمیتونه برداره، توپها با قاشق باید برداشته میشد و …. شما میتونستید خیلی سریع کار کنید یا باهوش کار کنید و یه فرمولی پیدا کنید که از بقیه تیمها سریعتر توپها رو بزارید تو ظرف. در واقع خلاقیت آدمها رو به چالش میکشیدند. تیمی هم که برنده میشد راه حلش رو به اشتراک میذاشت. مهم این بود که به آدمها بفهمونند با سریعتر کار کردن یا استرس ممکنه به نتیجه نرسی، اگر قبلش فکر کنید ممکنه بهتر به نتیجه برسید. یه سری بازی اینطوری بود که هزینش فقط خوندن یه کتاب اجایل کوچ و ۴۰۰ تا توپ پینگ پنگ بود.<br />
اونجا این شکلیه که یه بخشی از فرایند آنبردینگ با اجایل کوچ جلسه داری و از دیدگاههای مختلف آموزش میدن، از دیدگاه فنی، از دیدگاه اجایل کوچ، از دیدگاه تیملید، از جنبههای مختف سعی میکنند آدم رو جا بندازن و بگند چه انتظاری از جنبههای مختلف از فرد میره. یکی از کارهای مهمی که اجایل کوچها انجام میدند بررسی سلامت تیم از نگاه تیم بودن هست مثلا اگر بعد از مدتی بچهها صبحها جلسه رو نمیان یا جلسه به جای ۱۰ دقیقه ۴۵ دقیقه طول میکشه اینا coordination انجام میدن، آدمها رو سر جای خودشون نگه میدارن جوری که استفاده حداکثری ازشون بشه. مثلا تو رترواسپکتیو چک میکنند به کارهای اسپرینت رسیدیم یا نه؟ یا در مجموع تو ۲ هفته گذشته خوشحال بودید یا نه؟ راضی بودید از کار کردن یا نه؟ یا میگند دو هفته گذشته خودتون رو در قالب یه حیون بکشید، مثلا لاک پشت ۲ هفته گذشته خیلی کند بودیم؛ خرچنگ انگار چندتا دست داشتم و کلی کار مختلف میکردم. یه جورایی با خلاقیت کمک میکنند محیط کار رو بهتر بکنند چطوری میتونیم بهتر کار بکنیم چه عاملایی حذف و اضافه شه اجایل کوچها بخش عمدهای از کارشون کوردینیشن آدمهاست.</p>
<h4 id="چه-ابزارهایی-استفاده-میکنید">چه ابزارهایی استفاده میکنید؟</h4>
<p>تمام شرکت رو slack هست تیمای مختلف کانال مختلف دارن خیلی کم از stack overflow و … استفاده میکنیم چون سعی میکنیم با هم صحبت کنیم، تیمها کانالای مختلف دارند مثلا rxJava unit test Android و … کانال مخصوص خودش رو داره و اکثر سوالها اون تو پرسیده میشه. ارتباط اصلی شرکت معمولا رو ایمیل هست. شرکت یه اپ پرایویت فیسبوک رو خریده https://spotify.facebook.com سوشال نتورک شرکت هست مثلا بخوایم یه gif بزاریم یا این جور چیزا. تیم ما از جیرا استفاده میکنند ولی تیمهایی هست که از ترلو و … استفاده میکنند. جیرا هم کلی کاستومایز شده معمولا اجایل کوچها این کار رو میکنند. یه باتی داریم که معمولا pr سامبیت میشه میاد تستهای مختلف روش اجرا میکنه. jenkins نیست، فکر کنم خودشون نوشتند. داکیومنتها رو گوگل درایو هست، Confluence داریم ولی من از گوگل درایو استفاده میکنم. یه معماری مبتنی بر Redux داریم که یه خورده دستکاریش کردن برای جاهایی که Event base هست. کلا قرار نیست بریم رو Kotlin چون تمام ریسورسهایی که میخوایم بیشتر و پختهتر رو جاوا هست. برنامه نویسهای اندروید و بکاند رو هم شیفت میدند که فول استک بشند تا جایی که میتونند، چون مایکرو سرویسها هم رو جاوا هست راحتتره. (من از quarter قبل شروع کردم بکاند بزنم و احتمالا کوارتر بعد بیشتر بکاند میزنم.) در نتیجه کاتلین با قاطعیت رد شد هیچ کس نمیخواست بره سراغش ولی شرکتهایی هستند که رفتند خوشحال هم هستند. Hangouts خیلی زیاد استفاده میشه همه جلسات و ارتباطات با هنگوات هست. گوگل کلندر خیلی زیاد استفاده میشه و خیلی جدی گرفته میشه.</p>
<h4 id="یه-جا-گفتی-رو-کلاودیم-دیتا-سنتر-داریم-یا--بیشتر-بگو">یه جا گفتی رو کلاودیم دیتا سنتر داریم یا … بیشتر بگو</h4>
<p>اسپاتیفای الان یه دونه دیتا سنتر تو لندن داره قبلا بیشتر بود تو اروپا آمریکا و … بعد دیدن هزینه نگهداریش خیلی زیاده و ما زاتا یه شرکت موسیقی هستیم و نمیخوایم به اون سمت بریم و درگیر اون لول از نگهداری بشیم. مثلا تجهیزات سخت افزاری داشته باشیم و رفتیم رو گوگل کلاود و خیلی هم به نفعمون شد. یه دونه تو لندن هست به خاطر یه سری مشکلات با گوگل کلاود که قرار هست اونم تو ۳ ماه آینده کلا خاموشش کنند.</p>
<h4 id="اونجا-که-گفتی-بعد-از-اینکه-وارد-اپ-میشی-کلا-۲-قسمت-میشه-رو-میشه-توضیح-بدی">اونجا که گفتی بعد از اینکه وارد اپ میشی کلا ۲ قسمت میشه رو میشه توضیح بدی</h4>
<p>وقتی وارد اپ میشی ۲ تا چیز قبل از لود شدن هر کدی فچ میشه یکی user policy که تا وقتی نیاد شما اون پراگرس بار رو میبینی حتی اگر اطلاعات صفحه هوم اومده باشه یه چیز دیگه داریم به اسم aba که فریم ورک a/b test هست و یه سری configuration میفرسته. مثلا ممکنه قرار باشه ۴ تا تب تو نویگیشن داشته باشی جای ۵ تا، ممکنه اون توی aba باشه ولی به aba معمولا ۰.۷ ثانیه فرصت میدیم اگر از سمت بکند اومد که اومد اگر نیومد با یوزر پالیسی میریم جلو. بسته به این که کدوم یکی برای شما بیاد یه کلاسهایی لود میشه به صورت داینامیک که اون تصمیم میگیره بری تو اپ فعلی یا بری توی اپ قدیمی. برای من خیلی جالب بود که پکیجهایی که داری انتخاب میکنی متناسب با چیزی که ران تایم هست انتخاب بشه، یعنی الان من این پکیج رو لود کنم یا این یکی رو. مثلا وقتی بخوای core برنامه رو راه بندازی که با ndk کامپایل شده و شما فقط باید run کنیش بسته به این که چه پکیجی رو داری چیز متفاوتی برات لود میشه</p>
<h4 id="حجم-اپ-چقدر-هست">حجم اپ چقدر هست؟</h4>
<p>فکر کنم ۴۰ مگ یا همچین چیزی ولی برای کشورهایی که نت داغونی دارن یه اپ دیگه نوشته شد به اسم اسپاتیفای تاینی و همه چیزش فرق داره هیچ چیش با اپ ما یکی نیست. کلا ۲ مگ حجم هست. فقط رندر میکنه چون هیچ لاجیکی توش وجود نداره. از لحاظ ظاهری تقریباً مو نمیزنه با اپ فعلی خیلی شبیه ولی یه تیم دیگه نوشته و یه اده آدمند که تخصصشون فقط تو بهینه سازی، کم کردن حجم کد و … هست در این حد که تو apk حتی یه دونه کلاس اضافه نره. من کدوشون رو کم دیدم ولی اصلا استانداردهای کارشون فرق داره و یه جور دیگه کد میزنند و من از کاری که میکنند سر در نمیارم.</p>
<h4 id="اپ-خودتون-انگار-۱۸-مگه">اپ خودتون انگار ۱۸ مگه</h4>
<p>اپ دیباگمون ۴۰ مگ هست. این اسپاتیفای تاینی هست. ایمیج میدونم اصلا استفاده نشده از فونت استفاده کردند، انیمیشن نداره حجمش کم شده زمان لود شدن ویوها خیلی اومده پایین و…</p>
<h4 id="یه-اپ-اندروید-اسپاتیفای-هست-که-آیکونش-سبز-کمرنگ-هست-و-بلافاصله-میگه-این-یکی-رو-نصب-کن-داستانش-چیه">یه اپ اندروید اسپاتیفای هست که آیکونش سبز کمرنگ هست و بلافاصله میگه این یکی رو نصب کن، داستانش چیه؟</h4>
<p>یه اتفاق چند سال پیش رخ داده بود که بهش میگند insedence (اتفاق) یکی یه ایمیلی فرستاده بود و ایمیلش یه چیزی شبیه [email protected] بوده که ceo شرکت هست و گفته بچهها این رو براتون میفرستم تستش کنید. یه لینکی بوده با این لینک عملا کلی از اطلاعات شرکت رو دراورده، من دقیقا نمیدونم چه اتفاقی افتاده ولی مجبور شدند در عرض یه هفته کل پکیج برنامه رو عوض کردند برای اینکه طرف دسترسی نداشته باشه به اونجا. ممکنه key store و پسورد رو در آورده باشه.</p>
<h4 id="دیتابیستون-چیه">دیتابیستون چیه؟</h4>
<p>نمیدونم چون ما از یه apiای استفاده میکنیم که یه تیم دیگه داره maintain میکنه. ولی میدونم هم رو فایل سیستم مینویسیم هم یه دیتابیسی هست که نمیدونم چیه و هم بسته به کاری که بخوای ممکنه رو کلاود بنویسند. تنظیمات ستینگ میدونم مثلا رو کلاود هست. ما با یه سریع انوتیشن میگیم چی میخوایم مثلا این پرامری کی هست و … ولی نمیدونم اون پشت چیه<br />
بعضی تیمها هم هستند که اصلا فیچر ندارند مثلا android infrostrucher اون تیم فیچر نداره ریپازیتوری رو داره مین تین میکنه. مثلا یه تیم داریم client build ریلیز کردن با اون تیمه زمان بیلد اگر بره بالا اون تیم گزارش میده که چرا؟ اون تیم بود که گفت باید ماژولارایز کنیم کد بیس رو و اگر نه یه ۲ سال دیگه با همین سرعت بخوایم کد جنریت بکنیم ۲۰ دقیقه باید منتظر باشیم که گریدل دونه دونه سینک کنه.</p>
<h4 id="چندتا-تیم-دارید">چندتا تیم دارید؟</h4>
<p>اون ترایبی که ما کار میکنیم ۸ اسکواد مختلفه ولی کلا نمیدونم چندتا تیم داریم از اینا ۴ تاش تو استکهلمند ۴ تا تو گوتنبرگ</p>
<h4 id="چه-جوری-آپدیت-میدید">چه جوری آپدیت میدید؟</h4>
<p>هر هفته جمعه پوش میکنیم تو استور و هر هفته باید ریلیز کنیم. هر تیمی باید جمعه فیچرهای خودش رو ساین آف کنه، یعنی کدم رو تست کردم OK هست. یه داکیومنتی شیر میشه بین همه، تست میکنن اگر OK بود داکیومنت رو ساین میکنن بعد تیم ریلیز میفهمه همه چی OK هست.</p>
<p>آخر هفته ریلیز میکنید به باگ بخورید چی؟</p>
<p>یه تیمی داریم که on call هست و همیشه کار میکنه ولی اگر نتونی اپ خودت رو هم تست کنی خیلی اوضاع خرابه دیگه</p>
<h4 id="مثلا-تست-میکنی-ردیفه-ولی-ریلیز-که-میکنی-میبینی-۲-درصد-کرش-داره-مثلا-firebase-رو-آپدیت-کردم-این-به-کرش-میخوره">مثلا تست میکنی ردیفه ولی ریلیز که میکنی میبینی ۲ درصد کرش داره مثلا Firebase رو آپدیت کردم این به کرش میخوره</h4>
<p>این اتفاق نباید رخ بده</p>
<h4 id="برا-شما-نباید-برای-ما-میشه--">برا شما نباید برای ما میشه : )</h4>
<p>وقتی آپدیت میدید relese note چیه؟ باگ فیکسه یا فیچر هدف داریه</p>
<p>تیمی که داره ریلیز میکنه اصلا براش مهم نیست که شما چی داری ریلیز میکنی متنی هم که زیر آپدیتها هست همش ثابته امیدواریم از این تجربه اسپاتیفای لذت ببرید و … در نتیجه شما باید همواره هر باگی هست فیکس بکنید چون برای هفته بعد میره بالا. ۲ تا ویدیو هم داده بود قبلا که چطور کار میکنند اسپاتیفای کالچر یا همچین چیزی تو vimeo دیده بودم.(https://vimeo.com/85490944) تو اون میگه از نظر اسپاتیفای ریلیز کردن مثل یه قطار هست اگر به این رسیدی، رسیدی اگر نرسیدی باید صبر کنی با قطار بعدی، تو این کوارتر هم قرار هست ریلیز هر ۳ روز یکبار بشه و قرار هست تو ۲۰۱۸ به هر روز ریلیز و هر کامیت قابل ریلیز کردن بشه حتی اگر ریلیز ندیم.</p>
<p>این سیاست منطقش چیه؟</p>
<p>اول که اونجا مشکل محدودیت حجم اینترنت و … نداریم که به چشم بیاد. ولی از لحاظ کیفی میخوان به اونجا برسن که هرچی میذاری رو ریپازیتوریت انقدر خوب باشه که بشه ریلیز کرد. الان استاندارد شرکت بالاست یعنی هر چیزی بزاری بالا تو یه هفته میتونی مطمئن باشی که میشه ریلیزش کرد ولی میخوان به جایی برسند که هرچی میذاری همون لحظه اگر بره دست ۳۰۰ میلیون کاربر بدون مشکل کار بکنه cd هست دیگه.</p>
<p>الان چندتا لایه کلی دارید توی کدتون؟ که فولی ماژولند؟</p>
<p>اگه بخوام کلی بگم مثلا صفحه براوز رو کلا یه ماژولش کردیم تو کد بیس اصلی بود کنار بقیه فرگمنتها ولی چون داشتیم از اول مینوشتیمش یه ماژولش کردیم همه فرگمنت لاجیک و تست رفت توش، فیچرها مثلا ماژول شدن، Search, Home, Your Library, Core</p>
<p>بعد توی اون دوباره خودش ماژولارایز نیست؟</p>
<p>نه پکیج بندی کردی ولی یه ماژول هست دیگه اگر circular dependency به وجود بیاد باید بریم اون یکی رو هم ماژولارایز کنیم. کسی که ماژولارایز میکنه باید دیپندنسی رو هم خودش solve بکنه مگر اینکه بخوای پلیر کل برنامه رو ماژولارایز بکنی که باید یه تیم براش بزاری.</p>
<h4 id="شده-کسی-اخراج-بشه-دلیلش-چی-بوده">شده کسی اخراج بشه؟ دلیلش چی بوده؟</h4>
<p>تا حالا ندیدیم ولی شاید به خاطر مسائل اخلاقی و اینها کسی اخراج بشه، پروسه استخدام از لحاظ فنی انقدری خوب هست که پیش نیاد.</p>
<h4 id="پاداش-یا-جریمه-دارید">پاداش یا جریمه دارید؟</h4>
<p>کسی رو تا الان ندیدم جریمه بکنن، محیط و آدمهای شرکتخیلی حرفهایتر از این حرفها هست که جریمه و کسر از حقوق و اینها داشته باشیم، نهایتا کسی ناراضی باشه با شرکت خداحافظی میکنه، پروموشن هم برای Exceeding Expectation هست. یعنی از خواستهها و مسئولیتهات فراتر عمل کنی. یه مقدار روی حقوق هست.</p>
<h4 id="stepها-رو-کی-تعیین-میکنه">stepها رو کی تعیین میکنه؟</h4>
<p>یه فریمورک هست که مطابق با اون بهت یه درجهی ارشدیت داده میشه و برای اینکه درجه بالاتری بگیری باید یه سری تاثیرات رفتاری و تکنیکی از خودت نشون بدی</p>
<h4 id="چه-third-partyهایی-استفاده-میکنید">چه third partyهایی استفاده میکنید؟</h4>
<p>مطمئن نیستم لیست کاملش چیه، ولی مثلا رتروفیت، okhttp Stetho</p>
<h4 id="مگه-نتورک-تو-core-نبود">مگه نتورک تو core نبود؟</h4>
<p>یه سری چیزهارو داریم دیپریکیت میکنیم، میریم روی okhttp و gRPC</p>
<h4 id="جالب-بود-که-کد-رو-تونستی-بهمون-نشون-بدی-تو-شرکت-مکانیزمی-هست-از-دزدیدن-کد-جلوگیری-کنه-مثلا-دسترسی-بسته-شه-یا-">جالب بود که کد رو تونستی بهمون نشون بدی، تو شرکت مکانیزمی هست از دزدیدن کد جلوگیری کنه؟ مثلا دسترسی بسته شه یا …</h4>
<p>اعتماد، اگر بهم اعتماد نداریم دلیلی برای کار باهم وجود نداره! و صد البته یه سری بند و قانون هم تو قرارداد هست</p>
<p>با تشکر از آرش عباس و بهداد در تکمیل این مطلب</p></content><author><name>behdad</name></author><category term="spotify" /><category term="اسپاتیفای" /><summary type="html">خوندن صحبت کسایی که توی شرکتهای بزرگ دنیا کار کردند به ما کمک میکنه که بدونیم ساز و کار این شرکتها چطوریه، بر اساس چه اصولی مدیریت میشن و پروژههاشون رو چطوری جلو میبرند. از اینجور مصاحبهها تو اینترنت پیدا میشه ولی این یکی فرق داره؛ چون صحبتهای یه ایرانی هست که مدتها تو ایران بوده و علاوه بر موارد بالا، در مورد نحوهی مهاجرت و تفاوتهای اونجا با ایران هم صحبت کرده. پیشنهاد میکنم صحبتهای آرش رو که خیلی با دقت گفته شده و جزئیات زیادی از شرکت اسپاتیفای داره رو بخونید.</summary></entry><entry><title type="html">با alias سریعتر کد بزنید!</title><link href="http://pullrequest.ir/%D8%A8%D8%A7-alias-%D8%B3%D8%B1%DB%8C%D8%B9-%D8%AA%D8%B1-%DA%A9%D8%AF-%D8%A8%D8%B2%D9%86%DB%8C%D8%AF!/" rel="alternate" type="text/html" title="با alias سریعتر کد بزنید!" /><published>2018-10-31T00:00:00+00:00</published><updated>2018-10-31T00:00:00+00:00</updated><id>http://pullrequest.ir/%D8%A8%D8%A7-alias-%D8%B3%D8%B1%DB%8C%D8%B9%E2%80%8C%D8%AA%D8%B1-%DA%A9%D8%AF-%D8%A8%D8%B2%D9%86%DB%8C%D8%AF!</id><content type="html" xml:base="http://pullrequest.ir/%D8%A8%D8%A7-alias-%D8%B3%D8%B1%DB%8C%D8%B9-%D8%AA%D8%B1-%DA%A9%D8%AF-%D8%A8%D8%B2%D9%86%DB%8C%D8%AF!/"><p>دستورات سریع لینوکسی برای برنامهنویسها</p>
<h1 id="مقدمه">مقدمه</h1>
<p>البته که دوست دارم یه متن بلند بنویسم! اما همزمان که دارم این مطلب رو مینویسم، دارم روی یه مطلب (چند نسخهای) کار میکنم در بارهی برنامهنویسی وب. مثل همیشه، از صفر تا صدش، برای اونایی که تا حالا حتی برنامهنویسی هم نکردن! کار عجیبیه، کلی چیز باید بخونم و انجام بدم و یاد بگیرم. بگذریم…</p>
<p>این مطلب من، قرار نیست خیلی طولانی باشه و پیشبینی میکنم که به مرور بروز رسانی بشه. داستانش هم از این قراره که، من علاقه ندارم کدها رو چندبار بنویسم. مد نظرم اینه که یه سری «کلید» برای خودم داشته باشم و جاهای مختلف ازشون استفاده کنم.</p>
<h1 id="لینوکس">لینوکس</h1>
<p>لینوکس یه هستهی سیستمعامله. یعنی دستورات و فرایندهایی که یه سیستمعامل نیاز داره رو براش فراهم میکنه و یه راه ارتباطی بین سختافزار و سیستمعامله. ضمنا، لینوکس متن بازه، یعنی میشه هرچیزی رو توش تغییر داد و شخصیسازی کرد.</p>
<p>سیستمعاملهای زیادی هم وجود دارن که مبتنی بر لینوکس هستن، یعنی، از هستهی لینوکس استفاده میکنن و یه جورایی «توزیعی» یا Distributionای از لینوکس هستن (بین کاربرهای لینوکسی، به Distro هم معروفن). <a href="https://goo.gl/vVJpgK">من اینجا سعی کردم در مورد سیستمعاملهای لینوکس بیشتر توضیح بدم.</a></p>
<h1 id="شِل-یا-shell">شِل یا Shell</h1>
<p>خیلی ساده، شِل یا «تِرمینال» یه برنامه هست که دستورات رو از کاربر میگیره و اونا رو به سیستمعامل و در نهایت خروجی رو نمایش میده. شِلِ لینوکس یکی از مهمترین اجزای لینوکس به حساب میاد و یکی از محیطهای مورد علاقهی برنامهنویسهاست.</p>
<p><img src="https://files.virgool.io/upload/users/3181/posts/dxfys8enofv3/6inx1hftqjn6.png" alt="" /></p>
<p>اینجا من تصمیم دارم که روی یه سری از اصول این نرمافزار کار کنم و در نهایت یه سری از دستورات به درد بخور که خودمم استفاده میکنم رو بگم. ضمنا، اگر شما هم دستوراتی رو دارید، بهم بگید که اینجا آپدیت کنم.</p>
<p>برای باز کردن نرمافزار تِرمینال، میتونید توی سیستمعامل لینوکسی دکمهی Ctrl + Alt + T رو بزنید، یا دکمهی CMD + Space رو توی سیستمعامل مک بزنید و دنبال Terminal بگردید.</p>
<h1 id="دستورات-پایه">دستورات پایه</h1>
<p>این دستورات رو بدون علامت $ اجرا کنید. $ یک نشانست و به این معنیه که دستور داره با مجوز یک «کاربر» و نه یک «مدیر» اجرا میشه. نشانهی یک مدیر، علامت # هست.</p>
<h2 id="۱pwd">۱. pwd</h2>
<p>این دستور به شما آدرس جایی که توش هستید رو میگه. وقتی ترمینال باز میشه، معمولا از پوشهی Home شروع به کار میکنه. ضمنا، این آدرسها Absolute هستن، یعنی از پوشهی ریشه یا Root شروع میشن.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ pwd
/home/aien
</code></pre></div></div>
<h2 id="۲ls">۲. ls</h2>
<p>این دستور به شما محتویات پوشهای که توش هستید رو میگه. اگر به آخرش <code class="highlighter-rouge">-a</code> هم اضافه کنید، میتونید فایلهای مخفی رو هم ببینید.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ls -a
. Downloads .gtk-bookmarks .node-gyp .rdm .vscode
.. .dropbox .gtkrc-2.0 .npm .rediscli\_history Web
...
</code></pre></div></div>
<h2 id="۳-cd">۳. cd</h2>
<p>این دستور به شما این امکان رو میده که جای خودتون رو عوض کنید. مثلا از پوشهای که توش هستید، برید به یه پوشهی دیگه.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ pwd
/home/aien/
$ cd /home/aien/Bilder
$ pwd
/home/aien/Bilder
</code></pre></div></div>
<h2 id="۴mkdir-و-rmdir">۴. mkdir و rmdir</h2>
<p>این دستور به شما آدرس جایی که توش هستید رو میگه. وقتی ترمینال باز میشه، معمولا از پوشهی Home شروع به کار میکنه. ضمنا، این آدرسها Absolute هستن، یعنی از پوشهی ریشه یا Root شروع میشن.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir sample
$ cd sample
$ pwd
/home/aien/Bolder/sample
$ cd ..
$ pwd
/home/aien/Bilder
$ rmdir sample
$ ls
...
</code></pre></div></div>
<h2 id="۵touch">۵. touch</h2>
<p>این دستور به شما امکان ساخت فایلها رو میده.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ touch file.txt
$ ls
...
file.txt
...
</code></pre></div></div>
<h2 id="۶rm">۶. rm</h2>
<p>این دستور به شما امکان حذف فایلها و تو بعضی شرایط، فولدرها رو میده.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ rm file.txt
</code></pre></div></div>
<h2 id="۷cp">۷. cp</h2>
<p>این دستور به شما امکان کپی کردن فایلها رو میده. این دستور، دوتا ورودی دریافت میکنه، اولی آدرس جایی هست که فایل قرار داره و دومی آدرس جایی هست که فایل باید اونجا بره.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ touch file.txt
$ pwd
/home/aien/Bilder
$ cp ./file.txt /home/aien/Musik
$ cd /home/aien/Musik
$ pwd
/home/aien/Musik
$ ls
...
file.txt
...
</code></pre></div></div>
<h2 id="۸mv">۸. mv</h2>
<p>این دستور به شما امکان جابهجا کردن فایلها رو میده و مثل دستور کپی عمل میکنه.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ pwd
/home/aien/Musik
$ mv file.txt /home/aien/Videos
$ ls
...
...
$ cd ../Videos
$ pwd
/home/aien/Videos
$ ls
...
file.txt
...
</code></pre></div></div>
<h2 id="۹rm">۹. rm</h2>
<p>این دستور به شما امکان حذف فایلها و تو بعضی شرایط، فولدرها رو میده.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ rm file.txt
</code></pre></div></div>
<h1 id="دستورات-حرفهایتر">دستورات حرفهایتر</h1>
<h2 id="۱nano">۱. nano</h2>
<p>این دستور به شما امکان نوشتن داخل یک فایل رو میده. اگر اون فایل وجود نداشته باشه، اون رو ایجاد میکنه. بعد از اینکه داخل فایل نوشتید، کافیه Ctrl + X رو بزنید، Y رو بزنید و از برنامه خارج بشید. نوشتهها ذخیره شدن!</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ nano file.txt
</code></pre></div></div>
<h2 id="۲cat">۲. cat</h2>
<p>این دستور به شما امکان نمایش محتوای یک فایل رو میده.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat file.txt
In yek file nemune ast!
</code></pre></div></div>
<h1 id="دستورalias">دستور alias</h1>
<p>دستور <code class="highlighter-rouge">alias</code> کمک میکنه تا دستور یا دستوراتی رو با اسامی دیگه صدا بزنیم و اجرا کنیم. شاید با خودتون بگید آخه چه کاربردی داره وقتی میتونم خودم دستور رو تایپ کنم؟</p>
<p>موضوع اینه که گاهی نیاز هست دستوراتی رو اجرا کنیم که نسبتا پیچیده هستن و فقط تو بعضی چیزهای کوچیک فرق میکنن.</p>
<p>برای شروع، دستور زیر رو تایپ کنید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ alias
</code></pre></div></div>
<p>یه لیست طولانی از دستورات رو خواهید گرفت:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-='cd -'
...
l='ls -lah'
...
serve='http-server -o -a localhost .'
which-command=whence
</code></pre></div></div>
<p>آخر این لیست، دستور هست که نوشته <code class="highlighter-rouge">l='ls -lah'</code>. اگر شما این دستور رو تو ترمینال بنویسید، یعنی بنویسید <code class="highlighter-rouge">l</code>، مثل این میمونه که به ترمینال گفتید دستور<code class="highlighter-rouge">ls -lah</code> رو اجرا کنه.</p>
<p>حالا برای نمونه، دستور زیر رو بزنید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ alias p="pwd"
</code></pre></div></div>
<p>از این به بعد اگر من دستور <code class="highlighter-rouge">p</code> رو بزنم، انگار دستور <code class="highlighter-rouge">pwd</code> رو زدم، پس آدرس جایی که هستم رو میگیرم:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ alias p="pwd"
$ p
/home/aien
</code></pre></div></div>
<p>حالا فرض کنید که توی سیستمتون، نرمافزار Apache رو داشتید. برای دستکاری فایل اصلیش، لازم بود که مثلا nano رو با کل آدرس اون فایل وارد کنید. چی میشد اگر مینوشتید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ alias a="nano /etc/httpd/conf/httpd.conf"
</code></pre></div></div>
<p>اونوقت به جای هربار تیاپ کردن دستور، فقط a رو اجرا میکردید و فایل رو دستکاری…</p>
<h2 id="چطور-دستورات-alias-رو-دائمی-کنیم">چطور دستورات alias رو دائمی کنیم</h2>
<p>اگر تو یه ترمینال، یه دستور <code class="highlighter-rouge">alias</code> رو وارد کنید، بعد از بستن اون ترمینال، دستورتون هم از بین میره و دفعهی بعدی دوباره باید دوباره تعریفش کنید. راهکارش اینه که از فایل <code class="highlighter-rouge">.bashrc</code> استفاده کنید. خیلی ساده، دستور زیر رو بزنید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ nano ~/.bashrc
</code></pre></div></div>
<p>این دستور، فایل <code class="highlighter-rouge">.bashrc</code> که توی پوشهی Home شما هست رو باز میکنه. حالا دستور زیر رو به بالای این فایل اضافه کنید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>alias p="pwd"
alias bashrc="nano ~/.bashrc"
...
</code></pre></div></div>
<p>با این کار، هربار که دستور p رو بزنید، به جاش دستور pwd اجرا میشه. برای حذفش هم، کافیه دوباره اون رو از فایلتون حذف کنید (دستور زیر رو تو ترمینال بزنید تا فایلش باز بشه).</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ bashrc
</code></pre></div></div>
<h1 id="دستورات-پر-کاربرد">دستورات پر کاربرد</h1>
<p>یه لیست از دستورات پر کاربرد هست که <a href="https://goo.gl/2Z5Wn5">توی سایت خودم گذاشتم. میتونید به اونجا سر بزنید و دستورات بروز شده رو ببینید.</a></p>
<p>موفق باشید</p></content><author><name>آیین سعیدی</name></author><category term="linux" /><category term="command-line" /><category term="cli" /><category term="alias" /><category term="bash" /><category term="script" /><category term="shell" /><summary type="html">دستورات سریع لینوکسی برای برنامهنویسها</summary></entry><entry><title type="html">داکر، داکر کامپز، کانتینرها و اتوماسیون</title><link href="http://pullrequest.ir/%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1-%D9%88-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%B3%DB%8C%D9%88%D9%86/" rel="alternate" type="text/html" title="داکر، داکر کامپز، کانتینرها و اتوماسیون" /><published>2018-07-22T00:00:00+00:00</published><updated>2018-07-22T00:00:00+00:00</updated><id>http://pullrequest.ir/%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1-%D9%88-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%B3%DB%8C%D9%88%D9%86</id><content type="html" xml:base="http://pullrequest.ir/%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1-%D9%88-%D8%A7%D8%AA%D9%88%D9%85%D8%A7%D8%B3%DB%8C%D9%88%D9%86/"><p>داکر چی هست؟ داکر کامپز چیکار میکنه و چجوری میتونیم پروژمون رو اتوماسیون کنیم؟</p>
<h1 id="داکر-کانتینر-و-اتوماسیون">داکر، کانتینر و اتوماسیون</h1>
<p><img src="https://files.virgool.io/upload/users/3181/posts/b1mi525hzvoe/1p7yoldghfgz.png" alt="" /></p>
<h1 id="مقدمه">مقدمه</h1>
<p>بالاخره بعد از یه مدت طولانی که از داون شدن سایتم میگذره، تونستم دوباره وصلش کنم و کانفیگای سمت سرور رو دوباره فیکس کنم. شاید جالب باشه ولی سرور من جای خلوتیه و چیز زیادی توش نیست و وبسایت خودم تنها برنامهایه که توش اجرا میشه، اما نکتهی جالب اینه که موقع دیپلوی باهاش خیلی مشکل دارم. بگذریم، همین مشکلات باعث شد که به نوشتن این مطلب فکر کنم و تا جایی که میتونم در مورد داکر توضیح بدم.</p>
<p>خواهش من مثل همیشه، انه که ان مطلب رو بخونید، ازش لذت ببرید و برای دوستاتون هم بفرستید و اگر جایی اشکالی دیدید، بهم خبر بدید. ضمنا، حقوق نویسنده رو هم فراموش نکنید و اگر جایی از این مطلب استفاده میکنید، اسم نویسنده اصلی (من، آیین) رو توش درج کنید.</p>
<p>سپاس</p>
<h1 id="داکر-docker-چی-هست">داکر (Docker) چی هست؟</h1>
<p>اول از همه، داکر اسم شرکتی هست که واژه کانتِینِر یا Container رو روانهی دنیای آیتی کرده. البته که قبلا هم از این واژه استفادههای گستردهای میشده، اما داکر باعث شده که واژه کانتِینِر معنی مشخصتر و دقیقتری پیدا کنه.</p>
<p>خود نرمافزار داکر، یه سرویس برای مدیریت کانتینرها یا Container Service Manager هست. کلیدواژههایی که میشه برای داکر استفاده کرد، <strong>توسعهدادن، دیپلوی کردن و اجرا کردن</strong> هستن. در واقع داکر هدفش اینه که وقتی برنامهنویسها، نرمافزاری رو مینویسن، اون رو به کانتینرها منتقل و به سادگی اون رو هر جایی اجرا کنن.</p>
<h2 id="پلتفرم-سَکو-کانتینر-چی-هست">پلتفرم (سَکو؟!) کانتینر چی هست؟</h2>
<p>پلتفرم کانتینر یا Container Platform یه سرویس کامل برای سازمانها و شرکتهاست که بتونن باهاش مشکلات مختلفی رو حل کنن. مهمترین ویژگی کانتینرها اینه که تمام نرمافزارهایی که برنامه لازم داره رو، توی خودشون نگهمیدارن. اما یکم در مورد کانتینرها عمیق بشم…</p>
<p>کانتینر یه پراسِس (Process) داکر هست که فقط روی لینوکس یا ویندوز اجرا میشه (ظاهرا برای مک هم هست ولی من جایی ندیدم) و داخل خودش هرچیزی که برای اجرا شدن نیاز داشتهباشه رو داره. در واقع یه کانتینر <strong>یکمی شبیه به ماشینمجازی یا Virtual Machine هست</strong> با این تفاوت که <strong>هستهی سیستمعامل میزبان یا Host رو به اشتراک میذاره.</strong></p>
<p><img src="https://files.virgool.io/upload/users/3181/posts/b1mi525hzvoe/nyajlhjigsvr.jpeg" alt="" /></p>
<p>عکس بالا، اساسیترین تفاوت کانتینرها با ماشینهای مجازی رو نشون میده. چارت سمت راست کانتینر و سمت چپ، ماشین مجازی. زیر ساختها یا Infrastructures شبیه به هم، داکر از سیستمعامل میزبان و ماشین مجازی از Hypervisor که یه لایه هست تا برنامههای مورد نیاز سیستمعامل داخل ماشین رو فراهم کنه، استفاده میکنه. تو ماشین مجازی شما به یه سیستمعامل مهمان احتیاج دارید، مثلا توی سیستمعامل لینوکستون، ویندوز نصب میکنید، اما داکر اینطور نیست و از موتور خودش استفاده میکنه تا با سیستمعامل میزبان ارتباط برقرار کنه. تو ماشین مجازی شما سیستمعامل رو نصب میکنید که برنامههای لازم رو بتونید فراهم کنید. این قدم تو کانتینر از بین رفته (و دقیقا چیزیه که سرعت کانتینر رو به نسبت ماشینمجازی خیلی بیشتر میکنه). در نهایت کتابخونهها و برنامههای لازم اجرا میشن و شما میتونید سیستمتون رو بالا بیارید.</p>
<p>این رو اضافه میکنم، فرض کنید داکر همون نرمافزار Oracle VirtualBox یا VMWare هست و کانتینرها، همون سیستمعاملهایی که توشون نصب میکنیم.</p>
<h1 id="containerization-vs-virtualization">Containerization vs Virtualization</h1>
<p>قبل از اینکه وارد این مبحث بشم، یه نگاهی به ترمینولوژی داکر داشته باشیم:</p>
<p>موتور داکر یا <strong>Docker Engine</strong>قسمتی از داکر که وظیفهی ایجاد و اجرای کانتینرها رو دارههاب داکر یا <strong>Docker Hub</strong>سرویسی از داکر برای به اشتراکگذاری کانتینرها با دیگرانداکر کامپوز یا <strong>Docker Compose</strong></p>
<p>ابزاری که باهاش برنامههای چند کانتینری تعریف میکنیم. این ابزار از فایلهای Yaml استفاده میکنه تا فایلها و تنظیمات رو کانفیگ کنه و کانتینر رو آماده اجرا کنه.</p>
<p>در کل استفاده از این ابزار سه مرحله داره:</p>
<ol>
<li>محیط برنامه رو با یه Dockerfile تعریف میکنیم تا همهجا بشه ازش استفاده کرد.</li>
<li>سرویسهایی که لازم هست برای اجرای این کانتینر رو تو فایل docker-compose.yml میذاریم تا با فایل Dockerfile یه جا اجرا بشن.</li>
<li>دستور docker-compuse up رو اجرا میکنیم و تموم میشه!</li>
</ol>
<p>داکر ایمِج یا <strong>Docker Image</strong></p>
<p>تو داکر، همهچیز بر اساس ایمِجها ساخته شده!</p>
<p>داکر فایل یا <strong>Docker file</strong>دستوراتی که برای ساخت ایمِج لازم هست اینجا تعریف میشه.</p>
<h2 id="حالا-کانتِینِریزِیشن-در-مقابل-ویرچوالیزِیشن-یا-مجازیسازی-چی-هست">حالا کانتِینِریزِیشن در مقابل ویرچوالیزِیشن یا مجازیسازی چی هست؟</h2>
<p>هرچهقدر که زمان میگذره، تکنولوژی داکر بین حرفهایهای IT محبوبیت بیشتری پیدا میکنه، که باعث میشه برای برنامهنویسها دونستن حداقل مبانی کانتینرها به یک «باید» تبدیل بشه.</p>
<p>صنعت IT هرروز درحال تغییر و پیشرفته و «سرعت و بهینهسازی» تبدیل به اساس این صنعت شدن. تکنولوژیها سعی کردن روشهای بهتری رو برای اتوماسیون ارائه بدن تا پروسه ساخت و تولید برنامهها روراحتتر و سریعتر کنن.</p>
<p>نمیدونم که آیا با Industry 4.0 آشنایی دارید یا نه، اما مجازیسازی یا ویرچوالیزیشن (Virtualization) سعی کرده تا این نسخه از صنعت IT رو بهینهتر و قابلحملتر یا Portable کنه. با اینحال، تکنولوژی مجازیسازی نقاط ضعف جدی رو داره، مثل کاهش محسوس پرفورمنس نرمافزارها که بخاطر وزن زیاد و ساختار سنگین VMها یا Virtual Machineها اتفاق میوفته. یا مثلا غیرقابل حمل بودن برنامهها و کارایی پایین در مدیریت منابع سیستم و چیزهای دیگه از این دسته.</p>
<p>اینجاست که صنعت IT رفته سراغ تکنولوژی داکر و کانتینریزیشن! دقیقتر میگم، موتور داکر برای کانتینریزیشن ساخته شده که مراحل <strong>بستهبندی، حمل و گسترش</strong> برنامهها رو بسیار ساده کرده.</p>
<h1 id="شکافت-هستهی-اتم">شکافت هستهی اتم!</h1>
<p>برای یادگیری و راهاندازی داکر، نیازی نیست فیزیک کوانتوم بلد باشید یا بتونید حداقل یکی از <a href="https://curiosity.com/topics/the-millennium-problems-are-seven-math-problems-worth-dollar1-million-each-curiosity/">سوالای میلنیوم ریاضی</a> رو حل کنید! فقط کافیه یکمی با محیط ترمینال و cli دوست باشید و یک تکستادیتور هم کنار دستتون باشه، و خب قطعا داشتن یکمی دانش برنامهنویسی هم میتونه به کارتون بیاد!</p>
<h2 id="نصب-و-راهاندازی-داکر">نصب و راهاندازی داکر</h2>
<p>گرفتن تمام ابزارهای مورد نیازتون برای داکر میتونه کمی خستهکننده به نظر برسه. اما توصیهی من اینه که قبل از نصب داکر، حتما <a href="https://code.visualstudio.com/">نرمافزار vscode رو دانلود کنید</a> و در نهایت <a href="https://www.docker.com/community-edition#/linux">داکر رو برای سیستمعامل خودتون دریافت کنید.</a></p>
<p>بعد از نصب داکر، دستور زیر رو اجرا کنید تا مطمئن بشیم همهچیز درست انجام شده:</p>
<p><code class="highlighter-rouge">$ docker run hello-world</code></p>
<p>که در پاسخش باید نتیجهی زیر رو دریافت کنید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Hello from Docker.
This message shows that your installation appears to be working correctly.
...
</code></pre></div></div>
<h2 id="بازی-با-busybox">بازی با BusyBox</h2>
<p>حالا که داکر نصب شده، بریم و یکم دستامون رو کثیف کنیم. برای اینکار یه کانتینر BusyBox (یه نرمافزار که یسری از ابزارهای Unix رو توی یه فایل به شما میده) رو نصب میکنیم تا طعم دستور <code class="highlighter-rouge">docker run</code> رو بچشیم.</p>
<p>برای شروع، دستور زیر رو اجرا کنید:</p>
<p><code class="highlighter-rouge">$ docker pull busybox</code></p>
<p>دقت داشته باشید که ممکن هست به ارور <code class="highlighter-rouge">permission denied</code> برخورد کنید. بهترین راه اینه که خودتون رو توی گروه docker اضافه کنید تا ازش پیشگری بشه.</p>
<p>دستور <code class="highlighter-rouge">pull</code> ایمِج BusyBox رو از <a href="https://hub.docker.com/explore/">رجیستری داکر (Docker Registry) یا همون داکرهاب (Docker Hub)</a> دریافت و اون روی روی سیستممون ذخیره میکنه. ضمنا شما میتونید دستور <code class="highlighter-rouge">docker images</code> رو اجرا کنید تا ببینید چه ایمِجهایی روی سیستمتون نصب شدن.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>REPOSITORY TAG IMAGE ID CREATED SIZE
nexus.ida-analytics.de/ida/moira latest e3503776559a 6 days ago 387MB
nexus.ida-analytics.de/ida/grafana latest a1192aa71c7f 7 days ago 387MB
nexus.ida-analytics.de/ida/grafana 6145fb02ee49 7 days ago 387MB
nexus.ida-analytics.de/ida/moira 1323d422a434 7 days ago 387MB
busybox latest 8c811b4aec35 7 weeks ago 1.15MB
</code></pre></div></div>
<h2 id="docker-run">Docker Run</h2>
<p>عالی شد! حالا وقتش شده که یه کانتینر داکر، مبتنی بر ایمِجی که گرفتیم رو اجرا کنیم. برای اینکار از دستور زیر استفاده میکنیم:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker run busybox
$
</code></pre></div></div>
<p>چی شد؟! چرا هیچ اتفاقی رخ نداد؟! خب، واقعیت اینه که کلی اتفاقات اینجا افتاده که با چشم غیر مسلح قابل رویت نیست :دی. وقتی که شما دستور <code class="highlighter-rouge">run</code> رو صدا میزنید، داکر ایمِجی که گفتید رو پیدا میکنه (اینجا میشه Busybox)، یه کانتینر براش میسازه و یه دستور رو توی کانتینر اجرا میکنه. اگر دقت کنید، تو دستور <code class="highlighter-rouge">docker run busybox</code> ما هیچ دستور اضافی رو فراهم نکردیم. بنابراین کانتینر ساخته شده، بالا اومده، یه دستور خالی رو اجرا کرده و خارج شده.</p>
<p>دستور بالا رو میشه اینطور هم نوشت:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker run busybox echo "Salam Donya!!"
Salam Donya!!
</code></pre></div></div>
<p>اینجا داکر، دستور echo رو اجرا کرده و در نهایت بسته شده. حالا فکر کنید میخواستید همهی اینا رو با ماشینمجازی اجرا کنید! چقدر باید صبر میکردید؟</p>
<p>حالا وقتش شده که دستور <code class="highlighter-rouge">docker ps</code> رو اجرا کنیم.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
</code></pre></div></div>
<p>از اونجایی که هیچ کانتینری در حال اجرا نیست، ما هم یه لیست خالی رو دریافت کردیم. حالا یکم دستور رو دقیقتر میکنیم:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2059d101f971 busybox "echo Hallo" 15 minutes ago Exited (0) 15 minutes ago hopeful_nightingale
45f36d883bd4 busybox "sh" 15 minutes ago Exited (0) 15 minutes ago kind_mcnulty
375b34dfa64c nexus.ida-analytics.de/ida/moira:latest "/bin/moira" 6 days ago Exited (137) 6 days ago moira
45ba50ce36f9 nexus.ida-analytics.de/ida/grafana:latest "/bin/start_grafana" 6 days ago Exited (0) 6 days ago grafana
</code></pre></div></div>
<p>همونطور که مشخصه، پارامتر <code class="highlighter-rouge">-a</code> دستور داده که لیست تمام کانتینرها، فاقد از وضعیتشون (که اینجا <code class="highlighter-rouge">exited</code> هست) برگردونده بشه.</p>
<p>شاید براتون سوال بشه که چطور میشه دستورات بیشتری رو توی کانتینر اجرا کرد؟ خیلی آسون. اگر با دستور <code class="highlighter-rouge">ssh</code> آشنایی داشته باشید، میخوایم اینجا یه کاری مشابه اون رو انجام بدیم:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # pwd
/
/ # uptime
22:30:58 up 3:26, 0 users, load average: 1.54, 1.46, 1.48
/ #
</code></pre></div></div>
<p>اجرا کردن دستور <code class="highlighter-rouge">run</code> با پارامتر <code class="highlighter-rouge">-it</code> باعث میشه که ما به داخل کانتینر (در واقع با ساخت یه سِشِن tty) بریم و دستوراتی که میخوایم رو اونجا اجرا کنیم.</p>
<p>قبل از اینکه به مرحلهی بعدی برم، بهتون این نکته رو هم میگم که چطور میشه کانتینرها رو حذف کرد. بالاتر دیدیم که با اجرا کردن دستور <code class="highlighter-rouge">docker ps -a</code> میتونیم لیست تمام کانتینرهامون رو بدست بیاریم. برای حذف یه کانتینر کافیه که <code class="highlighter-rouge">CONTAINER ID</code> او کانتینر رو برداریم و بعد دستور <code class="highlighter-rouge">docker rm CONTAINER_ID</code> رو اجرا کنیم. که در پاسخش باید آیدی کانتینر دوباره به شما نمایش داده بشه.</p>
<p>دستور زیر هم هست:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker rm $(docker ps -a -q -f status=exited)
</code></pre></div></div>
<p>اجرا کردن این دستور، تمام کانتینرهایی که وضعیت <code class="highlighter-rouge">exited</code> دارن رو پاک میکنه.</p>
<h1 id="وباَپ-تو-داکر">وباَپ تو داکر</h1>
<p>تا اینجا فهمیدیم که دستور <code class="highlighter-rouge">docker run</code> تا حدودی چطور کار میکنه، همزمان یکمی هم با کانتینرها بازی کردیم و با ترمینولوژی داکر بیشتر آشنا شدیم. حالا وقتش شده که بریم سراغ مسائل اساسی، و ببینیم که چطور میشه یه وباَپ رو تو داکر دیپلوی یا Deploy کرد.</p>
<h2 id="سایتهای-استاتیک">سایتهای استاتیک</h2>
<p>بذارید قدمهای کوچک برداریم. اولین چیزی که میریم سراغش، دیپلوی کردن یه سایت استاتیک خیلی ساده هست. یه ایمِج رو از داکرهاب دریافت یا pull میکنیم و اجراش میکنیم تا ببینیم چقدر راهاندازی سایتهای استاتیک کار آسونیه.</p>
<p>ایمِجی که برای اینکار استفاده میکنیم، یه ایمِج از قبل آماده شدست:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker run prakhar1989/static-site
</code></pre></div></div>
<p>از اونجایی که این ایمِج به صورت لوکال یا محلی تو سیستم ما نیست، داکر اون رو از رجیستری دریافت میکنه و بعد ایمِج رو اجرا میکنه. اگر همهچیز خوب پیش بره، شما پیام <code class="highlighter-rouge">Nginx is running...</code> رو خواهید دید. حالا که سرور راهافتاده، چطور میشه بهش دسترسی داشت؟ چطوری میشه فهمید تو چه پورتی اجرا شده؟</p>
<p>خب تو این حالت، داکر هیچ پورتی رو نمایش یا اصطلاحا اِکسپوز (Expose) نمیکنه، برای همین لازم هست که مجددا دستور <code class="highlighter-rouge">docker run</code> رو اجرا کنیم تا پورتها رو نمایش بدیم. همزمان هم باید کاری کنیم که ترمینال روی این حالت قفل نشه و ما بتونیم از ترمینال، بدون بستن سرور خارج بشیم. به این حالت میگن Detached Mode یا حالت جدا شده!</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker run -d -P --name static-site prakhar1989/static-site
531b38e65151ba7ee133aff085d4c3e31d9ab349d0fed2b48b91cf28d53ca685
</code></pre></div></div>
<p>تو دستور بالا، <code class="highlighter-rouge">-d</code> حالت detached mode رو اجرا و <code class="highlighter-rouge">-P</code> پورتهارو باز میکنه. <code class="highlighter-rouge">--name</code> هم اسمی رو برای کانتینر درنظر میگیره. حالا میتونیم پورتهای باز شده رو پیدا کنیم:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker port static-site
443/tcp -&gt; 0.0.0.0:32768
80/tcp -&gt; 0.0.0.0:32769
</code></pre></div></div>
<p>حالا، <a href="http://localhost:32769/">http://localhost:32769</a> رو باز کنید و نتیجه رو ببینید.</p>
<p>همچنین میتونید یه آدرس پورت دلخواه هم به ایمِجتون بدید:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
</code></pre></div></div>
<p>این دستور میگه که: به پورت ۸۸۸۸ سیستم هاست یا میزبان، هرچیزی که تو پورت ۸۰ ایمِج بود رو اختصاص بده. برای اینکه کانتینر رو متوقف کنید، دستور <code class="highlighter-rouge">docker stop</code> رو به همراه آیدی کانتینر اجرا کنید.</p>
<p>مطمئن هستم که شما هم موافقید این کار واقعا آسون بود! فکر کنید شما یه سرور دارید و میخواید سایتتون رو روش راهاندازی کنید، کل کار اینه که داکر رو نصب کنید و دستورات بالا رو وارد کنید!</p>
<p>ولی خب، این برای ما کافی نیست، چون ما دوست داریم بیشتر بدونیم :) برای همین باید یاد بگیریم چطور داکر ایمِج خودمون رو بسازیم…</p>
<h2 id="داکر-ایمِجها">داکر ایمِجها</h2>
<p>ما با ایمِجها تا حدودی آشنا شدیم، ولی تو این بخش میخوام عمیقتر شیرجه بزنیم تو ایمِجها و ببینیم اصلا ایمِجهای داکر چی هستن… کاری که انجام دادیم این بود که ایمِج busybox رو از رجیستری <strong>دریافت یا pull کردیم،</strong> و به داکر گفتیم که یه کانتینر <strong>مبتنی بر اون ایمِج</strong> برامون بسازه. اول بیاید یه لیستی از ایمِجهامون رو بگیریم:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nexus.ida-analytics.de/ida/moira latest e3503776559a 7 days ago 387MB
nexus.ida-analytics.de/ida/grafana latest a1192aa71c7f 7 days ago 387MB
nexus.ida-analytics.de/ida/grafana 6145fb02ee49 7 days ago 387MB
nexus.ida-analytics.de/ida/moira 1323d422a434 7 days ago 387MB
busybox latest 8c811b4aec35 7 weeks ago 1.15MB
prakhar1989/static-site latest f01030e1dcf3 2 years ago 134MB
</code></pre></div></div>
<p>این لیست، لیست همهی ایمِجهایی هست که من روی این سیستمم نصب دارم و از رجیستریهای مختلف دریافت کردم. TAG به یک نسخهی مشخص از ایمِج اشاره میکنه و IMAGE ID به آیدی منحصر به فرد اون ایمِج.</p>
<p>برای سادگی فهم، ایمِجها رو به چشم ریپازیتوریهای گیت ببینید. ایمِجها میتونن کامیت بشن و ورژنهای مختلفی داشته باشن، در حالت عادی هم، داکر نسخه latest رو دریافت میکنه که مشابه شاخه یا branch اصلی یا main تو گیت هست. مثلا میخوایم یه نسخه از اوبونتو رو دریافت کنیم:</p>