Architecture Decision Record

Active theme: Light

← مثال‌های رکورد تصمیم

زبان‌های برنامه‌نویسی

فهرست مطالب:

خلاصه

مسئله

باید زبان‌های برنامه‌نویسی را برای نرم‌افزار خود انتخاب کنیم. دو نیاز اصلی داریم: یک زبان برنامه‌نویسی فرانت‌اند مناسب برنامه‌های وب، و یک زبان برنامه‌نویسی بک‌اند مناسب برنامه‌های سرور.

تصمیم

TypeScript را برای فرانت‌اند انتخاب می‌کنیم.

Rust را برای بک‌اند انتخاب می‌کنیم.

وضعیت

تصمیم گرفته شد. برای جایگزین‌های جدید هنگام پیدایش‌شان آماده‌ایم.

جزئیات

مفروضات

برنامه‌های فرانت‌اند معمولی هستند:

  • کاربران و تعامل‌های معمولی

  • مرورگرها و سیستم‌های معمولی

  • توسعه‌ها و استقرارهای معمولی

احتمالاً برنامه‌های فرانت‌اند به‌سرعت تکامل می‌یابند:

  • می‌خواهیم توسعه‌ها، استقرارها، تکرارها و غیره سریع و آسان باشند.

  • به اثبات‌پذیری، مانند ایمنی نوع، ارج می‌نهیم و برای دستیابی به آن انجام کمی کار بیشتر برایمان مشکلی ندارد.

  • به سازگاری با نسخه‌های قدیمی نیازی نداریم.

برنامه‌های بک‌اند بالاتر از معمول هستند:

  • اهداف بالاتر از معمول برای کیفیت، به‌ویژه اثبات‌پذیری، قابلیت اطمینان، امنیت و غیره.

  • اهداف بالاتر از معمول برای نزدیکی به بی‌درنگ، یعنی نمی‌خواهیم به دلیل زباله‌روبی ماشین مجازی توقف داشته باشیم.

  • اهداف بالاتر از معمول برای برنامه‌نویسی تابعی، به‌ویژه برای موازی‌سازی، پردازش چندهسته‌ای و ایمنی حافظه.

سرعت کمتر زمان کامپایل را به نفع ایمنی زمان کامپایل و سرعت زمان اجرا می‌پذیریم.

قیود

محدودیت شدیدی بر زبان‌هایی داریم که با خدمات ارائه‌دهندگان بزرگ ابری برای توابع، مانند Amazon Lambda، قابل استفاده‌اند.

مواضع

این زبان‌ها را بررسی کردیم:

  • C

  • C++

  • Clojure

  • Elixir

  • Erlang

  • Elm

  • Flow

  • Go

  • Haskell

  • Java

  • JavaScript

  • Kotlin

  • Python

  • Ruby

  • Rust

  • TypeScript

استدلال

خلاصه برای هر زبان:

  • C: به دلیل ایمنی پایین رد شد؛ Rust تقریباً همه‌چیز را بهتر انجام می‌دهد.

  • C++: چون شلوغ‌پلوغ است رد شد؛ Rust تقریباً همه‌چیز را بهتر انجام می‌دهد.

  • Clojure: مدل‌سازی عالی؛ بهترین تقریب Lisp؛ زمان اجرای عالی روی JVM.

  • Elixir: زمان اجرای عالی شامل قابلیت استقرار و همروندی؛ تجربهٔ توسعه‌دهندهٔ عالی؛ اکوسیستم نسبتاً کوچک.

  • Erlang: زمان اجرای عالی شامل قابلیت استقرار و همروندی؛ تجربهٔ توسعه‌دهندهٔ چالش‌برانگیز؛ اکوسیستم نسبتاً کوچک.

  • Elm: بسیار امیدبخش به نظر می‌رسد؛ IBM مطالعات موردی بزرگی با نتایج خوب منتشر می‌کند؛ اکوسیستم کوچک‌تر.

  • Flow: بهبودی جالب نسبت به JavaScript؛ با این حال؛ توسعه‌دهندگان از آن دور می‌شوند.

  • Go: تجربهٔ توسعه‌دهندهٔ عالی؛ همروندی عالی؛ اما سابقهٔ تصمیم‌های بدی که زبان را فلج می‌کنند.

  • Haskell: بهترین زبان تابعی؛ جامعهٔ توسعه‌دهندگان کوچک‌تر؛ به اندازهٔ کافی موفقیت‌های تولیدی منتشرشده به دست نیاورده است.

  • Java: زمان اجرای عالی؛ اکوسیستم عالی؛ تجربهٔ توسعه‌دهندهٔ زیر متوسط.

  • JavaScript: محبوب‌ترین زبان تاریخ؛ گسترده‌ترین اکوسیستم.

  • Kotlin: بسیاری از مشکلات Java را رفع می‌کند؛ پشتیبانی عالی JetBrains؛ موارد منتشرشدهٔ خوب انتقال از Java به Kotlin.

  • Python: محبوب‌ترین زبان برای مدیریت سیستم؛ ابزارهای تحلیلی عالی؛ چارچوب‌های وب خوب؛ اما Google آن را به نفع Go رها کرد.

  • Ruby: بهترین تجربهٔ توسعه‌دهندهٔ تاریخ؛ بهترین چارچوب‌های وب؛ دوست‌داشتنی‌ترین جامعه؛ اما بسیار کند؛ بسته‌بندی آن تا حدی دشوار است.

  • Rust: بهترین زبان جدید؛ تأکید بر صفر انتزاع؛ تأکید بر همروندی؛ با این حال اکوسیستم نسبتاً کوچک؛ و محدودیت‌های عمدی بر برخی انواع شتاب‌دهی کامپایلر، مثلاً دسترسی مستقیم به حافظه باید صراحتاً ناامن (unsafe) باشد.

  • TypeScript: نوع‌ها را به JavaScript اضافه می‌کند؛ ترنسپایلر عالی؛ تأکید رو به رشد توسعه‌دهندگان بر انتقال از JavaScript به TypeScript؛ پشتیبانی قوی Microsoft.

