زندگی، فلسفه، تکنولوژی صنعت <- اندیشه ها، احساسات

چگونه می توانیم صنعت بازی سازی پویا و واقعی داشته باشیم؟

اخیرا به دلیل تصمیمات به نظر بنده غلط بنیاد مبنی بر گرفتن باج و خراج از بازی های رایانه ای که از خارج وارد می شوند، سر و صدای زیادی راجع به این مساله و مسایل دیگر راه افتاده است. تکرار چیزهایی که دیگران گفتند و می گویند و خودم در تویتر گفتم (@ashkansm89 ) کار بی فایده ایست و عقلانیت حکم بر پرهیز از آن می کند. به جز تویتر من، تویتر آقای امیر حسین فصیحی گرامی و پست حسین ابرار را می توانید بخوانید. مساله مهم این است که اگر از کمی بالاتر به موضوع نگاه کنیم، باید ببینیم برای ساخت صنعت بازی واقعی و پویا به چه چیزهایی نیاز داریم و آیا در حال حرکت به سمت آن هستیم یا خیر و سعی کنیم ایرادات موجود را برطرف نماییم.

هر صنعتی مستلزم وجود چند چیز است. خدمات/محصول، مشتری/نیاز و در نتیجه آن بازار. برای به وجود آمدن خدمات و محصول نیاز به افراد مجرب و شرکت های خوب است که بتوانند آن ها را ارایه کنند و برای وجود نیاز و مشتری و در نتیجه بازار باید به جز داشتن محصول خوب، تفکر/فرهنگ استفاده از آن محصولات نیز وجود داشته باشد. چه بسا محصولات خوبی که وارد دنیای ما شدند و برایشان بازاری درست نشد و از بین رفتند و چه بسا انسان های با استعداد و تلاشگری که توانا بودند ولی نتوانستند در زمان و مکان خاصی بخشی از یک صنعت شوند. برای مثال افراد نسبتا زیادی در دهه هشتاد میلادی روی VR کار کردند و امید ایجاد صنعتی با بازار همگانی بوده است. نتیجه آن به دلایل نبود تکنولوژی مناسب و پشتیبانی شرکت های بزرگ و در نتیجه نبود مشتری بسیار متفاوت شد. هر چند VR کاربردهای خود را در آن زمان در نرم افزارهای شبیه سازی پزشکی و نظامی پیدا کرد و تحقیقات پایه آن روز در نهایت منجر به تکنولوژی نسبتا قابل دسترسی امروز شده است و حتی در گذشته در پارک های بزرگ مثل Disney land ها مورد استفاده قرار گرفته اما مثلا حتی در 5% خانه های کشورهای پیشرفته هم دستگاه VR موجود نبوده است. در این مثال مشکل تا حد بسیار زیادی تکنولوژی و قیمت تولید بوده است. در بسیاری زمان ها و مکان های دیگر سعی برای تولید صنایعی شکل گرفته که موفق نبوده اند ولی چون دلایلشان معمولتر و به دلیل نبود بازار و / یا نیروی کار مناسب و شرایط بد بوده است، داستان هایشان خیلی بازگو نمی شود. 

به هر حال ما برای داشتن صنعت بازی باید تیم های خوبی داشته باشیم که می توانند بازی تولید کنند و اصولا نگاه محلی به این صنعت خیلی نگاه درستی نیست. بزرگترین بازارهای این صنعت در اروپا و آمریکای شمالی هستند و تنها کشوری که هم بازار بزرگی دارد و خیلی محصولاتش فقط در کشور خودش خوب فروخته می شود ژاپن است. دو نکته شایان توجه است، یک این که ژاپنی ها این مطلب را مایه شکست می دانند و دوست دارند مثل گذشته بازیهایشان در تمام دنیا خوب به فروش برسند و دوم این که ژاپنی ها بازاری با فرهنگ مناسب و میزان درآمد بالا هستند. دو شرکت از سازنده های کنسول بازی سازی در ژاپن هستند و فقط یکی از آن ها آمریکایی است. جمعیت ژاپن بالا است و مردم بازی و مجله و فیلم و .. زیاد می خرند و قوانین هم به شدت در ژاپن رعایت می شوند. پس ما باید بتوانیم بازی هایی بسازیم که در همه دنیا به فروش برسند. زمانی که ما کار را شروع کردیم هنوز به جز بازی پایان معصومیت هیچ بازی ایرانی دیگری وارد بازار نشده بود و ما کلا به فروش بین المللی فکر می کردیم. حال آن که موفقیتی در این زمینه کسب نکردیم دلایل زیادی دارد که در این پست جای بررسیش نیست. منظورم این نیست که باید بازار داخل را نادیده بگیریم، خیر با توجه به فروش خوب بازی گرشاسپ و  احتمالا برخی بازی های دیگر در گذشته و فروش خوب برخی بازی های موبایلی، بازار داخلی ما هم می تواند به بازاری جدی تبدیل شود. 

ما به جز تیم های خوب به بازاری نیاز داریم که در آن مردم حاضرند پول یک وعده غذای یک نفر را برای یک بازی بدهند و در گوشی های موبایل هم فرهنگشان پیشرفت کند تا بتوان بازیهای نسبتا بهتر و پیچیده تر را به آن ها فروخت. زیرا بسیاری از بازی هایی که در حال حاضر در کافه بازار فروخته می شوند فقط یک تم فرهنگی با المان های gameplay بسیار ساده و سطحی هستند و در هیچ کشور دیگری قابل ارایه نیستند. در حالی که خیلی از بازیهای به ظاهر موفق درآمدشان از این بازار کافی نیست و با فروش بازی خود در کشورهای دیگر می توانند موفقیت قابل قبولی کسب کنند. برای ایجاد این بازار ما نیاز داریم برای مردم فرهنگ سازی کنیم، محصولات خوب داخلی و محصولات خوب خارجی را به آن ها بفروشیم. مردم محصولات خوب داخلی را می خرند حتی اگر نسخه های خارجی را مجانی گرفته باشند. این مطلب در باره فیلم، موسیقی و کتاب صدق می کند و در مورد بازی هم می تواند این طور باشد. چون در کشور ما فیلم و موسیقی خارجی حدودا مجانی است، قطعا قیمت عامل خرید مردم نیست. عامل آن وجود صنعتی است که محصول با کیفیت تولید می کند و می تواند محصول با کیفیت تولید کند، تهیه کننده دارد چون بازار دارد. می توان روی بازگشت سرمایه آن حساب کرد و ...

ما برای داشتن صنعت بازی باید سعی کنیم شرکت هایی که واقعا استعداد دارند و تیم هایی که واقعا می توانند بازی بسازند را در فضایی قرار دهیم که کارهای خوب بسازند، تا به وجود آمدن ناشر و تهیه کننده باید سعی کنیم در صورت لزوم حمایت مالی کنیم (همان طور که در بنیاد در سال های ابتدایی اتفاق می افتاد). باید سعی کنیم فضا طوری شود که نمونه های موفق باعث شوند که برخی افراد به فکر نشر و تهیه بازی بیفتند. یکی از دلایل بد بودن گرفتن باج و خراج از واردات بازی همین است که این کار به تولید این ناشران و تهیه کننده ها کمک می کرد. دلیل آن هم این تصور است که نشر بازی خارجی کاری ندارد. حال آن که خود من قصد نشر یکی از بازی هایی که در گذشته روی آن کار کرده بودم در ایران را داشتم و هزینه های تبلیغات و (گاهی هزینه اولیه که باید به سازنده بازی برای گارانتی بدیم) ترجمه و مناسب سازی و ... اصلا پایین نیست و درصد سود شما از بازی هم یا کم است و یا برای داشتن درصد بالا باید گارانتی زیادی (حد اقل ها برای بازی ها و تیم های کوچیک از 25-30 هزار دلار شروع می شود) پرداخت کنیم. 

حال سوال کردن و پاسخ به آن خیلی هم سخت نیست که آیا ما در حال جذب استعداد های خوب از دانشگاه های خوب به سمت بازی سازی هستیم؟ آیا دانشجو های خوبی تربیت می کنیم؟ آیا ما به شرکت هایی که نشان داده اند می توانند بازی بسازند و یا تیم هایی که دارای demo/prototype خوبی بوده اند سرمایه تولید داده ایم و یا امکان کسب آن از راهی دیگر مثل VC ها را برایشان فراهم کرده ایم؟ آیا ما بازی سازان توانایی پذیرش کارآموز در شرکت و پذیرش ریسک زمانی و مادیش را داریم؟ آیا فضای کار ما برای ورود افراد جدید راحت و مناسب است؟ جواب برخی از این سوالات خوشبختانه مثبت و جواب برخی منفی است. بنیاد ملی بازیها کارهای خوبی در گذشته انجام داده است. بازیهای ایرانی را به نمایشگاه های خارجی برده، نمایشگاه های داخلی برای مردم برگزار نموده تا مردم با بازی ها آشنا شوند. برای ما تولید کننده ها TGC برگزار کرده است و در گذشته از بازی ها حمایت مالی درست و بر پایه استعداد تیم ها کرده است اما بنیاد در سهم خود کارهای اشتباهی مثل برگزاری برخی رویداد ها و دادن برخی بودجه ها به افراد نادانی که فقط حرفهای خوب می زنند و خرج برخی پول ها برای برخی پروژه هایی که معلوم بوده خیلی هم از آنها چیزی در نمی آید کرده است. بنیاد حمایت خود را به شکل وام تبدیل کرد که پذیرش ریسکش برای تیم های کوچک مثل ما ممکن نیست. ما توانایی ساخت بازی را داشتیم ولی روی پروژه های خارجی کار می کردیم چون نیاز به درآمد برای همه وجود داشت و جایی برای سرمایه گرفتن نداشتیم. البته شرایط الآن کمی برایمان بهتر است و به امید خدا به زودی دمویی آماده خواهیم داشتو در خارج و داخل به دنبال سرمایه خواهیم بود. کارهای دیگری مثل رده بندی بازی ها با پر کردن فرم در بازارها توسط توسعه دهندگان و ارسال عکس و فیلم بازی به بنیاد می تواند با هزینه بسیار کمتری انجام شود. طبعا دروغ گویی در این زمینه با پیگرد قانونی همراه خواهد بود.

