یادداشت‌های بک‌اند ۵: از پژوهش تانسوری تا مهندسی بک‌اند

یادداشت‌های بک‌اند ۵: از پژوهش تانسوری تا مهندسی بک‌اند

رزومه‌ام روی کاغذ شبیه رزومهٔ دو نفر است. یکی پایان‌نامهٔ کارشناسی ارشدش را دربارهٔ تجزیه‌های تانسوری برای کلان‌داده نوشته. دیگری بیش از ده سال با C#،‏ .NET و SQL Server در محیط عملیاتی کار کرده و این اواخر روی سامانه‌های آزمونی که ده‌ها هزار دانش‌آموز در یک دقیقه واردشان می‌شوند. من هیچ‌وقت این دو را دو مسیر شغلی جدا تجربه نکرده‌ام. عادت‌هایی که در پژوهش پیدا کردم همان‌هایی‌اند که موقع طراحی یا بازبینی یک بک‌اند بیشتر از همه به کارم می‌آیند،‏ و کار بک‌اند هم مدام شکل خواندن ریاضی را برایم عوض می‌کند.

این یادداشت دربارهٔ همین هم‌پوشانی است و بیشتر نظر شخصی است تا آموزش.

خط زمانی،‏ خیلی خلاصه

  • ۲۰۱۱ تا ۲۰۱۵: کارشناسی ریاضی کاربردی در دانشگاه ارومیه.
  • ۲۰۱۶ تا ۲۰۱۹: کارشناسی ارشد علوم کامپیوتر در دانشگاه تربیت مدرس. پایان‌نامه‌ام با عنوان «یادگیری کلان‌داده با نمایش تانسوری» به راهنمایی دکتر منصور رزقی،‏ روش tc-SVD را معرفی کرد. در سال ۲۰۱۸ و دوباره در ۲۰۲۰ تا ۲۰۲۱ دستیار آموزشی درس‌های یادگیری ماشین پیشرفته و داده‌کاوی بودم.
  • ۲۰۱۶ تا ۲۰۱۸: توسعه‌دهندهٔ دات‌نت در Withem،‏ یک شبکهٔ اجتماعی خصوصی برای بازیگران.
  • ۲۰۱۹: در امیدان حضور اپلیکیشن‌های React و React Native را از نو ساختم و APIهای REST نسخه‌دار با مستندات Swagger نوشتم.
  • ۲۰۲۰ تا ۲۰۲۱: به‌صورت فریلنس برای صرافی بانک رفاه سامانه‌ای ساختم که حسابداری حواله‌های ارزی را از صفحه‌گسترده به یک سامانهٔ تحت وب منتقل کرد،‏ با تمرکز بر پایداری،‏ یکپارچگی تراکنش‌ها و سازگاری داده‌های مالی.
  • ۲۰۲۱ تا ۲۰۲۳: در «گزینه دو»،‏ اول به‌عنوان برنامه‌نویس فول‌استک و بعد مهندس ارشد بک‌اند. سامانهٔ گزارش‌گیری را برای کم کردن بار پایگاه‌داده از نو طراحی کردم،‏ لاگ ساخت‌یافته با Serilog را جا انداختم،‏ ساختار Redis Sentinel را طراحی و راه‌اندازی کردم که در اوج آزمون‌ها ۴۵٬۰۰۰ تا ۷۰٬۰۰۰ کاربر هم‌زمان را تحمل می‌کرد،‏ و یک تیم چهارنفرهٔ علم داده را بنیان گذاشتم و رهبری کردم.
  • از اکتبر ۲۰۲۳: مهندس ارشد بک‌اند در NovaTech؛‏ معماری یک پلتفرم آزمون تطبیقی مبتنی بر IRT را طراحی کردم که حدود ۸۹٬۰۰۰ دانش‌آموز از آن استفاده می‌کنند،‏ توسعهٔ میکروسرویس‌های .NET 6/8 را رهبری می‌کنم و منتور دست‌کم پنج برنامه‌نویس هستم.
  • ۲۰۲۴: قرارداد دورکاری با Noraco برای خودکارسازی خط پردازش تبدیل PDF به LaTeX با برچسب‌گذاری به کمک مدل زبانی،‏ برای بیش از ۵٬۰۰۰ سؤال.

چهار عادت پژوهشی که با من به این کار آمدند،‏ تقریباً به ترتیبی که روش کارم را عوض کردند:

۱. به شکل داده احترام بگذارید