تصمیم گرفتیم VMها مجموعه‌ای از مصالحه‌ها دارند که اکنون به آن‌ها نیاز نداریم، مانند پیچیدگی اضافی که قابلیت‌های زمان اجرا فراهم می‌کند.

باور داریم تصمیم اصلی ما را دو دغدغهٔ فراگیر پیش می‌برند:

  • برای سریع‌ترین سرعت زمان اجرا و تنگ‌ترین دسترسی به سیستم، JavaScript و C را انتخاب می‌کنیم.

  • برای نزدیک به سریع‌ترین سرعت زمان اجرا و نزدیک به تنگ‌ترین دسترسی به سیستم، TypeScript و Rust را انتخاب می‌کنیم.

یادکرد شایسته به زبان‌های VM و چارچوب‌های وب که اگر زبان VM می‌خواستیم انتخاب می‌کردیم می‌رسد:

  • Clojure و Luminus

  • Java و Spring

  • Elixir و Phoenix

پیامدها

توسعه‌دهندگان فرانت‌اند باید TypeScript یاد بگیرند. اگر تجربهٔ اصلی توسعه‌دهنده استفاده از JavaScript باشد، این احتمالاً منحنی یادگیری آسانی است.

توسعه‌دهندگان بک‌اند باید Rust یاد بگیرند. اگر تجربهٔ اصلی توسعه‌دهنده استفاده از C/C++ باشد این احتمالاً منحنی یادگیری متوسطی است، و اگر تجربهٔ اصلی توسعه‌دهنده استفاده از Java، Python، Ruby یا زبان‌های مشابه با مدیریت خودکار حافظه باشد منحنی یادگیری دشواری است.

TypeScript و Rust هر دو نسبتاً جدیدند. این یعنی بسیاری از ابزارها هنوز برای این زبان‌ها مستندات ندارند. برای مثال، خط‌لولهٔ devops باید برای این زبان‌ها راه‌اندازی شود، و تاکنون هیچ‌یک از ابزارهای devops که ارزیابی می‌کنیم نمونه‌های پیش‌فرض برای این زبان‌ها ندارند.

زمان کامپایل برای TypeScript و Rust کاملاً کند است. بخشی از این ممکن است به دلیل جدید بودن زبان‌ها باشد. ممکن است بخواهیم بررسی کنیم چگونه زمان‌های کند کامپایل را کاهش دهیم، مثلاً با کامپایل بر حسب تقاضا، همروندی کامپایل و غیره.

پشتیبانی IDE برای این زبان‌ها هنوز فراگیر و درجه‌یک نیست. برای مثال، JetBrains برای Python IDE PyCharm را با پشتیبانی درجه‌یک می‌فروشد، اما IDE‌ای با پشتیبانی درجه‌یک برای Rust نمی‌فروشد؛ در عوض، JetBrains می‌تواند از افزونهٔ Rust استفاده کند که شاید 80% پشتیبانی زبان Rust را نسبت به پشتیبانی زبان Python فراهم می‌کند.

مرتبط

تصمیمات مرتبط

به سمت انتخاب‌های اکوسیستمی خواهیم رفت که با این زبان‌ها همسو هستند.

برای مثال، می‌خواهیم IDE‌ای انتخاب کنیم که قابلیت‌های خوبی برای این زبان‌ها دارد.

برای مثال، برای چارچوب وب فرانت‌اند خود، احتمال بیشتری دارد چارچوبی را انتخاب کنیم که به TypeScript گرایش دارد (مثلاً Vue) تا چارچوبی که به JavaScript ساده گرایش دارد (مثلاً React).

الزامات مرتبط

کل زنجیرهٔ ابزار ما باید از این زبان‌ها پشتیبانی کند.

مصنوعات مرتبط

انتظار داریم ممکن است برخی رازها را به متغیرهای محیطی صادر کنیم.

اصول مرتبط

دو بار اندازه بگیر، یک بار بساز. برخی ایمنی‌ها را بر برخی سرعت‌ها اولویت می‌دهیم.

زمان اجرا ارزشمندتر از زمان کامپایل است. استفادهٔ مشتری را بر استفادهٔ توسعه‌دهنده اولویت می‌دهیم.

توضیحات

هر توضیحی اینجا.