در آخر بگویم که به نظرم مشخص است باید چه کارهایی انجام شود و برخی از آن ها که فرهنگی هستند بیشتر زمان برده و طول می کشند. چیزهایی در ذهن ما سازندگان و چیزهایی در ذهن مردم باید تغییر کند تا صنعت بهتر شود اما همین امروز هم با همین ذهن ها با مدیریت بهتر منابع می شود نتایج خیلی بهتری داشت. ما باید افرادی که فقط اطراف بازی هستند و بی جهت به عنوان مدیر پروژه و مثلا برگزار کننده فلان و ... خبرنگار نامناسب و بازی ساز الکی هستند از واقعی ها جدا کنیم و منابع را روی افراد دانا و درست کار صرف کنیم. هم تیم های جدید با استعداد قابل یافت هستند و هم بسیاری از افراد که یا مشغولند و یا تیم هایشان در گذشته از هم پاشیده موجودند. البته برخیشان به خارج از کشور رفته اند که غمی است و اندوهی که شاید تا همه چیز درستتر نشود به راحتی همه شان باز نگردند. باید بنیاد و ما سعی کنیم که با منطق و بررسی نظرات افراد شایسته و انجام کارهای عاقلانه محیط را برای تولید محصول با کیفیتتر آماده کنیم (رویداد level up کار بسیار مثبتی در این زمینه بود) و مردم را نیز با محصولات آشنا کرده و به صادرات محصول های با کیفیت کمک هم بکنیم. البته گاهی حرفهایی هم از زبان برخی گفته می شود که ما را به شک وامی دارد که آیا اگر با بنیاد کاری بکنیم مثل شرکت فن افزار به ناحق همه زحماتمان به پایه پولی که بنیاد به عنوان حمایت با سود بالا به آن ها داده، گذاشته می شود یا خیر؟ آیا بنیاد برای همین تولید نشده و کارش همین نیست؟ آیا فن افزار کوتاهی در تولید و فروش گرشاسپ کرده است و آیا سود بنیاد کم بوده است؟ من آخرین چیزی که در زمندگیم می خواهم این است که زحمت بکشم و به چیزی برسم و ده سال دیگر وقتی نزدیک چهل سالم شد کسی بیاید و بگوید که باعث موفقیت من او بوده و این باعث بودن را بیش از حد تاثیر واقعیش جلوه دهد. شاید موفق نشوم بهتر است. البته شکر خدا که راه برای انجام هر کاری زیاد است و ما همه با عشق وارد این کار شده ایم و به دوعوت کسی نیامده ایم که به ناراحتیش برویم و صفر تا صد کارمان تلاش و امید و تجربه خودمان است. دستمان به زانوی خودمان و امیدمان به خدا است و به آن چه خود می کنیم. اگر بنیاد خوب باشد و تصمیم های خوب بگیرد، برای همه خوب است و اگر بد باشد برای همه بد. من به شخصه تا به حال ارتباطی با کسی در بنیاد نداشتم و در گذشته یک بار برای برگزاری global gamejam با بنیاد تماس گرفتم و یک بار هنگامی که می خواستیم شرکت ثبت کنیم (البته حمایت های بنیاد موقعی که ما پول نیاز داشتیم دیگر موجود نبود). نه دشمنی با بنیاد دارم و نه دلیلی برای دشمنی با نهادی که برای این تولید شده که به امثال من کمک کند، اما اگر این نهاد این کار را نکند و به جای آن در توهم و ادعا درگیر باشد، ما باید از راه دیگری نیازهایی که بنیاد قرار است برآورده کند را برآورده کنیم، بازار بسازیم و فرهنگ بسازیم و بازی و این کار را خواهیم کرد چه بنیاد همراه باشد و چه نباشد. این ها را نوشتم که بگویم اگر بنیاد بخواهد کار جدی کند، هم کارها مشخص هستند و هم همه بازی سازان عاشقانه به آن کمک خواهند کرد و همه سود خواهیم کرد و ایران عزیزمان به جلو خواهد رفت. برخی هم ناراحت می شوند که بساط show هایشان و پول هایی که بی خود می گرفتند جمع شده که خوب ناراحت شوند. باید جمع می شده. امیدوارم که آینده مان را خوب بسازیم.

۲۶ دی ۹۶ ، ۱۹:۰۴ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

گرفتن پروژه از خارج از کشور (بخش دوم)

در پست قبل راجع به این موضوع کمی می خواستم بیشتر به شکل عملی صحبت کنم. این که کارها رو از کجا می شه پیدا کرد و چه طور کار رو می شه گرفت که چون طولانی شد ننوشتم. تو این پست اونا رو توضیح می دم و این که باز هم می گم من کسی رو به انجام این کار تشویق نمی کنم. فکر می کنم باید اولویت نوشتن پروژه خود آدم باشه و با این کار می شه شرکت رو ماندگار کرد. این کار فقط برای زنده نگه داشتن شرکت مناسبه و ترجیحا باید مقدار پولی که می گیرید اون قدر باشه که به نوشتن پروژه خودتون کمک کنه و با پروژه خارجی تموم نشه.حالا در باره مکان های گرفتن کار بگم که همونطور که قبلا گفتم بیشتر تو انجمن های مربوط به خود شرکتا کار پیدا می کنید و تو آشنایی با آدم ها از طریق بیرون دادن demo/screenshot/blog/... ولی حالا فرض کنید کاری یافتید که می خواید بگیریدش. باید چی کار کرد؟ طبعا اولش یه پیام یا ایمیل به ارسال کننده کار می فرستید. معمولا خودشون روش ارتباط رو می نویسند. بعد معمولا ازتون زمان و قیمت می خوان ولی به جز اون ها خیلی خوبه که تو ایمیلی کوتاه توضیح بدید چرا برای اون کار مناسبید و دروغ نگید. تشخیصش با وناست که شما مناسبید یا نه. قطعا کارایی هم سطحتون پیدا خواهد شد. اولش هم قطعا خیلی بیشتر طول خواهد کشید. این رو باید بدونید که در بیشتر مواقعی که با کشور های اروپایی و آمریکایی کار می کنید، باید با طرف مقابل روی اسکایپ یا برنامه دیگری صحبت کنید. برنامه دیگر معمولا شامل google hangout و جدیدا slack می شه. 

طبعا اگه نتونید خوب حرف بزنید و منظورتونو برسونید و یا منظور و بفهمید، نمی تونید کار رو بگیرید. لهجه اون قدر نباید مهم باشه. من هیچ وقت لهجه خیلی بدی نداشتم که بدونم اثرش چه قدره ولی خیلیا رو دیدم که لهجه شدید دارند (روسی، هندی، اروپای شرقی ...) و داشتند کار می کردند.

بقیه چیزایی که لازم دارید خیلی مشخصه، کار خوب و اخلاق حرفه ای و تشخیص شخصیت طرف مقابل. مثلا اگه کسی شوخ نیست و خیلی جدیه خوب طبعا اگه خیلی هم مسخره بازی در بیارید خوشش نمیاد و برعکس. من از فیلم بازی کردن خیلی بدم میاد و اصلا نه می تونم بازی کنم و نه منظورمه که بازی کنید. توضیحش برام سخته. مادب و متشخص بودن معمولا کمک می کنه و این که حد خودتونو بدونید و .. مثلا اگه طرف مقابل چهل سالشه و شما کمتر از سی و تجربش تو بازی های خفن استودیو های بزرگه، خوب باید سعی کنید که بفهمید دارید با کی صحبت می کنید. من این مشکل رو تو خیلیا دیدم که یا فکر می کنند باید خودشونو کم ببینند و یا این که پر رو و پر مدعا باشند. قطعا هیچ کدوم بهتون کمک نمی کنه. نظر بدید و مخالفت کنید (اگه  واقعا مخالفید و می دونید دارید چی می گید)، معمولا کسی که همیشه می گه چشم و شما درست می گید آدم خیلی راستگو و قابل اعتمادی نیست. 

گاهی ممکنه مشکلی پیش بیاد که از سمت مشتری باشه و دیر متوجهش بشه. خوبه که صبور باشید و این رو هم باید بدونید که ممکنه کسی پولتونو بخوره. من در ابتدای کار که تجربه کمتری داشتم این مشکل دو بار برام پیش اومد. یه بارش از شب تا صبح امتحان رو یه بازی turn based شبکه ای کار کردیم که چون fade to black گوش می دادیم اسمش شد fade to black و طرف گفت من اولین build رو تو Android ببینم باهاتون قرارداد می بندم. ما هم با فیلترینگ برای اولین بارمو ن یه build گرفتیم و براش فرستادیم و سه روز وقت طلف کردیم که تهش معلوم شد یارو تو دمو پروژه رو به سرمایه دارا نشون می داده پول بگیره. 

یه بار دیگه هم بودش که طرف دو هفته خودش نمی تونست پروژه رو نصب کنه و قبلی رو می دید  و هی فکر می کرد باگ داره و آخرش وقتی پروژه برای مشکل وقت کنسل شد بقیه پول ما رو نداد. البته تو این کیس ما هم تو تخمینمون خیلی اشتباه کرده بودیم.

نکته دیگه ای که باید حواستون باشه، برای پروژه هایی که ساعتی بهتون پول نمی دن هست. تو اونا باید تخمین خوبی بزنید و کلا تخمین زدن  نرم افزار سخته، بازی از اونم سختتره. کتاب demystifying the black art of software estimation آقای استیو مک کانل رو پیشنهاد می کنم. 