پایان‌نامه‌ام از یک گلایه شروع شد: روال رایج،‏ تصویر یا ویدیو را پیش از هر یادگیری‌ای به یک بردار بلند تبدیل می‌کند و در این راه همان ساختاری را دور می‌ریزد که داده را معنادار کرده بود. پیکسل‌های همسایه از هم دور می‌افتند. تانسور هر بُعد را به‌عنوان یک مُد جدا نگه می‌دارد و روش‌هایی که روی آن ساخته می‌شوند می‌توانند از این ساختار استفاده کنند،‏ به‌جای این‌که دوباره کشفش کنند.

سیستم‌های بک‌اند همین اشتباه را با لباس دیگری تکرار می‌کنند. همه‌چیز در یک جدول پهن می‌رود،‏ یا در یک ستون JSON،‏ یا در یک کلید کش که یک شیء بزرگ را نگه می‌دارد در حالی که هر فراخواننده فقط یک فیلدش را می‌خواند. سؤالی که در پژوهش یاد گرفتم مستقیم ترجمه می‌شود: این داده در عمل در راستای کدام محورها خوانده می‌شود؟ به ازای هر دانش‌آموز،‏ هر آزمون،‏ هر سؤال،‏ در طول زمان؟ این‌ها همان مُدها هستند و هر کدام خانهٔ متفاوتی را پیشنهاد می‌کند.

مثلاً در یادداشت آزمون تطبیقی،‏ سه نوع داده با شکل‌های کاملاً متفاوت کنار هم نشسته‌اند. پارامترهای سؤال کم‌حجم‌اند،‏ در هر درخواست خوانده می‌شوند و به‌ندرت عوض می‌شوند،‏ پس جایشان یک کش درون‌پروسه‌ای تغییرناپذیر است. برآورد توانایی یک جلسه آرایه‌ای کوتاه است که با هر پاسخ تغییر می‌کند،‏ پس جایش Redis با TTL است. پاسخ‌ها سند دائمی‌اند و جایشان SQL Server. اگر هر سه را با سیاستی یکسان در یک مخزن بگذارید،‏ دست‌کم برای یکی‌شان انتخاب اشتباهی کرده‌اید.

۲. به‌روز کنید،‏ از نو حساب نکنید

بخش عمده‌ای از ادبیات پژوهشی تجزیه‌های بزرگ‌مقیاس دربارهٔ یک چیز است: وقتی دادهٔ تازه می‌رسد،‏ می‌شود همان تجزیه‌ای را که داریم به‌روز کرد،‏ به‌جای این‌که از صفر دوباره حسابش کنیم؟ محاسبهٔ دوباره ساده و درست است و دقیقاً همان چیزی است که زودتر از همه مقیاس‌پذیری را از دست می‌دهد.

در کار بک‌اند این مفیدترین سؤالی است که می‌شناسم. برآورد توانایی در آزمون تطبیقی نمونهٔ خوبی است: توزیع پسین بعد از هر پاسخ همان توزیع پسین قبلی است ضرب در یک منحنی درست‌نمایی،‏ پس جلسه هیچ‌وقت تاریخچه‌اش را از اول مرور نمی‌کند. گزارش‌گیری جایی است که این عادت بیشتر از همه جواب می‌دهد. پیش از نوشتن کوئری‌ای که همه‌چیز را دوباره تجمیع می‌کند،‏ می‌پرسم از اجرای قبلی چه چیزی عوض شده و آیا می‌توانم فقط همان را به‌روز کنم. گاهی جواب منفی است،‏ چون داده به اندازهٔ کافی کوچک است یا اصلاحیه‌ها زیادند،‏ و یک محاسبهٔ کامل زمان‌بندی‌شده کاملاً کافی است. فقط می‌خواهم این تصمیمی باشد که کسی آگاهانه گرفته.

۳. صادقانه اندازه بگیرید

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

کار روی کارایی دقیقاً همین انضباط را لازم دارد و دور زدنش آسان است. در «گزینه دو» با تست‌های بار Locust گلوگاه‌ها را پیش از اوج آزمون‌ها پیدا می‌کردم و قاعده‌هایی که رعایت می‌کنم مستقیم از آزمایشگاه آمده‌اند: پیش از هر تغییری اندازه بگیرید،‏ هر بار فقط یک چیز را عوض کنید،‏ خط پایه را نگه دارید،‏ و به صدک‌ها نگاه کنید نه میانگین،‏ چون درخواست‌های کند در میانگین پنهان می‌شوند. بهینه‌سازی بدون اندازه‌گیری قبل و بعد فقط یک نظر است،‏ گاهی نظری خوب.