از نظر قیمت ها باید دقت کنید که کسی که داره شما رو برای کار انتخاب می کنه از چند حالت خارج نیست، یکی این که اون قدر خفنید که می خواد شما رو پروژش کار کنید، که اگه این طوره نسبت به ارزشی که به نظرتون کارتون داره قیمت بدین. یا طرف می خواد از یه کشور دیگه کانترکتور استخدام کنه که پول کمتری بده و یا تو کشوری هست که دورش اصولا آدم زیاد نیست. به هر حال تو این حالات دوم و سوم باید محل زندگی اون طرف مقابل رو در نظر بگیرید. معمولا مقداری که حاضره به شما بده تو حالت دوم کمتر از قیمت تو کشور خودش و تو حالت سوم حدودای قیمت ها تو کشور خودشه. حالت های دیگه ای هم هست، مثلا پروژه با قیمت فیکس که از اول بهتون می گن و ... معمولا اینا اگه قیمتشون به شکل احمقانه ای کم نباشه، فقط در صورتی بهتون داده می شه که تجربه زیادی داشته باشید. در ضمن اگه زمان شما با کشور اونا زیاد فرق کنه، به خصوص در برنامه نویسی که به تعامل زیادی نیاز داره، هم کارتون سخت می شه و هم احتمال داره بخوان پول کمتری بهتون بدن مگر این که تو ساعتای اونا کار کنید. البته این برای کشور هایی مثل آمریکا هست که طرف برای قیمت اومده سراغ شما.

اگه شما دنبال کار نرفتید و اونا اومدن سراغ شما (چندین سال طول می کشه که این طور بشه) معمولا شرایط بهتره و معمولا هم کار رو می گیرید مگر این که یکی از طرفین توقعات عجیبی داشته باشه. در مورد شخصیت هم بگم که سعی کنید از آدمای نسبتا معقول و کسایی که شغلشون همین هست کار بگیرید. هندل کردن کارفرمایی که این شغلش نیست و سرمایه گذاری فان یا رویاییشه و یا کسی که مثلا برای یه شغل دیگه یه برنامه سه بعدی می خواد ریسک رو می بره بالا. البته من کار این طوری خوب هم انجام دادم ولی باید حواستون به میزان دانش و سرمایه طرف مقابل باشه. 

امیدوارم این پست مفید بوده باشه و امیدوارم بتونید رو پروژه های خودتون کار کنید

۲۲ دی ۹۶ ، ۲۲:۱۸ ۲ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

گرفتن پروژه از خارج از کشور

من در بخش زیادی از دوران کاریم بر روی پروژه هایی کار کرده ام که متعلق به مشتری بوده اند و به جز چند پروژه کوتاه ، بقیه برای شرکت های خارجی بوده است. در این پست سعی می کنم در باره نکات مثبت و منفی این کار و روش انجامش صحبت کنم. در این پست به هیچ وجه تشویق یا دور کردن کسی از انجام این کار را ندارم و فقط آن چه بر من گذشته است را شرح می دهم با امید این که افکار خودم را مرتب کرده و در باره آن با دیگران تبادل نظر کنم.

پیش زمینه

پس از شکل گیری علاقه من به بازی سازی که البته بخشی از زمینه یادگیری سریعش را یک پروژه پیشنهادی از یک معلم فراهم کرد من با دوستانم چند بازی کوچک در Game Maker 6 ساختیم و پس از آن هم در اوایل دوره دانشجویی به دنبال ساخت بازی خودمان بودیم. برای کسب درآمد کنار تحصیل هم به کارهای شبکه مشغول بودیم که البته کمابیش انجام می دادیم و جدی نبود. بعد ها هنگام تولید اولین پروژه بزرگمان که به شکست انجامید برای کسب درآمد در انجمن های یونیتی به دنبال پروژه گشتیم و کم کم انجام پروژه های مشتری به جد آغاز شد.


چرا باید پروژه دور کاری انجام دهیم؟

همان طور که گفتم دلیلی برای انجام این کار وجود ندارد. ما برای این به سمت انجام پروژه ها رفتیم که می خواستیم کسب درآمد برای جلو بردن پروژه خودمان داشته باشیم. برخی معتقدند که بهتر است پروژه های مشتری از جنس دیگری باشند و مثلا به جای پروژه بازی پروژه های شبکه یا تولید سایت و .. باشند. به نظر من این کار به دو دلیل بد است. اول چون چیزهایی که یاد می گیرید و تجاربتان برای کار اصلیتان مفید نخواهند بود و در راستای هدفتان نیستند و دوم این که شما نمی توانید در دو زمینه به یک اندازه پیش رفت کنید و هم پروژه های ارزانتر و نامناسبتری می گیرید و هم بازیتان پیشرفتش کندتر می شود.


نکات مثبت و منفی انجام پروژه مشتری

نکات مثبت گرفتن پروژه مشتری به طور کلی کسب درآمدی منظم و سریع با ریسک نسبتا کمتر از تولید، به چالش کشیده شدن برای انجام کارهایی که لزوما در پروژه خودتان انجام نمی دادید و یادگیری مهارت های نرم و سخت مختلف است. اگر شما به پول نیاز دارید و باید برای جلو بردن پروژه خودتان پول در بیاورید و پروژه هنوز به حدی نرسیده که برایش ناشر یا سرمایه بگیرید، انجام پروژه راهی نسبتا مناسب برای کسب درآمد است. البته باید دقت کنید که معمولا در شروع شما درآمد زیادی نخواهید داشت و اول باید تجربه یا نمونه کار مناسب داشته باشید تا پول خوبی بگیرید. 

از نکات مثبت دیگر که گفتم به چالش کشیده شدن و کسب مهارت است. کسب مهارت در پروژه های مشتری بسیار خوب اتفاق می افتد، البته به شرطی که آن قدر در کارتان خوب باشید که در پروژه های چالش دار و سخت پذیرفته شوید. شما مجبور خواهید بود به حرفهای کارفرما و گاه مدیر فنی تیم گوش کنید و کاری را به روش خاصی انجام دهید و یا کاری را انجام دهید که قبلا انجام نداده اید. اگر شما به شکل زمانی در پروژه مشغول باشید برای همه این یادگیری ها و انجام کارتان پول هم می گیرید. البته این کار فقط در صورتی به سود شما است که یادگیریتان سریع باشد و اصولا تا شما کارتان خوب نباشد با قیمت مناسب به شکل زمانی در پروژه پذیرفته نمی شوید. معمولا در اوایل کار بیشتر پروژه های با قیمت فیکس به شما سپرده خواهد شد که مزیت آخر را از بین می برد و اگر برای زمان مصرفیتان پول بگیرید و به حد کافی در یادگیری و انجام کار سریع نباشید آن وقت از پروژه اخراج می شوید و نظر یک کارفرما نیز نسبت به شما بد شده است.

مساله مهم و مثبت دیگر ارتباط و تعامل است. شما در تیم خودتان ممکن است با گروه هم سن و سال و دوستانتان درگیر باشید و برخی انواع تعاملات ضروری را تجربه نکنید که انجام پروژه فرصت کسب تجربه در این راستا را نیز به شما می دهد. مثلا این مهارت را پیدا می کنید که وقتی از یک نفر مقدار زیادی پول می خواهید و دارد اشتباه می کند، چه طور با او برخورد کنید. یاد می گیرید چه طور به استدلال فنی با برنامه نویسی بپردازید که در پروژه قدرت بیشتری از شما دارد یا چگونه با فردی با جایگاه بهتر ولی در نقشی دیگر مثلا نقش طراح بازی تعامل کنید. در تیم خودتان ممکن است این مسایل به شکل خیلی غیر رسمیتر و آشوبناکتری اتفاق بیفتد که اگر خوب مدیریت شود نکته بسیار مثبتی هم هست، ولی تجربه این کارها به مدیریت آن کمک می کند.

مکات منفی انجام پروژه برای مشتری کار نکردن روی پروژه خودتان است. این بدین معنا است که شما گرانبهاترین منبعتان یعنی زمان را صرف کاری ثانویه می کنید. انجام پروژه برای مشتری ریسک کمتری دارد ولی سود کمتری هم دارد که برای گسترش تیم نکته مثبتی نیست. البته اگر شما قصد داشتن کسب و کار خود را نداشته باشید این ها اصلا نکته منفی نیستند. در صورتی که شما قصد انجام پروژه خودتان را ندارید این کار می تواند از نظر فنی چالش برانگیز باشد و از نظر مالی هم نتیجه نسبتا مناسبی داشته باشد. البته صنایعی هستند که شما با برنامه نویسی در آن ها پول بیشتری در خواهید آورد ولی ممکن است از انجام کارتان به اندازه بازی سازی لذت نبرید.


تجربیات من در گرفتن پروژه

قلم این بخش کمی امری است، شما موقع خواندن در نظر بگیرید که من نظرم را می گویم و فکر نمی کنم که این درستترین نظر است.

گرفتن پروژه مشتری می تواند از داخل یا خارج صورت بگیرد. شما در داخل راحتتر می توانید مشهور شوید و راحتتر می توانید به گفت و گو و تعامل رودررو بپردازید و در مقابل پروژه هایی به نسبت با چالش کمتر و سود مالی کمتری خواهید گرفت. البته مسایلی که می گویم به شکل کلی است و ممکن است خلاف آن وجود داشته باشد. 

هنگام گرفتن پروژه از خارج از کشور گرفتن پروژه برای کل تیم فنی و هنری و طراحی کار مشکلی است و معمولا برای انجام این کار به نمونه کار تیمی و رفتن به کنفرانس ها نیاز دارید. من برای تیمی کار می کردم که خیلی از پروژه های prototype مورد نیاز War Gaming را انجام می داد ولی تیم ما بازی های زیادی در کنسول و PC ارایه کرده بود و در صنعت دارای network قوی بود.

برای گرفتن پروژه نیاز دارید که خود را به دیگران بشناسانید و در کاری بسیار خوب باشید. ابتدا باید با قیمت های کمتر پروژه ها را قبول کنید تا دارای نمونه کارهای مناسب شوید. بیشتر کارهای نسبتا خوب شما را بدون داشتن نمونه قوبل نمی کنند. سعی کنید در مساله ای خاص مثلا برنامه نویسی هوش مصنوعی، شبکه یا شیدر و ... بسیار خوب شوید تا برای کارهای خاص پذیرفته شوید ولی از طرفی چون معمولا برای تیم های کوچک کار خواهید کرد باید بتوانید کارهای دیگر را هم انجام دهید وگرنه به شکل بلند مدت در پروژه ها نخواهید ماند.

باید روشن باشد ولی هرگز و هرگز و هرگز دروغ نگویید، پنهان کاری نکنید و چیزی را طور دیگری وانمود نکنید. شفاف باشید و اشتباهاتتان را بپذیرید زیرا بدون داشتن این ها به درد نمی خورید و کسی با شما کار نخواهد کرد. اگر حس ضعف کردید به جای تقابل مهارتتان را بالا ببرید و سعی کنید وز مشورت دیگران استفاده کنید.

نوشتن بلاگ و پاسخ گویی به وسالات دیگران به شکل کامل و عمیق به شناخته شدنتان کمک می کند ولی نمی دانم اگر به این کار علاقه نداشته باشید چه قدر خوب می توانید آن را انجام دهید. من اولین پستم برای گاماسوترا را طی دو ماه و آخر شب ها نوشته و پاک نویس کردم (به ساعت این پست هم نگاه کنید :) ). داشتن برخورد مناسب و نظرات جالب و کلا ارتباط خوب و روابط عمومی بسیار کمک می کند ولی اگر کاری را مصنوعی انجام دهید سریع مشخص شده و به ضررتان تمام می شود. هیچ کس از همه کارهای دیگران ذوق نمی کند. خودونی بگم ادا در نیارید :) 

شما در برخی کارها ضرر خواهید کرد. من در ابتدای کار به دلیل بد تخمین زدن خودم یا ناتوانی تیممان در انجام کاری یک پروژه را کنسل کردم و یک پروژه به مشکل خورد که هم ناتوانی و تخمین اشتباه ما بود و هم کار نابلدی کارفرما. یک ماه تمام کارفرما نمی توانست بازی را روی iPhone خود نصب کند و نسخه قدیمی را می دید و در نهایت از پروژه 10000 دلاری فقط 4500 دلار به ما رسید که البته آن روزها پول خوبی بود و ما هم دفتر گرفتیم و هم کارمان را جدیتر ادامه دادیم. طول می کشد تا بتوانید کارها را خوب تخمین بزنید و قبل از زیاد شدن مهارتتان پروژه های بزرگتر را نگیرید و یا از با تجربه ترها کمک فکری بگیرید. 


سعی کنید روی پروژه هایی کار کنید که می توانید یا پروژه یا تیم یا چیز دیگری در کار را عاشقانه دوست داشته باشید. این موضوع خیل مهم است و به نظرم فقط باید وقتی نادیده گرفته شود که یا از نظر مالی شرایط خوبی ندارید و یا هدف کسب درآمدتان آن قدر خوب و جذاب است که اشقش هستید و انگیزه کافی را به شما می دهد. اگر شما عاشق کاری باشید در پروسه انجامش هم بسیار بیشتر یاد خواهید گرفت و هم کاری خواهید کرد که کارفرما از شما راضی خواهد بود.

معمولا شرکت ها از شما خواهند خواست اطلاعات تماس کارفرماهای قبلیتان را برای reference به آن ها بدهید تا در باره شما از آن ها سوال کنند. این کار معمول است و شما اگر خوب کار کنید باید خوشحال هم شوید ولی به همین دلیل سعی کنید برای کسانی کار کنید که دانش خوبی دارند و به اشتباه و به خاطر ضعف خودشان گمان نمی کنند که شما کارتان را بد انجام داده یا می دهید. البته من با این تصور این را می گویم که شما کارتان را خوب انجام می دهید و اگر از پس کاری بر نیایید صادقانه می گویید و حتی جریمه مادیش را نیز در صورت لزوم متحمل می شوید. من بخش زیادی از کارهای ایرانیم را از کسی گرفتم که اولین پروژه اش را کنسل کردم چون در زمانی که می خواست امکان انجامش را نداشتم. سه روز از شروع پروژه گذشته بود و من پیش پرداخت را سریع بازگردانده و خواستم جریمه هم بدهم که پذیرفته نشد. اعتمادی بین من و صاحب پروژه شکل گرفت که با گذشت بیش از 7 سال هنوز برای خیلی کارها با من مشورت می کند و پروژه های مختلفی را هم برایش انجام داده ام.

گرفتن پروژه از کارفرماهای کشورهای فقیرتر معمولا ساده تر است و مهارت کمتری لازم دارد ولی کیفیت پروژه ها هم پایینتر است و معمولا رزومه خوبی برایتان نیست. آن را فقط در ابتدا و هنگام ضرورت انجام دهید. کشورهای آسیای شرقی به جز ژاپن و کره جنوبی و کشور های دیگر آسیایی و آفریقایی از این دسته هستند. گرفتن کار از آمریکا هم به دو دلیل سختتر از اروپاست. یکی ممنوعیت قانونی آن ها و دوم اختلاف ساعتی که می تواند تعامل را سخت کند. البته بسته به این که تیم سازنده اصلی در غرب یا شرق آمریکا باشد ساعاتی که با هم بیدار هستید و کار می کنید می تواند بین 2 تا 6 ساعت از روز باشد (فرض کردم تا 10 شب حاضرید بمونید سر کار).

از سایت هایی که پروژه ها در آن ها قرار می گیرند فقط upwork/oDesk خوب هستند که اگر کسی از خارج برایتان حساب باز نکند که بتواند ثابت کند در آن کشور است به راحتی بلاک خواهید شد. معمولا بهترین کارها را از انجمن های نرم افزارهایی که با آن ها کار می کنید و جاهایی مثل بخش شغل های stack overflow خواهید گرفت زیرا اعضای اصلی صنعت بیشتر در این مکان ها دنبال نیرو می گردند. در باره مدل سازی و آرت ظاهرا موضوع مقداری متفاوت است که من اطلاع چندانی از آن ندارم. معمولا کسانی در odesk و ... کار قرار می دهند که بیرون صنعت هستند و یا برای سازمانشان / مدرسه شان نیاز به بازی دارند و یا پولی دارند و دوست دارند بازی بسازند و دانششان به زیر صفر میل می کند و گاهی شیرجه می زند که بسیار خطرناک است.


این پست خیلی طولانی شد، احتمالا بعدا از تجربه کار هایم به شکل موردی خواهم نوشت و قصه خواهم گفت.

۱۵ دی ۹۶ ، ۲۳:۴۹ ۲ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

voxel چیست؟

در چند وقت گذشته بیش از پیش با موجودیتی به نام voxel کار کرده ام و گاه گاه مطالبی راجع به آن در تویتر فارسی خودم و یا تویتر انگلیسیم به اشتراک گذاشته ام. سوالات فردی در تویتر من را بر آن داشت که کمی راجع به آن ها در یک پست توضیح دهم.
یک واکسل توضیح دهنده یک نقطه در فضای سه بعدی است. مثل پیکسل که یک نقطه در فضای دو بعدی یک تصویر را شرح می دهد، واکسل هم یک نقطه در فضای سه بعدی را شرح می دهد. معروفترین بازی که از این مفهوم استفاده می کند Minecraft است اما voxel ها لزوما نباید مربع باشند. توضیح یک واکسل می تواند شامل نرمی سطح و normal های آن نقطه از سطح و حتی مختصات UV برای texture باشد. voxel ها برای تعریف یک شکل در فضای سه بعدی مورد استفاده قرار می گیرند. برای نمایش معمولا با الگرویتمی یک سیستم بر پایه voxel را به مدلی بر پایه مش های معمول (بر پایه polygon) تبدیل می کنند و render می کنند. در واقع در یک مدل بر پایه voxel به جای تعریف یک سری polygon که شکل را تشکیل می دهند از مقدار دادن به خانه های یک grid سه بعدی استفاده می کنید. دقت کنید که این خانه ها الزاما نباید مکعب باشند.
شاید از خود بپرسید چرا باید مدل و فضا را در فضای voxel تعریف کنیم و هنگام نمایش به mesh تبدیل کنیم. voxel ها به جز بازی ها در نرم افزارهای پزشکی و ... نیز کاربرد دارند. دلایل مختلفی برای جذاب بودن voxel ها در domain های مختلف موجود است. در بازی ها اگر شما قصد داشته باشید که با کد و به شکل procedural دنیای بازی را تغییر دهید و مثلا به کاربر امکان کندن زمین یا ساختن سازه را بدهید. voxel ها کار ساخت ابزار برای کاربران را بسیار ساده می کنند و هم پیاده سازی شما بسیار ساده می شود و هم کاربران بسیار ساده با ابزارهایتان ارتباط برقرار می کنند. ساخت همه ابزارهای voxel based بر پایه مش های معمولی هم ممکن است اما این کار بسیار سخت و پیچیده می شود.
همچنین اگر شما بخواهید بر اساس یک الگوریتم دنیای خود را تولید کنید و مثلا کوه و دره و رود و ... بسازید. voxel ها از بهترین روش های برای نگهداری داده مربوط به دنیا برای تغییر ساده و تبدیل ساده به mesh هستند.
جذابیت دیگر voxel ها این است که به راحتی می توانید voxel های دورتر از دوربین را با detail کمتری برای کاربر به مش تبدیل کنید و همچنین می تواین به سادگی با داشتن یک درخت octree و ماتریس خلوت voxel ها ، تشخیص دهید با در نظر گرفتن موقعیت فعلی کاربر باید کدام بخش از دنیای واکسلی را به مش تبدیل کنید.
واکسل ها به جز این جذابیت ها دارای مشکلاتی هم هستند. اگر شما بخواهید دنیایتان را از تعداد زیادی voxel بسازید نیاز دارید که حافظه زیادی را برای voxel ها مصرف کنید و همچنین کار با آن ها در game enegine های آماده معمول دارای چالش هایی است زیرا این برنامه ها برای تولید مش و کلا محتوا در real-time بهینه نشده اند. مثلا در UE4 و Unity شما نمی توانید در thread هایی به جز thread اصلی بسیاری از کارها مثل تولید mesh مربوط به سیستم collision را انجام دهید و فقط می توانید آرایه vertex ها را در threadی دیگر بسازید و برای تبدیل آن به مش و نسبت دادنش به scene باید منتظر وقت خالی در thread اصلی بمانید و آن را بلاک کنید. همچنین واکسل ها پشتیبانی خوبی از انیمیشن اسکلتی ندارند و شما نمی توانید به راحتی یک مدل را در فضای واکسل انیمیت کنید و از آن رندر بگیرید. به روز کردن مش برای هر فریم بسیار کند است و الگوریتم های موجود دیگر هم بهینه نیستند (sub-optimal هستند).
۰۲ دی ۹۶ ، ۱۶:۳۹ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