۴. ریاضیِ پشت ابزار را بخوانید

در پژوهش یاد می‌گیرید تا وقتی فرض‌های یک روش را نخوانده‌اید به آن اعتماد نکنید. نکتهٔ اصلی پایان‌نامهٔ خود من هم دقیقاً از همین جنس بود،‏ یک فرض پنهان: ضرب t بُعد سوم را طوری در نظر می‌گیرد که انگار دور خودش می‌چرخد؛‏ فرضی که برای بعضی داده‌ها بی‌ضرر است و برای تصویر بی‌صدا غلط.

ابزارهای عملیاتی هم فرض‌هایشان را پنهان می‌کنند و این فرض‌ها معمولاً در بدترین لحظه خودشان را نشان می‌دهند. تکثیر در Redis ناهم‌زمان است،‏ پس یک فیل‌اوور می‌تواند نوشتن‌هایی را که تأیید شده بودند از بین ببرد. انتخاب سؤال بر اساس بیشینهٔ اطلاعات،‏ سؤال‌های با قدرت تمیز بالا را بیش از حد به کار می‌برد،‏ چون تابع اطلاعات دقیقاً همین را پاداش می‌دهد. یک مدل زبانی توکن‌ها را از یک توزیع احتمال انتخاب می‌کند؛‏ دمای صفر تنوع را کم می‌کند،‏ اما در عمل خروجی را قطعی نمی‌کند. هیچ‌کدام از این‌ها راز نیست؛‏ در مستندات یا در ریاضی نوشته شده،‏ برای کسی که آن را مثل یک مقاله بخواند: اول دنبال فرض‌ها.

این دو مسیر چطور به هم کمک می‌کنند

روشن‌ترین نقطهٔ تلاقی تا امروز «گزینه دو» بود،‏ وقتی یک تیم چهارنفرهٔ علم داده را برای الگوریتم‌های رتبه‌بندی،‏ نمره‌دهی و پیشنهاد بنیان گذاشتم و رهبری کردم. کاری پژوهشی بود درون یک شرکت محصول‌محور،‏ و نتیجه‌هایش باید داخل همان سیستم‌هایی اجرا می‌شد که با اوج آزمون‌ها روبه‌رو بودند؛‏ همین کار را صادق نگه می‌داشت.

پلتفرم NovaTech همان تلاقی است از طرف دیگر. نظریهٔ سؤال–پاسخ تعیین می‌کند سیستم بعد از هر پاسخ چه چیزی را باید حساب کند؛‏ مهندسی تعیین می‌کند آیا می‌شود این کار را برای پلتفرمی که حدود ۸۹٬۰۰۰ دانش‌آموز از آن استفاده می‌کنند،‏ در لحظه‌هایی که بسیاری از آن‌ها هم‌زمان می‌آیند،‏ انجام داد. در Noraco نقطهٔ تلاقی یک مدل زبانی وسط یک خط پردازش داده بود،‏ و سال‌ها سروکار داشتن با درس‌های یادگیری ماشین بدبینیِ سالمی در من ساخته بود: یک مدل می‌تواند کاملاً مطمئن باشد و باز هم اشتباه کند،‏ و برای همین کنسول بازبینی را بخشی از خود خط پردازش می‌دانم.

تدریس هم در همهٔ این‌ها سهم داشت. دستیار آموزشی یادگیری ماشین پیشرفته و داده‌کاوی بودن مجبورم کرد چیزها را آن‌قدر دقیق توضیح بدهم که کس دیگری بتواند به کارشان ببرد،‏ و منتورینگ و تعیین استاندارد بازبینی کد هم بیشتر به همین برمی‌گردد.

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

چرا هر دو را نگه می‌دارم

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

به همین دلیل این سایت دو مسیر دارد. راهنماهای تانسور بخش پژوهشی را از ایده‌های پایان‌نامه‌ام به بعد ادامه می‌دهند و یادداشت‌های بک‌اند طرف دیگرند؛‏ هر دو را در نسخهٔ فارسی سایت پیدا می‌کنید. یادداشت بعدی به کار روزمرهٔ تولید برمی‌گردد: لاگ ساخت‌یافته با Serilog در ASP.NET Core.

این یادداشت به انگلیسی هم منتشر شده است: نسخهٔ انگلیسی.

بازگشت به همهٔ یادداشت‌ها