پیچیدگی ذاتی، پیچیدگی تصادفی

در فرایند تولید نرم افزار دو نوع پیچیدگی وجود دارد. پیچیدگی ذاتی (essential complexity) به نوعی از پیچیدگی گفته می شود که در ذات برنامه است و از مساله ای که حل می شود نشعت می گیرد. مثلا اگر قرار است برنامه شما سه مساله خاص را حل کند، این سه مساله از پیچیدگی های ذاتی برنامه هستند. نوع دیگر پیچیدگی نوع تصادفی است (accidental complexity) که به پیچیدگی هایی گفته می شود که مهندسان تولید کرده و در ذات مساله قرار ندارند. مثلا پیچیدگی استفاده از زبان های سطح پایین مثل assembly، ویرایش یک فایل با format بسیار پیچیده و یا طول کشیدن فرایند تست از پیچیدگی های تصادفی هستند.

این مطلب در مقاله بسیار مشهور no silver bullet فرد بروکس مورد بررسی قرار می گیرد. بروکس مطرح می کند که پیچیدگی های ذاتی برنامه ها تا حد زیادی حل شده اند و برای پیشرفت های شدید در هر ده برابر بهتر شدن، باید چندین متد مختلف و با قدرت زیاد تولید شوند.

مساله ای که من در این جا قصد مطرح کردنش را دارم مطالب درون مقاله نیست، بلکه می خواهم در باره اهمیت این موضوع صحبت کنم که ما به عنوان برنامه نویس بتوانیم پیچیدگی های تصادفی را تشخیص دهیم و در مواقع لازم ابزار های مناسب برای رفع این پیچیدگی ها را تولید کنیم. اگر پیچیدگی های تصادفی جلوی پیشرفت کار را بگیرند، ما در رقابت از کسانی که این پیچیدگی ها را برای خود حل کرده اند عقب خواهیم ماند و همچنین تولید نرم افزار برایمان کند خواهد شد. استفاده از  ابزار های نوشته شده خاص برای پروژه، نوشتن تست، Continuous integration ، استفاده از زبان های مناسب و framework ها مناسب برای مساله ای که آن را حل می کنیم و بسیاری موارد دیگر از این دسته ملاحظات هستند.

برنامه نویس های مختلفی را دیدم که از ابزار های اشتباه و روش هایی برای انجام کاری استفاده می کنند و آن وقت به علت اشتباه خود مساله را پیچیده می یابند. برنامه نویسی دیدم که چون با زبان جاوا کد می زد و کامپایل کردن یک پکیج برایش سخت شده بود. به این دلیل تصور می کرد که برنامه نویس بسیار خوبی است و کارهای پیچیده ای انجام داده است. همچنین برنامه نویسی دیگر را در جایی دیدم که به جای انجام یک کار تکراری به شکل خودکار با یک ابزار آن را دستی انجام می داد و ایراد می گرفت که او نباید این کار را انجام دهد. به خاطر می آورم که در گذشته خودم کارهای مختلفی را از روش سخت انجام داده ام و به همین دلیل پروسه انجام کار برایم سخت به نظر آمده بوده است. مثلا یک بار به جای visualize کردن یک سری داده برای درک بهتر با نوشتن آن در فایل به شکل آرایه ای دو بعدی از اعداد سعی می کردم آن را debug کنم که یافتن مشکلی ساده را برایم سخت کرد. و یا همین چند روز پیش به علت انتخاب کردن config اشتباه در visual studio هنگام کار با پروژه ، حدود یک ساعت تمام log های visual studio را برای یافتن اشکالی که اصلا وجود نداشت طلف کردم. اگر کدی نوشته بودم که پروژه ام انتخاب config اشتباه را به من گزارش دهد، امکان وجود این خطا اصلا وجود نداشت.

به همین دلیل یادگیری کار با سیستم های build محیطی که با آن کار می کنید و editor های مربوطه مثل Unity و visual studio برای هر برنامه نویس جدی لازم است. من خود چندان با ساخت extension برای visual studio آشنا نیستم. اندکی اطلاعات دارم ولی هرگز چیز جدی با آن نساخته ام. قصد دارم به زودی ضعف خود را در این زمینه جبران کنم. خوشبختانه در Unity تجربه نسبتا زیادی در ساخت اسکریپت های editor دارم و بارها برای کارهای مختلف در پروژه های مختلف ابزار های، ویرایش داده، ساخت build و ... ساخته ام. این کار به کم شدن اشتباهات و از بین بردن پیچیدگی های تصادفی کمک می کند.

۱۳ مهر ۹۶ ، ۰۱:۴۳ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

توابع محض (pure functions)

بیشتر وقت برنامه نویسان به debug کردن برنامه ها می گذرد. متوسط تعداد خط کد نوشته شده توسط بیشتر برنامه نویسان حدود 20 خط در روز است. دلیل این امر صرف شدن بیشتر وقت برای debugging می باشد. دلایل مختلفی باعث به وجود آمدن ایراد در برنامه می شود و روش های مختلفی برای رفع کردن این ایراد ها وجود دارد.

یکی از مهمترین دلایل ایراد در برنامه ها که در این پست راجع به آن صحبت می کنم وضعیت جاری نادرست در برنامه است. یعنی مثلا یک تابع فرض می کند که مقدار متغیری عمومی یا متغیری در یک نمونه از یک کلاس (instance)، باید عدد خاصی باشد ولی در شرایط فعلی به دلیلی مقدار اشتباهی در این متغیر قرار دارد. برای جلوگیری از این مشکل باید ابتدا مفهوم side-effect را بدانید. side-effect به معنای آن است که گاهی اوقات یک تابع علاوه بر گرفتن ورودی و دادن خروجی اثری بر روی متغیر های دیگر برنامه می گذارد. مثلا خواندن ورودی یک عمل دارای side-effect می باشد. اگر تابعی داشته باشید که برای شما زمان سیستم را بخواند و برگرداند و به علاوه مقدار متغیر latestReadTime را به روز کند که در توابع مختلف قابل دسترسی است، این تابع دارای side-effect است. اگر بخشی دیگر از برنامه با این فرض اجرا شود که مقدار درون lastReadTime حد اکثر 10 ثانیه کوچکتر از زمان حقیقی فعلی است و این زمان بیش از 10 ثانیه قبل به روز شده باشد، برنامه شما دچار مشکل خواهد شد.

همچنین اگر برای انجام کاری از متغیر های عمومی استفاده کنیم مشکل بالا رخ خواهد داد. مثلا همان lastReadTime یک متغیر عمومی است. اگر به جای استفاده از آن هر تابعی که به زمان نیاز دارد، مقدار زمان سیستم را بخواند، دیگر این مشکل پیش نخواهد آمد و دیگر هم نیازی نیست تابع خواندن زمان side-effect داشته باشد. به طور کل به توابعی که مقدار خروجیشان فقط و فقط از روی داده های ورودی مشخص می شود توابع محض و یا pure گفته می شود. این توابع نه متغیری عمومی در برنامه یا کلاس را عوض می کنند و نه با استفاده از متغیر های عمومی و کلاس خروجی خود را مشخص می کنند. مثلا تابع توان یا سینوس کاملا pure هستند. یافتن ایراد در توابع محض بسیار ساده است زیرا مقدار ورودی بررسی می شود و روش محاسبه خروجی نیز مشخص است. اگر تابع از state کلاس یا عمومی استفاده کند آن وقت باید اول متوجه شوید اثر متغیر عمومی در تابع چیست و مقدار متغیر عمومی به چه دلیل مقدار خاصی را گرفته است. یافتن رشته توابعی که باعث پیش آمدن حالت فعلی شده اند همیشه کار ساده ای نیست. این کار به خصوص در برنامه های شبیه سازی و بازی ها و هر برنامه concurrent دیگری بسیار مشکل است.

خوب است سعی کنیم از توابع محض برای بیشتر محاسباتمان استفاده کنیم، آبجکت هایی که به شکل مرجع (pass by reference) به ما داده می شوند را تا حد ممکن تغییر ندهیم و کاری کنیم هر تابع به خودی خود با ورودی هایش کار خود را انجام دهد. البته نوشتن کل برنامه به شکل تابع های محض نیاز به تکنیک های زبان های functional دارد که سرعت اجرا را پایین می آورند و سختی های خاص خود را نیز دارند ولی خیلی خوب است سعی کنیم تا جای ممکن از این توابع استفاده کنیم. من از زمانی که به این موضوع توجه کرده ام بسیار ایراد های کمتری به خاطر state اشتباه در برنامه هایم داشته ام. در زیر مثالی را می آورم که شاید مساله را روشنتر کند.

مثلا اگر می خواهیم آسیب ناشی از حمله به یک دشمن را حاسبه کنیم می توانیم تابع را درون دشمن نوشته و مقدار آخرین تیر خورده به دشمن و میزان healthش را در کلاس دشمن ذخیره کنیم و این تابع با استفاده از این متغیر ها میزان آسیب را حساب کند. در این شرایط شما نمی توایند دقیقا بفهمید چرا مقدار متغیر تیر خورده به دشمن مقدار خاصی دارد و چرا میزان health به حد کافی کم نشده اما اگر این مقدار ها به عنوان ورودی به تابع مربوط به محاسبه آسیب داده شوند آن گاه این تابع بدون توجه به وضعیت فعلی هر آبجکت دیگری می تواند مقدارش را حساب کند و درستی آن را بدون در نظر گرفتن وضعیت کل برنامه می توان امتحان کرد. بدتر از این مثال های بسیار پیچیده ای هستند که مقدار زیادی از state در متغیر های مختلف عمومی قرار داشته باشند که توابع آن ها را می خوانند و با آن ها کار می کنند. این کار باعث مشکل شدن debug برنامه می شود. باید سعی کنیم کلاس هایی کوچک با تعداد متغیر کلاس member variable بسیار کم داشته باشیم و همه توابع مقدارهای لازمشان را از ورودی بگیرند تا پس از یافتن جریان داده ها در برنامه (data flow) ، (که برای درک برنامه الزامی است) بتوانیم بفهمیم کجای سیستم آن طور که باید کار نمی کند. برای جلوگیری از مشکلات مربوط به performance بهتر است آبجکت های بزرگ را به شکل reference به توابع پاس دهیم ولی مقدار آن ها را تغییر ندهیم. در بعضی زبان ها مثل سی پلاس پلاس به علت امکان قرار دادن کلمه کلیدی const در آرگومان های تابع، می توانیم تغییرات را در زمان کامپایل تشخیص دهیم ولی در برخی زبان های دیگر یا باید دیسیپلین داشته باشیم و یا از ساختار های کتابخانه ها استفاده کنیم (مثل Immutable در سی شارپ).

در پست های آینده در باره روش های دیگر نوشتن کد کم خطا و مدیریت state بیشتر خواهم گفت.

۰۶ مهر ۹۶ ، ۰۰:۱۵ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

روان شناسی برنامه نویسی

تا به حال شده است با فکر کردن به کدتی که قبلا نوشته اید و یا پروسه ی فکرتان برای حل یک مساله یا برطرف کردن یک باگ فکر کرده باشید؟ آیا تا به حال به نوع ارتباطتان با برنامه نویسان دیگر هنگام خواندن و نوشتن کد و کامنت ها فکر کرده اید؟ آیا حس کرده اید که در قالب برخی زبان ها بهتر فکر می کنید و از بعضی ابزار ها استفاده بیشتری می کنید؟ همه این موضوع ها به روان شناسی برنامه نویسی مربوط می شود.

قصد داشتم در کنفرانس TGC یکی از دو مطلب ساخت سیستم های scalable و توضیع شده و یا روان شناسی برنامه نویسی را ارایه دهم که داوران موضوع اول را پذیرفتند و موضوع دوم مورد پذیرش قرار نگرفت. دوست دارم در این پست و شاید چند پست دیگر راجع به این موضوع که از موضوعات مورد علاقه من و از نظرم از موضوعات بسیار مفید برای برنامه نویسی خوب است، کمی صحبت کنم.

به تازگی با یکی از دوستانم بحث های فنی مختلفی راجع به انواع روش برنامه نویسی انجام می دهیم که کمک شایانی در زمینه فکر به این موضوعات به من کرده است. ابتدا با روان شناسی برنامه نویسی به شکل رسمی هنگام خواندن کتاب Code Complete آشنا شدم. این کتاب فصلی در باره اثر شخصیت بر برنامه نویسی داشت که توجه من را به این موضوع جلب کرد و کتاب بسیار عالی Psychology of computer programming را نیز به عنوان مرجعی جذاب معرفی کرد. همچنین کتاب The mythical man month هم از کتاب های خیلی خوب در این زمینه است که البته من این کتاب آخر را نخوانده ام و در لیست خواندنی هایم قرار دارد.

روان شناسی برنامه نویسی تلاش می کند تا کمک کند برنامه ها با هزینه کمتر، به موقع و با خطای کمتر تولید شوند، کارا باشند و قابل نگهداری باشند و در مقابل تغییر مقاومت نشان ندهند. برنامه نویسی یک کار ذهنی است و در واقع کمتر شغلی پیدا می شود که از علوم کامپیوتر و مهندسی نرم افزار کمتر فیزیکی باشد. برنامه نویسی فرایندی است که شامل خواندن و نوشتن کد، تفکر ، حل مساله، ارتباط برقرار کردن با دیگران، یادگیری، فهم و درک و ... است. برای بهتر برنامه نوشتن می توانیم برنامه نویسی و فهمیدن برنامه را از نظر ذهنی و روانی بررسی کنیم. این کار از دهه هفتاد میلادی آغاز شده است و در واقع psychology of computer programming و کتاب های دیگر به خوبی آن را تشریح می کنند. کتاب مهم دیگری به نام peopleware هم هست که بسیار زیبا این مطلب را مورد بررسی قرار می دهد. در زیر به برخی موارد جذاب راجع به روان شناسی برنامه نویسی اشاره می کنم و امیدوارم دوستان علاقه مند کتاب های مربوطه را بخوانند و از آن ها لذت ببرند.

باید بدون غرور برنامه نوشت egoless programming : این بدان معنا است که وقتی برنامه می نویسیم نباید فرض کنیم ایراد در کد ما یا پرسیدن سوال از دیگران شخصیتمان را پایین می آورد. باید فروتن باشیم و اگر چیزی را بهتر از بقیه می دانستیم آن را به دیگران آموزش داده و بدون تحقیر کردنشان به آن ها کمک کنیم. باید وقتی چیزی را نمی دانیم بی خود نظر های الکی ندهیم و رویش پا فشاری نکنیم. باید خودمان را موقع کد زدن فراموش کنیم و فقط به پیشرفت کارمان و پروژه که نهایتا به پیشرفت شخصیمان هم منتهی می شود فکر کنیم. باید عاشق کدمان و کارمان باشیم ولی خودمان را با کارمان و اشکالات و خبی هایش دقیقا یکی فرض نکنیم. حد اقل موقع تعامل با دیگران راجع به برنامه این کار را نکنیم :)

باید کد هر کس را دیگران review کنند: این کار بسیار معمول شده و امروزه در بسیاری از پروژه ها به خصوص پروژه های متن باز، این کار رخ می دهد. پس از آن که کسی تکه ای از یک قابلیت را پیاده سازی می کند و یا مشکلی را رفع می کند، دیگران کد او را بررسی می کنند. اشکالات مربوط به منطق برنامه، استفاده اشتباه از بخش های دیگر برنامه، فرضیات اشتباه، نام گذاری های نا مفهوم و الگوریتم های پیچیده و ... را در برنامه پیدا کرده و به نویسنده اصلی می گویند تا آن ها را رفع کند. ذهن ما وقتی از زاویه ای به مطلبی نگاه می کند در آن فرو می رود، به همین دلیل ذهنی جدید همیشه مسایلی را خواهد دید که ذهن اولیه ندیده است. همچنین فرد ممکن است در انجام برخی کارها تنبلی کند و یا از آن ها چشم  بپوشد و وجود review کمک می کند که این مشکل هم برطرف شود. ممکن است ما از سیستمی که کس دیگری در سیستم نوشته است به درستی استفاده نکنیم و این گونه خطا ها را افراد دیگر آشنا به بخش های دیگر برنامه سریع پیدا می کنند. ممکن است این کار اولش سخت باشد اما در صورتی که افراد به موضوع شخصی نگاه نکنند و میزان دانش افراد review کننده به حد کافی باشد این کار از مفیدترین کارهایی است که می توانید در تیم خود انجام دهید.

کد رسانه worm است: write once read many times هنگام نوشتن کد همیشه تصور کنید که کسی که آن را می خواند چه حسی خواهد داشت، آیا کد قابل فهم خواهد بود. کد بسیار بیش از آن چه نوشته می شود خوانده می شود، توسط نویسنده ای به جز نفر اصلی تغییر داده می شود. یک راه جالب این است که برنامه نویس بعدی یک بیمار روانی قاتل است که آدرس خانه شما را دارد. برنامه را طوری بنویسید که ناراحتش نکنید. خودتان فردا برای خودتان همان روانی مریض خواهید بود. بعد از یک ماه کد قدیمیتان را بخوانید تا ببینید طقریبا یک کد جدید محسوب می شود. ذهن سریع این چیز ها را فراموش می کند. ذهن ما در زمانی که درون یک مساله عمیق است همه جزیاتش را در حد توان در خود نگه می دارد اما این بخش از ذهن کند و کم حجم است و هر لحظه کارتان با مساله تمام شود پاک خواهد شد.

حواستان به خودتان باشد: شاید مهمترین حرفی که در این پست می زنم این باشد. به نظر من این عامل از مهمترین عامل های برنامه نویس بهتری شدن یا نشدن یک فرد است. ما باید به عنوان برنامه نویس سعی کنیم حواسمان باشد که داریم چه کاری را به چه گونه ای انجام می دهیم. مثلا چرا یک باگ را سریع فیکس کردیم و یا چرا نتوانستیم چیزی را سریع یاد بگیریم. فلان باگ را چه طور تولید کردم؟ اگر چه کار می کردم تولید نمی شد؟ باید چه کار می کردم که سریعتر بفهمم چه طور حلش کنم؟ این کار که به آن خود نگری یا Introspection گفته می شود از تکنیک های بسیار قوی برای برنامه نویس بهتری شدن است و توسط روان شناسان هم مورد استفاده قرار می گیرد. البته با introspection نمی توان آزمایش معتبر طراحی کرد ولی گاهی به ما سر نخ های بسیار مفیدی می دهد. بسیاری از روان شناسان موفق از این تکنیک سود زیادی برده اند زیرا ما بیش از آن که فکر می کنیم شبیه هم هستیم. با این کار برنامه نویسان دیگر و دلیل روش کد زدنشان، مدل برخوردشان با انتقاد و ... را نیز بهتر می فهمیم.

مساله آخر که بسیار مهم است صداقت است. یک برنامه نویس اگر صادق نباشد باید او را دور بیندازید. با او کار نکنید :) از بین ببریدش!! :)) دور از شوخی کار با کسی که صداقت ندارد. برای باگ هایش بهانه پیدا می کند. دلایل دروغین برای خوبی الگوریتمش پیدا می کند و الکی وانمود می کند چیزی را بلد است که بلد نیست، نظرات احمقانه می دهد و اگر نظراتش را قبول نکنید سعی می کند شخصیتتان را در تیم خراب کند کار بسیار سخت است. Intelectual honesty مساله بسیار بسیار مهمی است که در باره آن پستی مخصوص خواهم نوشت.

دوست دارم نظرات و تجربیات دیگران را در زمینه برخورد روان شناسانه با برنامه نویسی و نگاه به آن به عنوان یک علم انسانی را بدانم.

۰۱ مهر ۹۶ ، ۲۳:۲۴ ۱ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

ساخت object pool و خوبی ها و بدی هایش

نوشتن و خواندن در حافظه بسیار کند است و تخصیص آن توسط سیستم عامل و بازپس گیریش از آن هم کندتر است. در زبان های managed مثل جاوا و سی شارپ تخصیص حافظه به برنامه سریعتر است زیرا این کار از حافظه ای که خود framework/runtime برنامه از سیستم عامل گرفته صورت می گیرد. در عوض حافظه تخصیص داده شده باری است بر دوش Garbage Collector. به همین دلیل در تمام برنامه ها و به خصوص در یونیتی که GC چندان خوبی ندارند و از ورژن های قدیمی Mono استفاده می کند، برنامه نویسان سعی می کنند فشار روی GC را (برای جلوگیری از توقف برنامه برای garbage collection) کم کنند.

یکی از راه های کم کردن فشار بر روی سیستم های مربوط به حافظه allocate نکردن حافظه است که در واقع بهترین راه است. چون همیشه این کار ممکن نیست برنامه نویسان سعی می کنند از تکنیکی به نام Pooling استفاده کنند. در این روش تعدادی object از نوع مورد نظر allocate می کنند و هنگام نیاز از آن ها استفاده می کنند. به جز کم کردن میزان allocation ها و قرار دادن آن ها در زمانی مشخص این تکنیک برای object هایی که ساختشان بسیار هزینه بر است مثل database connection ها و ... نیز استفاده می شود. به طور کلی در محیط های managed تکنیک object pooling برای این دو کاربرد یعنی جلوگیری از allocation/deallocation های بی رویه و زیاد و نساختن مجدد object های هزینه بر استفاده می شود. معمولا توصیه می شود که فقط در صورتی این کار را انجام دهید که profiler به شما نشان می دهد که زمان برنامه برای allocation این object ها طلف می شود. این توصیه بیشتر راجع به .NET صدق می کند و هنگام نوشتن بازی mobile در Unity شما طقریبا همیشه نیاز دارید برای اجرای بازی روی گوشی های قدیمیتر با سرعت بالا object هایی که به تعداد زیاد از آن ها استفاده می کنید را pool کنید. وقتی می گویم طقریبا همیشه دارم حرف خطرناکی می زنم زیرا این موضوع بسته به قدیمیترین گوشی که می خواهید پشتیبانی کنید و نوع بازیتان متغیر است. خود بنده بازی های موبایلی را بدون هیچ گونه poolingی منتشر کرده ام ولی در ایران معمولا بازی ها گوشی های قدیمیتری را پشتیبانی می کنند و به همین دلیل در بازی هایی که خیلی خیلی casual و ساده نباشند معمولا به این تکنیک نیاز خواهید داشت.

در روش ساده ای از این تکنیک شما می توانید یک Dictionary<GameObject,List<GameObject>> pool داشته باشید که برای هر prefab به عنوان کلید، لیستی از Object های pool شده را نگه دارد. بهتر است کل pool را درون یک کلاس abstract کنید و هنگام ساخت object ها آن ها را از pool گرفته و SetActive(true) را برایشان صدا بزنید و هنگام از بین بردن یک object برای آن SetActive(false) صدا بزنید و آن را به لیست درون pool برگردانید. برای ساخت pool هایی از object هایی به جز GameObject باید خودتان آن را فعال و غیر فعال کنید. همچنین اگر برای reset شدن object ها نیاز به منطق خاصی است باید ساختاری در component هایتان برای صدا زدن این منطق قبل از ساخت آن و گرفتنش از pool پیاده سازی کنید. مثلا می توانید یک component به نام ResetableComponent داشته باشید با یک متد virtual که آن را بهنگام ساخت، برای object صدا می زنید.

در سرور ها شما معمولا object هایی که خیلی استفاده می شوند و مثلا برای serialization/deserialization داده و یا پاسخ گویی به درخواست ها کاربرد دارند را pool می کنید. به جز آن ها کانکشن های پایگاه داده و کلاینت های HTTP و ... نیز در بیشتر موارد pool می شوند. هنگام ساخت pool در کد های سرور خود باید profiler و لزوم ساخت pool را خوب بررسی کنید زیرا ممکن است که GC بسیار بهتر از شما حافظه را مدیریت کند. هم JVM و هم CLR و ماشین های مجازی خیلی زبان های دیگر بسیاری کارهای پیشرفته را برای مدیریت درست حافظه نسبت به عوامل مختلفی انجام می دهند ، برای همین زیاد برای ساخت pool عجله نکنید. همچنین این کار ممکن است باعث بروز باگ در سیستم شما شود و لزوما کارتان را راحت نمی کند.

pool ها باید چند ویژگی داشته باشند. اول آن که اگر به حد کافی object درونشان نبود بتوانند برای خود چند object اضافه بسازند و ذخیره کنند. دوم آن که باید در ابتدا با تعداد قابل پیکره بندی از object ها initialize شوند. سوم و بسیار مهم آن که پس از استفادهاز pool و تمام شدن کارش، تمام object های خود را برای پاک شدن توسط GC آماده کنند. چهارم که در سرور ها بسیار مهم است آن که هیچ poolی نباید بی نهایت بزرگ شود و شما باید در صورت نیاز نداشتن، object های اضافه ساخته شده در pool را پاک کنید و همچنین باید قابلیت reset کردن pool را هم داشته باشید. مثلا اگر pool شما دارای 64 عدد object است. برای دادن object به دیگر بخش های برنامه object کم می آورید و 32 object جدید می سازید و اندازه poolتان 96 عدد و بعد از مدتی مشاهده می کنید که مدت ها است که بیش از 80 object در pool خود دارید. بهتر است در این حالت بخشی از object های اضافه را پاک کنید و اندازه pool را دوباره به همان 64 تغییر دهید.

۳۰ شهریور ۹۶ ، ۱۷:۴۷ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

داستان باگی در بخش شبکه یونیتی در WebGL

از شروع برنامه نویسی به شکل جدی متوجه شدم که معمولا تمام باگ ها متعلق به کد خود من هستند و احتمال وجود باگ در نرم افزار هایی (عموما game engineهایی) که از آن ها استفاده می کنم خیلی خیلی کم است. حتی بحث های زیادی با دوستانم که با من کار می کردند و یا در دانشگاه با آن ها صحبت می کردم راجع به این موضوع داشتم. بعضی بچه ها تا برنامه کار نمی کرد گمان می کردند که مشکل در نرم افزار های مورد استفاده است در حالی که معمولا چنین نیست.

احتمال وجود باگ در کامپایلر ها بسیار کمتر از همه نرم افزار های دیگر، بعد از آن در سیستم عامل ها و بعد در کتابخانه های معروف باگ ها بسیار کم هستند. به هر حال مواقعی هستند که در این نرم افزار ها هم باگ پیدا می شود. شگفت انگیز است که در کامپایلر های معروف پر استفاده ترین زبان ها مثل C هم باگ (هر چند خیلی خاص و کوچک) بعد از سال ها استفاده یافت می شود. اما این موضوع نباید دلیل شود که کسی شک کند کامپایل یک حلقه for ساده با اشکال مواجه باشد. من این مورد را دیده ام و بزرگ نمایی نمی کنم. معمولا باگ ها هنگام تولید feature های جدید و یا در بخش هایی از یک بسته نرم افزاری که چندان مورد استفاده قرار نگرفته یافت می شوند و به سرعت هم برطرف می شوند.

زمستان دو سال پیش من در حال انتقال دو بازی آموزشی به کتابخانه نسبتا تازه شبکه یونیتی که به آن uNet می گویند بودم و قراردادی دو ماهه با شرکت صاحب بازی ها در New York داشتیم. بخش مربوط به webGL کتابخانه شبکه حتی کمتر از بخش اصلی آن تست شده بود و در داخل یونیتی هم کسی خیلی آن را تست نمی کرد. این بخش از WebSocket استفاده می کرد و کاملا از بقیه platform ها که بر پایه UDP بودند متفاوت بود. بازی ما به خوبی اجرا می شد ولی هر چند مسابقه یک بار در وسط بازی همه کلاینت ها disconnect می شدند. ما گمان کردیم که مشکل در کد خودمان است و قبل از چک کردن این موضوع میزان مصرف پهنای باند بازیمان را (که FPS و بسیار سریع بود) تا حد توانمان در زمان محدود پایین آوردیم. ما به این کار به دلایل دیگر هم نیاز داشتیم زیرا WebSocket همواره داده ها را reliable ارسال می کند و برای ساخت بازی FPS خیلی مناسب نیست. مشکل کم شد ولی برطرف نشد. پس از چند هفته بررسی و صحبت با یکی از همکارانم به اسم جکی که از مهندسان اصلی EVE Online بوده و ... گمان کردیم که Nagle Algorithm دلیل مشکل است. مهندسان یونیتی سخت پذیرفتند که آن را disable کنند در حالی که برای بازی ها این کار بسیار معمولی است. پس از بررسی های بیشتر لاگ سرور متوجه شدم یونیتی در سرور errorی لاگ می کند و بعد همه قطع می شوند. error را در گوگل جست و جو کردم که به سایز بافر دریافت داده در کتابخانه WebSocket مورد استفاده یونیتی مربوط می شد. پس از ارسال ناموفق چند پکت داده های ما از 4k بزرگتر می شد و باعث buffer overflow می شد. مهندسان یونیتی امکان تغییر سایز بافر را برای ما ضافه کردند تا ما بتوانیم برای هر کلاینت از بافر بزرگتری استفاده کنیم. سایز این بافر هم نمی تواند خیلی بزرگ باشد زیرا باعث موفقیت آمیز شدن نوع ساده ای از حملات DOS می شود. هر سرور در بازی ما حد اکثر 16 بازی کن را در خود جای می داد و به همین دلیل ما می توانستیم بافر هر کس را به سادگی 12k و یا حتی 16k در نظر بگیریم. اگر قرار باشد یک سرور 20000 کلاینت همزمان را در خود جای دهد، هر 10k بافر اضافه به معنی حدود 195MB حافظه اضافه خواهد بود.

به طور کلی وجود باگ در نرم افزارهایی که ما از آن ها استفاده می کنیم بسیار بدتر از وجود باگ در نرم افزار خودمان است. درست است که زحمت برطرف کردن مشکل گردن کس دیگری می افتد ولی زمان انجام این کار و کیفیتش دست ما نخواهد بود و گاهی این موضوع خیلی حیاطی است. در کیس ما ، بازی باید به مدارس بخش بزرگی از آمریکا فروخته می شد و زمان خرید مدارس تا تاریخ معینی بود و اگر ما بازی را در زمان مناسب به دست مدارس نمی رساندیم ، دیگر آماده شدن بازی فایده ای نداشت. بدی مشکل هم این جا بود که مشکل قطعی فقط وقتی بیش از 5-6 بازی کن از جاهای مختلف و نسبتا دور از هم به سرور وصل می شدند اتفاق می افتاد. اگر local تست می کردیم و یا 5 نفر از یک جا به سرور وصل می شدند معمولا در ارسال پکت ها اختلال کمتر بود و این مشکل پیش نمی آمد. به همین دلیل برای تست کردن یک fix باید چندین نفر از جاهای مختلف کلاینت را اجرا می کردند. راه دیگر داشتن یک ابزار load test نسبتا پیچیده بود که وقت تولید آن را نداشتیم. کل زمان پروژه برای من و برای تبدیل از کتابخانه شبکه uLink به uNet دو ماه بود که به علت وجود این باگ حدود سه ماه طول کشید تا کل پروژه جمع شد. اگر باگ در نرم افزار خودمان بود احتمالا سه هفته از این زمان کم می شد. متقاعد کردن مهندسین یونیتی برای امتحان کردن پروژه ما و یافتن باگ کار سختی بود زیرا نیاز به پروژه ای کوچک بود که مشکل را به سادگی نشان دهد. اگر خودم مشکل آن ها را به شکل دقیق پیدا نمی کردم، معلوم نبود که یکی دو ماه بیشتر طول بکشد یا نه. در ضمن پس از آماده شدن فیکس مربوط، review ها در یونیتی بیش از 2 هفته طول کشید و branch این fix با نسخه اصلی merge نمی شد. مهندسی که با ما کار می کرد سعی کرد با ارسال custom build کار ما را سرعت ببخشد ولی این کار هم دارای مشکلاتی بود و نهایتا ما صبر کردیم تا یک patch release با fix مورد نیاز ما بیرون بیاید. در تمام این مدت آرزو می کردن کاش باگ در کد خودم بود. البته پس از آن هم با مهندس شبکه یونیتی دوست شدم و هم با صاحبان پروژه ای که رویش کار می کردم رابطه ام بسیار بهتر شد و خاطره خوبی برای همه به جا ماند.

۲۵ شهریور ۹۶ ، ۰۰:۱۹ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده

Garbage Collector چیست و چه انواعی دارد؟

در سال های ابتدایی برنامه نویسی معمولا دانشجو ها با برنامه های کوچک سر و کار دارند. در سال های ابتدایی کار هم معمولا بخش های کوچکی از یک برنامه را می نویسند و یا با زبان های سطح بالا کار می کنند که مدیریت خودکار حافظه دارند. در زبان هایی مثل C/C++ Assembly و ... شما باید خودتان حافظه را مدیریت کنید و اگر به حافظه پویا dynamic memory نیاز داشته باشید باید خودتان آن را از سیستم عامل بگیرید. در زبان هایی که مدیریت حافظه خودکار دارند مثل Java, C#, Python, Go و ... مدیریت حافظه برای شما به طور خودکار صورت می گیرد.

بخشی از runtimeی که برنامه شما را اجرا می کند، مثلا virtual machine مربوط به Java و یا CLR (.NET) به نام Garbage Collector یا همان GC برای شما حافظه را مدیریت می کند. این کار با دو الگوریتم کلی در زبان های تجاری و غیر دانشگاهی اتفاق می افتد. یک نوع Mark and sweep GC (tracing) و نوع دیگر Automatic reference counting GC . بیشتر زبان های معروف از نوع اول استفاده می کنند و زبان هایی مثل Objective-C و Erlang از Automatic reference counting استفاده می کنند. در زبان هایی مثل سی پلاس پلاس و برخی کتابخانه ها و framework های سیستم عامل ها (مثل COM) از reference counting برای مدیریت برخی منابع استفاده می شود.

در روش reference counting شما برای هر assignment و خارج شدن متغیر ازscope یا ست کردن متغیر به null یکی به تعداد reference های یک Object اضافه و یا کم می شود. هر گاه تعداد reference های یک Object صفر شود می توانید آن را از حافظه پاک کنید. این روش باعث می شود هر assignment و خروج متغیر از scope کندتر از یک زبان mark and sweep GC اتفاق بیفتد ولی به طور کلی هر کدام از این دو روش می توانند در شرایط مختلف سریعتر از روش دیگر باشد. در این روش یک فیلد در حافظه خود object تعداد reference ها را می شمارد و پس از صفر شدن destructor را صدا زده و سپس object حافظه خود را به سیستم پس می دهد. در این روش اگر reference حلقه ای بین object ها وجود داشته باشد دیگر هیچ کدام از آن ها از حافظه خارج نمی شوند. به همین دلیل نوع دیگری از reference به نام weak ereference وجود دارد که باعث زیاد شدن تعداد reference های object نمی شود ولی object از وجود آن با خبر است و در پایان عمرش آن را به null ست می کند. این روش به طور کلی کمی سرعت اجرای برنامه را پایین می آورد و در عوض میزان کارایی برنامه کاملا deterministic بوده و هرگز وسط اجرا pause اتفاق نمی افتد و همه thread ها برنامه را اجرا می کنند.

در روش Mark And Sweep یا Tracing محیط اجرای برنامه یا همان runtime هنگام تخصیص حافظه به تمام متغیر های static و متغیر های عمومی و متغیر های قابل دسترسی در گراف برنامه از ریشه نگاه می کند و چک می کند کدام object از لیست object های allocate شده دیگر قابل دسترسی نیست و آن را پاک می کند. این روش می تواند باعث توقف اجرای برنامه یا حد اقل مشغول شدن بعضی از thread ها شود. معموملا این کار در زبان های پیشرفته مثل جاوا و سی شارپ به شکل generational صورت می گیرد که سرعت کار را بالا می برد.

در یک generational GC آبجکت ها ابتدا در gen 0 قرار می گیردند و هنگام اسکن کردن برای یافتن حافظه اضافه GC شما ابتدا gen 0 را بررسی می کند و اگر حافظه لازم را کسب کرد دیگر به اسکن لیست های بزرگتر gen 1 و gen 2 و ... نمی رود که احتمالا object های قدیمی در آن ها هستند که فعلا هم مورد استفاده و لازم هستند. اگر یک object یک بار در gen 0 زنده ماند به gen 1 منتقل می شود و اگر در یک اسکن از gen 1 زنده ماند به gen 2 می رود. این الگوریتم می تواند در محیط های مختلف به شکل های مختلف اجرا شود. در .NET شما دارای 3 generation هستید که با اعداد 0 و 1و 2 مشخص می شوند و object های بزرگتر از 80k هم به Large Object Heap می روند و طقریبا مثل gen 2 با آن ها برخورد می شود.

برای دیدن مقایسه کلی از این دو روش به این لینک مراجعه کنید.
برای آشنایی بیشتر با GC درون دات نت این لینک را ببینید.
در جاوا GC های مختلف با تعداد بالایی نتظیمات وجود دارد که می توانید گوگل را برای یافتن آن ها جست و جو کنید.

برنامه نویسان Unity دقت کنند که این engine از آخرین نسخه GC در Mono استفاده نمی کند و همچنین GC مونو با دات نت فرق دارد و GC موجود در Unity اصلا generational نبوده و لیست همه Object ها را یک جا اسکن می کند و به این دلیل بسیار کندتر می باشد. دلیل این که Unity در حال معرفی Native Collection در C# Job system است خلاص شدن از شر GC است.

۱۶ شهریور ۹۶ ، ۱۵:۳۲ ۰ نظر موافقین ۰ مخالفین ۰
اشکان سعیدی مزده