Codoloper

بلاگ

جدیدترین مطالب

آخرین مطالبی که در کدلپر منتشر شدن رو میتونی اینجا پیدا کنی

اخبار

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

Rust 1.97.0 منتشر شد نوشته شده توسط عرفان دهقانی

Rust 1.97.0 منتشر شد

۹ جولای ۲۰۲۶، تیم Rust نسخه‌ی ۱.۹۷.۰ رو منتشر کرد. این نسخه تغییرات زبانی بزرگی نداره، ولی سه چیزی که اضافه شده از اون دسته چیزهاییه که وقتی باهاشون کار می‌کنی، خوشحال می‌شی که هستن.

برای آپدیت:

rustup update stable

Symbol mangling v0 حالا پیش‌فرضه

این یکی یه تغییر زیرپوستیه که بیشتر وقت‌ها متوجهش نمی‌شی — تا وقتی که یه stack trace می‌گیری و یهو می‌بینی اسم functionها خوانا شدن.

وقتی Rust کد رو کامپایل می‌کنه، اسم هر item رو mangle می‌کنه تا با اسم‌های مشابه در crate‌های دیگه تداخل نداشته باشه. روش قدیمی از Itanium ABI که C++ هم ازش استفاده می‌کنه الهام گرفته بود — ولی مشکل داشت: generic parameterها فقط پشت یه hash پنهان می‌شدن، و بخش‌هایی از mangling از استاندارد Itanium منحرف شده بودن که همین باعث می‌شد demangler‌های خارجی درست کار نکنن.

روش جدید (v0) از Rust 1.59 به‌عنوان opt-in موجود بود، از نوامبر ۲۰۲۵ روی nightly پیش‌فرض شده بود، و حالا توی ۱.۹۷ به stable رسیده. نتیجه‌ی عملی: وقتی یه panic یا stack trace می‌بینی، اسم functionها همراه generic parameterهاشون نشون داده می‌شن، نه یه رشته‌ی hash‌شده‌ی نامفهوم.

روش قدیمی الان فقط روی nightly در دسترسه و برنامه اینه که در آینده کاملاً حذف بشه.

Cargo حالا warning‌ها رو مدیریت می‌کنه

تا قبل از این، رایج‌ترین راه برای deny کردن warning‌ها در CI این بود:

RUSTFLAGS=-Dwarnings cargo build

مشکل این روش اینه که -Dwarnings رو به هر invocation از rustc پاس می‌ده، و این build cache رو invalidate می‌کنه. یعنی هر بار که توی CI این flag رو داری، از کش استفاده نمی‌شه و همه چیز از صفر compile می‌شه.

از ۱.۹۷، Cargo خودش کنترل می‌کنه که warning‌ها چطور با موفقیت build تعامل داشته باشن. یه env var جدید اضافه شده:

# در CI: deny کردن warning‌ها
CARGO_BUILD_WARNINGS=deny cargo build

# موقع کار: خاموش کردن موقت warning‌ها
CARGO_BUILD_WARNINGS=allow cargo check

# حالت پیش‌فرض: نمایش بدون fail کردن
CARGO_BUILD_WARNINGS=warn cargo build

مزیت مهم اینه که این متغیر build cache رو invalidate نمی‌کنه. یعنی می‌تونی توی CI deny داشته باشی و همچنان از کش استفاده کنی. می‌شه با --keep-going هم ترکیبش کرد تا به‌جای توقف روی اولین خطا، همه‌ی خطاها و warning‌ها یکجا جمع بشن.

خروجی linker دیگه پنهان نمی‌شه

rustc وقتی کامپایل می‌کنه، یه linker رو از طرف کاربر صدا می‌زنه. تا الان اگه link موفق می‌شد، هر پیامی که linker داشت پنهان می‌شد. این رفتار گاهی مشکل‌ساز بود چون warning‌های واقعی linker — مثل deprecation warning برای یه optimization flag قدیمی — اصلاً دیده نمی‌شدن.

از ۱.۹۷، پیام‌های linker به‌صورت پیش‌فرض نمایش داده می‌شن:

warning: linker stderr: ignoring deprecated linker optimization setting '1'
  |
  = note: `#[warn(linker_messages)]` on by default

تیم Rust پیام‌هایی که false positive شناخته‌شده هستن رو فیلتر کرده تا نویز اضافه نداشته باشی. اگه یه پیام می‌بینی که فکر می‌کنی false positive هست، می‌تونی توی Cargo.toml آن را خاموش کنی:

[lints.rust]
linker_messages = "allow"

یه نکته مهم: این lint عمداً از گروه warnings جدا نگه داشته شده. یعنی CARGO_BUILD_WARNINGS=deny روی linker_messages تاثیر نمی‌ذاره — چون خروجی linker از پلتفرمی به پلتفرم دیگه فرق می‌کنه و نمی‌شه به‌طور قطعی همه‌شون رو deny کرد.

APIهای جدید stable شده

چند API مرتبط با bit manipulation اضافه شده که برای کدهای سطح‌پایین کاربردیه:

let x: u32 = 0b1010_1100;

// جدا کردن بیت بالایی
x.isolate_highest_one(); // => 0b1000_0000

// جدا کردن بیت پایینی
x.isolate_lowest_one(); // => 0b0000_0100

// مقدار بیت بالایی
x.highest_one(); // => 0b1000_0000

// مقدار بیت پایینی
x.lowest_one(); // => 0b0000_0100

// تعداد bitهای لازم برای نمایش مقدار
x.bit_width(); // => 8

همه‌ی این methodها روی NonZero<T> هم در دسترسن. char::is_control هم حالا توی context‌های const کار می‌کنه.

یه تغییر کوچیک برای کاربران WebAssembly

اگه با WebAssembly کار می‌کنی، یه breaking change هست که از نسخه‌ی ۱.۹۶ شروع شده: Rust دیگه به‌طور پیش‌فرض --allow-undefined به linker پاس نمی‌ده. یعنی symbolهای undefined الان linker error هستن، نه WebAssembly import‌های ضمنی. اگه intentional بود، باید صریح تعریفش کنی:

#[link(wasm_import_module = "env")]
unsafe extern "C" {
    fn my_extern_function();
}

این release از نظر حجم تغییرات زبانی یه نسخه‌ی آروم بود، ولی هر سه‌ی این تغییرها از اون دسته چیزهاییه که بعد از یه مدت کار کردن باهاشون، نفهمیدی چطور قبلاً بدونشون کار می‌کردی.

Muse Spark 1.1: متا وارد بازار API پولی شد نوشته شده توسط عرفان دهقانی

Muse Spark 1.1: متا وارد بازار API پولی شد

۹ جولای ۲۰۲۶، متا همزمان دو کار کرد: یه مدل جدید منتشر کرد و برای اولین‌بار پول گرفت. این دومی شاید مهم‌تر از اولی باشه.

متا سال‌ها روی open-source بود — Llama، Llama 2، Llama 3 — و هویتش رو روی این گذاشته بود که «ما مدل‌ها رو رایگان می‌دیم». Muse Spark 1.1 اولین مدل frontier متاست که پشت یه paid API قرار گرفته. این یعنی متا دیگه فقط یه تامین‌کننده‌ی مدل open-source نیست — داره مستقیم وارد همون بازاری می‌شه که Anthropic و OpenAI ازش پول در می‌آرن.

مدل چیه

Muse Spark 1.1 نسخه‌ی ارتقاءیافته‌ی Muse Spark اصلیه که اپریل ۲۰۲۶ منتشر شد — اولین مدل از Meta Superintelligence Labs، واحدی که Alexandr Wang (موسس Scale AI) رهبریش رو بر عهده داره. این مدل multimodal و reasoning-based هست و برای کارهای agentic طراحی شده: متن، تصویر، و ویدیو رو می‌فهمه، از ابزارها و سرویس‌های خارجی استفاده می‌کنه، کدنویسی و دیباگ می‌کنه، و می‌تونه وظایف چندمرحله‌ای رو با دخالت کمتر انسان انجام بده.

context window یه میلیون توکن داره، که برای کارهای agentic طولانی‌مدت عدد مهمیه. یه ویژگی هم که متا روش تاکید کرده اینه که مدل می‌تونه به‌جای اینکه sequential کار کنه، parallel subagent بزنه — یعنی چند بخش از یه task رو همزمان پیش ببره.

کجا قوی‌ترین، کجا عقب‌تر

متا روی benchmark‌هایی مثل MCP Atlas، JobBench، Humanity's Last Exam، و FinanceBench عملکرد خوبی نشون داده. MCP Atlas مخصوصاً مهمه چون tool-call success رو روی task typeهای مختلف می‌سنجه — و این دقیقاً همون چیزیه که برای ساختن agent واقعی اهمیت داره.

ولی متا خودش هم صادق بوده: روی benchmark‌های خالص کدنویسی و reasoning، Opus 4.8 از آنتروپیک و GPT-5.5 از OpenAI هنوز جلوترن. و Mythos 5 و Fable 5 آنتروپیک و GPT-5.6 سول از OpenAI هم کلاً در یه لیگ دیگه‌ان. Muse Spark 1.1 رو نه باید با بهترین مدل‌های موجود مقایسه کنی، نه باید دست کم بگیریش.

قیمت‌گذاری

هر یک‌میلیون توکن ورودی ۱.۲۵ دلار، خروجی ۴.۲۵ دلار. این عدد رو بذار کنار بقیه:

توکن ورودی‌های Claude Haiku 4.5 و GPT-5.6 Luna از Muse Spark ارزون‌ترن، ولی Sonnet 4.6 آنتروپیک و مدل‌های میانه‌ی OpenAI گرون‌ترن. یعنی Muse Spark 1.1 توی طیف mid-tier قیمتی قرار می‌گیره — نه ارزون‌ترین، نه گرون‌ترین. برای کسی که می‌خواد یه مدل agentic با context window بزرگ و قیمت معقول داشته باشه، جای جالبیه.

توسعه‌دهنده‌هایی که ثبت‌نام می‌کنن ۲۰ دلار اعتبار رایگان می‌گیرن.

نکته‌ای که توسعه‌دهنده‌ها باید بدونن

Meta Model API هم با OpenAI SDK سازگاره هم با Anthropic Messages format. یعنی اگه الان روی یکی از این دوتا کار می‌کنی، اشتکال‌پذیری به Muse Spark نیاز به rewrite نداره — فقط base URL رو به api.meta.ai/v1 تغییر بده، key بده، و اسم مدل رو muse-spark-1.1 بذار.

این یه تصمیم توزیع‌گر هوشمندانه‌ست. یعنی تیم‌ها می‌تونن Muse Spark رو A/B کنن با مدل فعلیشون بدون اینکه stack رو از نو بسازن.

این هفته برای متا

Muse Spark 1.1 تنها چیزی نبود که این هفته از متا اومد. دو روز قبلش Muse Image و Muse Video هم منتشر شدن — اولین مدل‌های تولید تصویر و ویدیوی Superintelligence Labs. ولی Muse Image یه جنجال هم به‌همراه آورد: اجازه داد کاربرا روی عکس‌های public اینستاگرامی که دیگران گذاشتن افکت AI اعمال کنن، بدون اینکه از صاحب عکس اجازه گرفته بشه. این تصمیم با اعتراض زیادی روبه‌رو شد.

وضعیت دسترسی

مدل الان توی «Thinking mode» در اپ Meta AI و سایت meta.ai در دسترسه — بدون نیاز به API. برای توسعه‌دهنده‌ها، Meta Model API به‌صورت public preview فعلاً فقط برای آمریکاییاست.

متا گفته این مدل در آینده جای Llama رو توی WhatsApp، Instagram، Facebook، و عینک‌های هوشمند متا هم می‌گیره. مارک زاکربرگ هم برای اولین‌بار از جولای ۲۰۲۳ روی X پست گذاشت که این مدل «strong agentic and coding model at a very low price» هست. سه سال سکوت روی یه پلتفرم برای اعلام یه مدل AI — این یه نشانه از اینه که داخل متا چقدر به این لانچ اهمیت می‌دن.

رقابت AI این هفته به‌طرز جالبی شلوغ بود. بازار داره به یه سمتی می‌ره که قیمت‌ها پایین‌تر، context windowها بزرگ‌تر، و تمرکز بیشتر روی کار agentic هست. Muse Spark 1.1 دقیقاً وسط همین جریانه.

TypeScript 7 Stable منتشر شد و حدودا ۱۰ برابر سریع تره نوشته شده توسط عرفان دهقانی

TypeScript 7 Stable منتشر شد و حدودا ۱۰ برابر سریع تره

۸ جولای ۲۰۲۶، مایکروسافت نسخه‌ی stable از TypeScript 7 رو منتشر کرد. بعد از حدود یه سال preview و beta و RC، حالا دیگه آزمایشی نیست.

اگه مقاله‌ی قبلی ما درباره‌ی RC رو خونده باشی، می‌دونی ماجرا از کجا شروع شد: مایکروسافت کامپایلر TypeScript رو که از ابتدا با JavaScript نوشته شده بود، با Go بازنویسی کرد. ولی «بازنویسی» دقیقاً کلمه‌ی درستی نیست — این یه port بود. ساختار کد، الگوریتم‌ها، و data structureها حفظ شدن، فقط زبان پیاده‌سازی عوض شد. نتیجه اینه که semantics تایپ‌چک دقیقاً همونه، ولی سرعتش حالا چیز دیگه‌ایه.

اعداد واقعی روی پروژه‌های واقعی

مایکروسافت همراه با اعلام stable، benchmark روی چند codebase واقعی منتشر کرده. روی VS Code با ۲.۳ میلیون خط کد، تایپ‌چک از ۱۲۵ ثانیه به ۱۰.۶ ثانیه رسیده — نزدیک ۱۲ برابر. روی Sentry با ۱.۹ میلیون خط، ۱۵.۷ ثانیه. روی Bluesky با ۶۲۸ هزار خط، ۲.۸ ثانیه. روی Playwright با ۵۲۸ هزار خط، ۱.۴۷ ثانیه.

عدد کلی که مایکروسافت می‌گه «اغلب بین ۸ تا ۱۲ برابر» هست — نه ۱۰ برابر ثابت. این بستگی داره به اندازه‌ی پروژه و ساختار dependency graph.

دلیل این سرعت دو چیز بود: اول، Go binary به‌جای JavaScript interpreted اجرا می‌شه. دوم، کامپایلر جدید می‌تونه از shared memory parallelism استفاده کنه. به‌صورت پیش‌فرض با ۴ worker تایپ‌چک می‌کنه — می‌تونی با flag --checkers این عدد رو تنظیم کنی. worker بیشتر یعنی سریع‌تر، ولی رم بیشتر هم می‌خواد.

برای چی این‌قدر طول کشید؟

وقتی مارس ۲۰۲۵ Anders Hejlsberg این پروژه رو اعلام کرد، خیلی‌ها انتظار نداشتن که اینقدر زود stable بشه. در واقع beta اپریل ۲۰۲۶ اومد، RC ژوئن ۲۰۲۶، و stable جولای ۲۰۲۶ — تقریباً ۱۵ ماه از اعلام تا stable. دلیل این سرعت نسبی اینه که از صفر طراحی نشد؛ port بود نه rewrite.

مایکروسافت بیش از یه سال با تیم‌های داخلی و شرکت‌هایی مثل Bloomberg، Canva، Figma، Google، Notion، Slack، Vercel و VoidZero روی preview buildها کار کرد. نتیجه اینه که از روز اول stable، این مدل‌ها روی codebaseهای میلیون‌خطی تایید شده.

نصب

npm install -D typescript@latest

همین. دیگه خبری از @typescript/native-preview یا tsgo نیست — اون package برای دوران beta بود. از این به بعد همه چیز از همون typescript package معمولی میاد و با همون tsc اجرا می‌شه.

برای چک کردن نسخه:

npx tsc --version  # باید TypeScript 7.x.x باشه

چی ممکنه بشکنه

TypeScript 7 با TypeScript 6 از نظر تایپ‌چک compatible هست — یعنی کدی که با ۶ compile می‌شد باید با ۷ هم compile بشه. با این حال، چند تغییر هست که باید بدانی:

--target es5 و format‌های output مثل AMD، UMD و SystemJS حذف شدن. moduleResolution: "node10" (همون قدیمی‌ترها که node می‌نوشتن) هم نیست. rootDir حالا به‌صورت پیش‌فرض ./ هست نه root پروژه، و types به‌صورت پیش‌فرض آرایه‌ی خالیه.

اگه مستقیم از TypeScript 5 یا قدیمی‌تر upgrade می‌کنی — نه ۶ — احتمال مشکل بیشتره چون این deprecationها توی ۶ warning بودن و حالا توی ۷ hard error شدن. توصیه اینه که اگه روی ۵ هستی، اول به ۶ بری و بعد به ۷.

یه چیز مهم که هنوز نیست

API برنامه‌نویسی TypeScript — همونی که ابزارهایی مثل typescript-eslint، ts-morph، و custom transformerها ازش استفاده می‌کنن — توی ۷.۰ پایدار نیست. مایکروسافت گفته این API توی نسخه‌ی ۷.۱ که چند ماه دیگه میاد آماده می‌شه.

یعنی اگه workflow‌ات به این ابزارها وابسته‌ست، فعلاً باید یه سری چیزها رو pinned روی TypeScript 6 نگه داری:

npm install -D @typescript/typescript6   # aliased package برای linting

مایکروسافت یه compatibility package برای این کار منتشر کرده تا بتونی هم ۶ هم ۷ رو side-by-side داشته باشی.

editor

برای VS Code، TypeScript Native Preview extension که قبلاً جداگانه نصب می‌کردی دیگه لازم نیست — همون typescript package که توی پروژه نصبه، editor هم ازش استفاده می‌کنه. فقط یه بار VS Code رو restart کن.

اگه روی editor دیگه‌ای کار می‌کنی (Neovim، Zed، Cursor)، language server protocol یکیه — هر clientی که از tsserver استفاده می‌کنه خودش سریع‌تر می‌شه بدون اینکه config خاصی بخواد.

نظر شخصی

این نوع تغییرات نادره. معمولاً «مهم‌ترین release در سال‌های اخیر» یه عبارت overused هست، ولی اینجا واقعاً صدق می‌کنه — نه به‌خاطر یه feature جدید، بلکه به‌خاطر اینکه یه چیزی که همه باهاش کنار اومده بودن (کامپایلر کند) یهو یه مقیاس کامل فرق کرده. اگه روی پروژه‌ی بزرگی کار می‌کنی که تایپ‌چک CI بیشتر از یه دقیقه طول می‌کشه، آپدیت کردن به ۷ احتمالاً صرفه‌جویانه‌ترین کاریه که می‌تونی این هفته انجام بدی.

این موضوع واقعا من رو به شخصه آزار میداد. من سیستمم بد  نیست ولی تاپ ناچم نیست و خب لود شدن تایپ اسکریپت برام انقدر کند بود که واقعا ازاردهنده بود. هنوز بررسیش نکردم ولی خب I have a lot of hope

Next.js 16.3 Turbopack: وقتی dev server دیگه ۲۱ گیگ رم نمی‌خوره نوشته شده توسط عرفان دهقانی

Next.js 16.3 Turbopack: وقتی dev server دیگه ۲۱ گیگ رم نمی‌خوره

اگه روی یه پروژه‌ی Next.js بزرگ کار کردی و یه نقطه‌ای رسیدی که Task Manager رو باز کردی و دیدی dev server تنهایی داره ۸ گیگ رم می‌خوره، می‌دونی این احساس چیه. Turbopack از اول با این طراحی اومد که همه‌چیز رو cache کنه تا compile سریع‌تر باشه — ولی قیمتش این بود که هرچقدر بیشتر توی پروژه می‌چرخیدی، حافظه بیشتری می‌خورد و هیچ‌وقت هم آزاد نمی‌کرد.

نسخه‌ی ۱۶.۳ این trade-off رو عوض کرده.

مصرف حافظه: ۹۰ درصد کمتر

تیم Turbopack سه ماه روی این کار کرد. نتیجه چیه؟ روی codebase داشبورد vercel.com، بعد از compile کردن ۵۰ route، مصرف حافظه از ۲۱.۵ گیگابایت به ۲ گیگابایت رسیده — یعنی ۹۰ درصد کمتر. روی سایت nextjs.org هم از ۴۶۰۰ مگابایت به ۸۴۰ مگابایت، یعنی حدود ۸۲ درصد کاهش.

چطور؟ با یه مکانیزم جدید به اسم memory eviction. ایده ساده‌ست: به‌جای اینکه نتایج cache شده برای همیشه توی RAM نگه داشته بشن، حالا Turbopack می‌تونه اونایی که دیگه فعال استفاده نمی‌شن رو بریزه روی دیسک و از حافظه پاک کنه. این feature روی filesystem cache که از نسخه‌ی ۱۶.۱ اضافه شده بود تکیه می‌کنه، و توی ۱۶.۳ هر دو به‌صورت پیش‌فرض فعال هستن.

اگه بخوای غیرفعالش کنی یا رفتارش رو debug کنی:

const nextConfig = {
  experimental: {
    turbopackMemoryEviction: false,
  },
};

یه چیز مهم: عدد دقیق کاهش حافظه برای هر پروژه فرق می‌کنه. بستگی داره به اینکه route graph پروژه‌ات چقدر بزرگه و توی یه session چقدر ازش استفاده کردی.

filesystem cache برای build

تا الان، filesystem cache فقط توی next dev کار می‌کرد. از ۱۶.۳، همین cache برای next build هم در دسترسه.

اعداد رو ببین: روی nextjs.org، build با cache از ۲۱ ثانیه به ۹.۲ ثانیه رسیده — ۲.۳ برابر سریع‌تر. روی vercel.com/geist که یه design system بزرگه، از ۳۰ ثانیه به ۵.۵ ثانیه — یعنی ۵.۵ برابر. روی vercel.com/home که پروژه‌ی سنگین‌تریه، بهبود کمتره: از ۶۶ به ۴۶ ثانیه.

فعال کردنش یه flag می‌خواد:

const nextConfig = {
  experimental: {
    turbopackFileSystemCacheForBuild: true,
  },
};

برای CI هم می‌شه از این استفاده کرد: کافیه پوشه‌ی .next رو بین runها کش کنی. وقتی Turbopack اون دایرکتوری رو اول build پیدا کنه، از کار قبلی استفاده می‌کنه به‌جای اینکه همه‌چیز رو از صفر compile کنه.

React Compiler با Rust

React Compiler از نسخه‌ی ۱۶.۰ توی Next.js stable بوده، ولی تا الان فقط به‌عنوان یه Babel transform اجرا می‌شد. مشکل اینجا بود که Babel روی پروژه‌های بزرگ سنگین می‌شد و build رو کند می‌کرد.

تیم React یه پورت native از این compiler با Rust نوشته، و تیم Turbopack سریع این رو integrate کرده. نتایج اولیه روی پروژه‌هایی مثل v0 نشون می‌ده که compile time بین ۲۰ تا ۵۰ درصد بهتر می‌شه. فعلاً experimental هست:

const nextConfig = {
  reactCompiler: true,
  experimental: {
    turbopackRustReactCompiler: true,
  },
};

import.meta.glob

Turbopack حالا از API ای که Vite معروفش کرده پشتیبانی می‌کنه:

const posts = import.meta.glob('./posts/*.mdx');

این به‌جای اینکه مجبور بشی اسم همه‌ی فایل‌ها رو hardcode کنی، هر فایلی که با pattern مطابقت داشته باشه رو import می‌کنه. نتیجه یه object هست که key‌هاش path فایل‌هاست:

for (const path in posts) {
  const post = await posts[path]();
}

می‌تونی با eager: true همه‌شون رو بلافاصله import کنی، یا فقط چند export خاص رو بگیری، یا pattern‌های منفی بگذاری. file watcher هم بهش وصله — اگه فایلی اضافه یا حذف شد، خودش recompile می‌کنه.

یه نکته: این feature فقط روی Turbopack کار می‌کنه. اگه هنوز با --webpack build می‌گیری، اینجا نیست.

HMR سریع‌تر و runtime کوچیک‌تر

دو بهبود دیگه که کمتر headline می‌گیرن ولی در عمل احساس می‌شن: اول اینکه HMR subscription tracking بهتر شده — با یکی کردن چند subscription در جاهایی که قبلاً جداگانه بودن، dev server cold start روی اپ‌های پیچیده بیش از ۱۵ درصد سریع‌تر شده. دوم اینکه runtime code ای که Turbopack به هر route اضافه می‌کنه کوچیک‌تر شده — چون حالا فقط کدی که واقعاً استفاده می‌شه (مثل WebAssembly loader یا worker support) شیپ می‌شه، نه همه‌چیز یکجا.

یه feature کوچیک‌تر هم برای monorepoها اومده: با turbopackLocalPostcssConfig: true می‌تونی per-package پیکربندی PostCSS داشته باشی به‌جای اینکه همه از root config بخوننن.

اگه الان روی Next.js 16.x هستی، این آپدیت شاید مهم‌ترین چیزیه که از نظر DX روزانه حسش می‌کنی — نه یه feature جدید، بلکه اینکه وقتی ساعت‌ها روی پروژه کار می‌کنی، IDE و dev server با هم دیگه دعوا نمی‌کنن سر رم.

نقد و بررسی

میخوای بدونی یچیزی چطور کار میکنه قبل اینکه بخوای استفاده کنی؟

Hermes Agent: یک agent رایگان که میتونه کارای جالبی انجام بده نوشته شده توسط عرفان دهقانی

Hermes Agent: یک agent رایگان که میتونه کارای جالبی انجام بده

یه اعتراف صادقانه قبل از شروع: آنچه روی کاغذ درباره‌ی Hermes Agent نوشته شده — که «به‌طور خودکار یاد می‌گیره» — دقیقاً اون‌طوری که ادعا می‌شه کار نمی‌کنه. skill document می‌سازه، ولی به اون شکل خودکار و بی‌دردسری که تبلیغش می‌شه نیست. این رو از تجربه‌ی مستقیم می‌گم، نه از بنچمارک.

ولی اگه این انتظار رو کنار بذاری و بفهمی که Hermes واقعاً چی هست، یکی از بهترین agentهای open-source ای خواهد بود که امتحان کردی.

واقعیت: چقدر prompting می‌خواد

Hermes بدون توضیح درست کار نمی‌کنه. اگه prompt کوتاه و مبهم بدی، نتیجه متناسبه. ولی اگه یه prompt با جزئیات کافی بدی — دقیقاً مشخص کنی چی می‌خوای، چه محدودیت‌هایی داره، output چه شکلی باشه — آنچه در ادامه انجام می‌ده می‌تونه واقعاً چشم‌گیر باشه. کارهای طولانی، پیچیده، و چندمرحله‌ای که معمولاً agent‌های دیگه یا نصفه رها می‌کنن یا خراب تموم می‌کنن.

این یعنی Hermes «agent برای همه» نیست. agent‌ای است که با یه اپراتور حواس‌جمع، خوب کار می‌کنه.

ترکیب با 9Router: چرا مهمه

جذاب‌ترین بخش ماجرا اینجاست: Hermes با هر OpenAI-compatible endpoint ای کار می‌کنه. یعنی می‌تونی 9Router رو جلوش بذاری و از مدل‌های رایگان یا ارزون استفاده کنی — و Hermes همون کاری رو می‌کنه که با Claude یا GPT-4 انجام می‌داد.

عملاً می‌شه از agentی استفاده کرد که performance‌اش به agentهای گرون نزدیکه، با هزینه‌ای که نزدیک به صفره. این ترکیب رو امتحان کردم و کار می‌کنه.

skill ها: چیزی که واقعاً ارزش داره

یه چیز که در عمل خیلی کاربرد داشت، سیستم skill هست — نه اون چیزی که agent خودش می‌سازه، بلکه skill هایی که خودت با Claude می‌سازی و بهش می‌دی. می‌تونی یه workflow پیچیده رو یه بار به‌درستی توصیف کنی، بذاریش توی یه skill، و بعد هر بار که Hermes به اون task می‌رسه، از همون توصیف استفاده کنه. این‌طوری دیگه لازم نیست هر بار از اول توضیح بدی.

چیزی که کشف کردم: sudo ندید

یه هشدار جدی: دسترسی sudo بهش ندید.

نه به‌خاطر اینکه مشکل امنیتی عجیبی داره — بلکه چون agent وقتی روی یه task پیچیده کار می‌کنه، ممکنه اشتباه کنه. و اگه sudo داشته باشه، اشتباهش می‌تونه جبران‌ناپذیر باشه. از تجربه‌ی مستقیم: یه دیتابیس محلی پاک شد. بعیدترین اتفاق ممکن بود ولی افتاد.

محدود کردن دسترسی‌ها — خصوصاً روی فایل‌سیستم — یه قدم ضروریه نه یه پیشنهاد احتیاطی.

اگر خیلی بیشتر بخواید امنیت رو رعایت کنید میتونید روی یک VM یا VPS رانش کنید و باهاش در ارتباط باشید از جاهایی که ساپورت میکنه (تقریبا همه کاری میشه کرد) ولی شخصا روی سیستمم هست (لینوکس) و تا الان مشکلی نداشتم و مستقیم توی ترمینال باهاش کار میکنم.

چیه و چی نیست

چیه: یه agent محلی قدرتمند برای کارهای پیچیده و طولانی که با راهنمایی درست نتایج خوبی می‌ده. اگه بهش skill های درست بدی و prompt دقیق بنویسی، کارهایی انجام می‌ده که معمولاً از agentهای open-source انتظار نداری. MIT، رایگان، سورس باز.

چی نیست: agent ای که بدون نظارت کار کنه، یا که به‌طور خودکار skill بسازه و بهتر بشه — حداقل نه به اون شکلی که توی marketing claim می‌شه.

مشخصات کلی

Hermes Agent از Nous Research فوریه ۲۰۲۶ منتشر شد و الان روی نسخه‌ی v0.18.2 هست. از یه gateway اجرا می‌شه و می‌تونی از Telegram، Discord، Slack، WhatsApp، Signal، و Email باهاش در ارتباط باشی. با هر provider ای کار می‌کنه — Nous Portal، OpenRouter، Anthropic، OpenAI، یا مدل محلی با Ollama. تا ژوئن ۲۰۲۶ به ۱۸۸ هزار ستاره‌ی GitHub رسیده، NVIDIA هم آن را به‌عنوان runtime مرجع برای Nemotron 3 Ultra انتخاب کرده.

# macOS / Linux
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash

# یا از طریق pip
pip install hermes-agent && hermes

Desktop app هم برای macOS و Windows مستقیم از سایت قابل دانلود هست.

9Router: وقتی rate limit دیگه نمی‌تونه جلوی کار کردن رو بگیره نوشته شده توسط عرفان دهقانی

9Router: وقتی rate limit دیگه نمی‌تونه جلوی کار کردن رو بگیره

یه اتفاق آشناست: وسط یه session طولانی با Claude Code یا Codex، یه پیام می‌بینی که quota تموم شده. نه اینکه کارت تموم شده — quota تموم شده. بعد یا باید صبر کنی تا reset بشه، یا دستی بری سراغ یه provider دیگه، یا tool رو ببندی و بری سراغ یه API key دیگه.

9Router برای همین مشکل ساخته شده. یه gateway محلی که بین ابزار AI تو و بیش از ۶۰ provider قرار می‌گیره، و وقتی یه provider به سقف رسید، خودکار به یه جایگزین می‌ره — بدون اینکه لازم باشه چیزی بزنی یا session رو قطع کنی.

ایده‌ی اصلی: سه tier، یه fallback خودکار

9Router روی یه مدل routing سه‌لایه کار می‌کنه:

Tier 1 — Subscription: اشتراک‌هایی که از قبل داری. Claude Code، OpenAI Codex، GitHub Copilot، Cursor. اگه اشتراک داری، 9Router اول از اینها استفاده می‌کنه.

Tier 2 — Cheap: مدل‌هایی که API key می‌خوان ولی ارزونن. GLM به ازای هر میلیون توکن ۰.۶۰ دلار، MiniMax M2.7 به ازای هر میلیون توکن ۰.۲۰ دلار، Kimi با ۹ دلار در ماه. وقتی Tier 1 تموم شد، اینجا میاد.

Tier 3 — FREE: iFlow، Qwen، Kiro، OpenCode. کاملاً رایگان و بدون محدودیت ثابت. آخرین سنگر.

وقتی quota یه provider در Tier 1 تموم می‌شه، 9Router خودکار به Tier 2 می‌ره. وقتی Tier 2 هم تموم شد، به Tier 3 می‌ره. از نظر tool تو — Cursor، Cline، Claude Code — هیچ اتفاقی نیفتاده. همون endpoint جواب می‌ده.

نصب و راه‌اندازی

npm install -g 9router
9router

همین. یه dashboard محلی باز می‌شه که می‌تونی providerها رو اضافه کنی — OAuth برای اشتراک‌ها، API key برای بقیه. بعد هر tool ای که داری رو به این endpoint اشاره بده:

http://localhost:20128/v1

این endpoint با فرمت OpenAI کاملاً compatible هست، پس هر ابزاری که بتونه با OpenAI کار کنه — Claude Code، Codex، Cursor، Cline، Continue، و بقیه — می‌تونه از همین endpoint استفاده کنه.

راستی اگر فلگ t- رو به 9router پاس بدی میتونی ترمینال رو ببندی و توی بکگراند کارشو میکنه.

چیزهایی که توی مسیر اضافه شدن

Format Translator: اگه یه tool با فرمت OpenAI کار می‌کنه ولی می‌خوای به Anthropic یا Gemini وصل بشی، 9Router فرمت رو وسط راه ترجمه می‌کنه. نیازی نیست tool ات Anthropic Messages format بلد باشه.

Multi-Account: می‌تونی چند حساب از یه provider اضافه کنی و 9Router با round-robin بینشون load balance کنه. اگه یه حساب به محدودیت رسید، خودکار به حساب بعدی می‌ره.

RTK Token Saver: خروجی دستوراتی مثل git diff، grep، find و tree رو قبل از فرستادن به مدل فشرده می‌کنه. ادعای سازنده اینه که ۲۰ تا ۴۰ درصد توکن ورودی کمتر مصرف می‌شه. این به‌صورت پیش‌فرض فعاله و lossless هست.

Caveman Mode: یه system prompt تزریق می‌کنه که جواب‌های مدل رو کوتاه‌تر و متراکم‌تر می‌کنه. پنج سطح شدت داره. اگه با مدل‌هایی کار می‌کنی که verbose جواب می‌دن و می‌خوای توکن خروجی کمتر مصرف بشه، این feature کمک می‌کنه.

MITM Bridge: یه feature پیشرفته‌تر که ترافیک IDEهایی مثل GitHub Copilot، Kiro IDE، یا Antigravity رو intercept می‌کنه و به 9Router هدایت می‌کنه. این یعنی می‌تونی از اشتراک IDE هایی که داری برای call کردن هر backend ای که بخوای استفاده کنی. سازنده خودش تاکید کرده که باید policy هر tool رو بررسی کنی قبل از استفاده.

Cloud Sync + Tunnel: اگه بخوای از جای دیگه‌ای غیر از ماشین محلیت به 9Router دسترسی داشته باشی، یه Cloudflare tunnel می‌تونی راه بندازی.

یه نکته درباره‌ی provider های رایگان

Tier 3 شامل providerهایی مثل iFlow و Kiro می‌شه که «unlimited free» هستن. واقعیت اینه که این‌ها معمولاً quota دارن، ولی reset شون سریع‌تره یا سقفشون بالاتره از providerهای اصلی. اگه روی پروژه‌های سنگین کار می‌کنی، Tier 3 رو آخرین fallback در نظر بگیر، نه ابزار اصلی — چون کیفیت مدل‌های رایگان معمولاً پایین‌تره.

open source و رایگان

9Router با MIT license منتشر شده و سورسش روی GitHub هست. هیچ سرور مرکزی‌ای وجود نداره — همه چیز روی ماشین خودت اجرا می‌شه. پرداختی برای خود 9Router وجود نداره؛ هزینه فقط مربوط به providerهاییه که انتخاب می‌کنی.

برای کسی که چند اشتراک AI مختلف داره و هر ماه بخشی از quota هدر می‌ره، یا کسی که وسط کار به rate limit می‌خوره و باید دستی provider عوض کنه، 9Router یه مشکل واقعی رو حل می‌کنه.

زبان برنامه‌نویسی Verse, انقلاب در توسعه متاورس و بازی‌سازی؟ نوشته شده توسط عرفان دهقانی

زبان برنامه‌نویسی Verse, انقلاب در توسعه متاورس و بازی‌سازی؟

دنیای بازی‌سازی و اینترنت سه‌بعدی (متاورس) با سرعتی سرسام‌آور در حال حرکت است. تا پیش از این، توسعه‌دهندگان بازی‌ها مجبور بودند میان زبان‌های پیچیده و سطح پایینی مثل C++ (برای کارایی بالا) یا ابزارهای اسکریپت‌نویسی بصری و محدود، دست به انتخاب بزنند. اما کمپانی اپیک گیمز (Epic Games) با معرفی ابزار Unreal Editor for Fortnite (UEFN) از یک برگ برنده رونمایی کرد: زبان برنامه‌نویسی ورس (Verse).

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

زبان Verse چیست و چرا متولد شد؟

زبان Verse یک زبان برنامه‌نویسی چندپارادایمی (Multi-Paradigm) است که ویژگی‌های برنامه‌نویسی تابعی (Functional)، منطقی (Logic) و امری (Imperative) را به شکلی نوآورانه با هم ترکیب کرده است. اپیک گیمز این زبان را با سه اصل بنیادی طراحی کرده است:

  1. فقط کد است (It's just code): پیچیده‌ترین مفاهیم بازی و شبیه‌سازی، در قالب ساختارهای اولیه و خوانای متنی بیان می‌شوند.

  2. یک زبان برای همه چیز (Just one language): ساختارهای یکسانی برای زمان کامپایل (Compile-time) و زمان اجرا (Run-time) استفاده می‌شود.

  3. اول متاورس (Metaverse first): این زبان از پایه برای یک محیط شبیه‌سازی جهانی، توزیع‌شده و زنده طراحی شده است؛ جایی که کدهای نوشته شده باید سال‌ها بدون مشکل و با حفظ سازگاری عقب‌رو (Backward Compatibility) اجرا شوند.

ویژگی‌های کلیدی و انقلابی زبان Verse

اگر با زبان‌هایی مثل پایتون، سی‌شارپ یا جاوااسکریپت کار کرده باشید، در مواجهه با Verse با مفاهیم شگفت‌انگیزی روبرو خواهید شد که فرآیند توسعه را به شدت ایمن‌تر و لذت‌بخش‌تر می‌کنند.

۱. همه چیز یک «عبارت» است (Everything is an Expression)

در زبان‌های سنتی، ما بین دستورات (Statements - مانند حلقه‌ها که مقداری برنمی‌گردانند) و عبارات (Expressions - که مقدار تولید می‌کنند) تفاوت قائل می‌شویم. در Verse این مرز وجود ندارد؛ همه چیز یک عبارت است و یک مقدار تولید می‌کند.

به عنوان مثال، یک شرط ساده یا حتی یک حلقه در ورس می‌تواند مستقیماً به یک متغیر نسبت داده شود:

Result := if (Condition[]) then "yes" else "no"
Multiply := for (X : Array) { X * 42 }

این ویژگی باعث می‌شود کدها فوق‌العاده ترکیب‌پذیر (Composable) و خلاصه شوند.

۲. سیستم شکست به جای مقادیر بولی (Failure as Control Flow)

یکی از جذاب‌ترین بخش‌های فنی ورس، سیستم شکست (Failure System) آن است. در ورس چیزی به نام مقدار Boolean (True/False) سنتی برای کنترل جریان برنامه وجود ندارد. در عوض، عبارات یا «موفق» می‌شوند و مقداری را برمی‌گردانند، یا «شکست» می‌خورند.

توابعی که ممکن است شکست بخورند با براکت [] مشخص می‌شوند. اگر عبارتی در یک محیط failable (قابل شکست) اجرا شود و شکست بخورد، تغییرات آن بخش از کد به صورت خودکار به حالت قبل برمی‌گردد (Speculative Execution). این یعنی دیگر نیازی به نوشتن ساختارهای تکراری try-catch برای مدیریت خطاها ندارید.

۳. همزمانی ساختاریافته (Structured Concurrency)

برنامه‌نویسی بازی‌های آنلاین و چندنفره به شدت به مدیریت زمان و رویدادهای همزمان وابسته است. ورس با معرفی مفاهیمی چون sync ،race ،rush و branch برنامه‌نویسی ناهمگام (Async) را به بازیچه تبدیل کرده است. شما می‌توانید چندین کار را به طور همزمان اجرا کنید، مشخص کنید که کدام یک باید منتظر دیگری بماند، یا در صورت برنده شدن یک پردازش در مسابقه (race)، بقیه پردازش‌ها را فوراً لغو کنید؛ همه این‌ها بدون ریزش حافظه یا تداخل‌های رایج شبکه!

جایگاه Verse در اکوسیستم Unreal Editor for Fortnite (UEFN)

در حال حاضر، دروازه ورود به دنیای ورس، ابزار UEFN یا همان محیط توسعه فورتنایت است. پیش از این، کاربران در بخش Fortnite Creative تنها می‌توانستند دستگاه‌های بازی (Devices) را با خطوط بصری و محدود به هم متصل کنند. اما ورس به شما قدرت مطلق می‌دهد.

با استفاده از Verse در UEFN می‌توانید:

  • تعاملات پیچیده بسازید: رفتار بازیکنان، قوانین بازی و محیط را با دقت میلی‌ثانیه‌ای کنترل کنید.

  • منطق‌های داینامیک خلق کنید: بازی‌هایی بسازید که بر اساس وضعیت فعلی جهان بازی یا مشخصات بازیکن، به صورت زنده تغییر می‌کنند.

  • محدودیت ابزارهای بصری را بشکنید: ساخت سیستم‌های امتیازدهی پیشرفته، هوش مصنوعی شخصی‌سازی‌شده برای NPCها و مکانیزم‌های خلاقانه که تا پیش از این غیرممکن بود.

مقایسه اجمالی: Verse در برابر زبان‌های دیگر

ویژگیزبان Verseزبان‌های سنتی (C++/C#)
هدف اصلیشبیه‌سازی متاورس و بازیتوسعه عمومی و سیستم
مدیریت خطاسیستم شکست (Failure Contexts)استثناها (Exceptions / Try-Catch)
نوع پارادایمتابعی - منطقی - امریشیءگرا یا امری
امنیت شبکهبالا و بومی (بدون Desync)نیازمند کدنوسی دستی پیچیده

چگونه یادگیری Verse را شروع کنیم؟

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

گام اول: نصب ابزارها

ابتدا باید نرم‌افزار Epic Games Launcher را نصب کرده و از درون آن Unreal Editor for Fortnite (UEFN) را دریافت کنید. ورس به صورت بومی در این ادیتور ادغام شده است.

گام دوم: استفاده از قالب‌های آماده (Templates)

مستندات رسمی اپیک گیمز شامل پروژه‌های آماده‌ای مانند Verse Starter Template است. با باز کردن این پروژه‌ها، می‌توانید کدهای نوشته شده برای هدایت یک NPC یا تغییر یک دستگاه در بازی را ببینید، آن‌ها را دستکاری کنید و نتیجه را فوراً در بازی مشاهده کنید.

گام سوم: مطالعه منبع اصلی (Book of Verse)

اگر برنامه‌نویس هستید و می‌خواهید مستقیماً به سراغ مفاهیم عمیق مانند سیستم افکت‌ها (Effects)، کلاسیفیکیشن تایپ‌ها (Type System) و مدیریت حافظه بروید، کتاب آنلاین ورس (Book of Verse) که در آدرس verselang.github.io/book در دسترس است، بهترین و دقیق‌ترین مرجع برای شماست.

آینده زبان Verse؛ فراتر از فورتنایت

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

تیم سویینی (مدیرعامل اپیک گیمز) بارها اشاره کرده است که هدف نهایی ورس، تبدیل شدن به زبان استاندارد موتور بازی‌سازی Unreal Engine و در نهایت کل اینترنت سه‌بعدی است. پتانسیل این زبان در هندل کردن پروژه‌های MMO (بازی‌های آنلاین انبوه) با هزاران بازیکن در یک سرور واحد، بدون ناهماهنگی (Desync)، توجه بسیاری از نظریه‌پردازان زبان‌های برنامه‌نویسی را جلب کرده است.

کلام آخر

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

Claude Fable 5 و Claude Mythos 5 منتشر شدند - قدرتمندترین مدل‌های جدید Anthropic نوشته شده توسط عرفان دهقانی

Claude Fable 5 و Claude Mythos 5 منتشر شدند - قدرتمندترین مدل‌های جدید Anthropic

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

این دقیقاً همان اتفاقی است که برای خانواده Claude Mythos افتاد.

در ۹ ژوئن ۲۰۲۶، Anthropic از دو مدل جدید به نام‌های Claude Fable 5 و Claude Mythos 5 رونمایی کرد. این معرفی، اوج یک فرآیند چند ماهه بود که از آوریل همان سال آغاز شده بود — زمانی که Anthropic برای اولین بار ثابت کرد مدل‌های هوش مصنوعی می‌توانند به مرزهایی برسند که انتشار بی‌قید و شرط آن‌ها دیگر گزینه‌ای مطمئن نیست.

در این مقاله، با تکیه بر اعلامیه رسمی Anthropic، تمام جوانب این دو مدل را بررسی می‌کنیم.


پیش‌زمینه: داستان Mythos Preview

برای درک Fable 5 و Mythos 5، باید به آوریل ۲۰۲۶ برگردیم.

در آن ماه، Anthropic اولین مدل از خانواده Mythos-class خود را با نام Claude Mythos Preview معرفی کرد. اما برخلاف تمام مدل‌های قبلی، این مدل به صورت عمومی منتشر نشد. دلیل آن چیز غیرمنتظره‌ای بود: Mythos Preview توانسته بود آسیب‌پذیری‌هایی در سیستم‌عامل‌ها و مرورگرهای اصلی شناسایی کند — بدون اینکه اصلاً برای این هدف طراحی شده باشد.

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

Anthropic در پاسخ به این وضعیت، پروژه‌ای به نام Project Glasswing راه‌اندازی کرد: یک برنامه همکاری کنترل‌شده با سازمان‌های منتخب، از جمله Apple، Google، Amazon، Microsoft، Cisco، JPMorgan Chase و دولت ایالات متحده. هدف این پروژه استفاده از توانایی‌های Mythos برای تقویت امنیت زیرساخت‌های حیاتی بود — نه بهره‌برداری از آن برای حمله.

چند هفته بعد، Anthropic دسترسی را به حدود ۱۵۰ سازمان در بیش از پانزده کشور گسترش داد. و حالا، با معرفی Fable 5، برای اولین بار این فناوری در اختیار عموم قرار گرفته است.


Claude Fable 5 چیست؟

Claude Fable 5 اولین مدل Mythos-class است که برای همه کاربران در دسترس قرار گرفته. Anthropic درباره آن صریح است: «توانایی‌های Fable 5 از هر مدلی که تا به حال به صورت عمومی عرضه کرده‌ایم فراتر می‌رود.»

اما این قدرت بیشتر با یک مکانیزم امنیتی همراه شده است. Fable 5 از سیستمی به نام classifier استفاده می‌کند — مجموعه‌ای از مدل‌های هوش مصنوعی جداگانه که درخواست‌های بالقوه مخرب را شناسایی می‌کنند. هر بار که این سیستم یک درخواست را مشکل‌دار تشخیص دهد، پاسخ به‌طور خودکار توسط Claude Opus 4.8 داده می‌شود — به جای اینکه درخواست کاملاً رد شود. این رویکرد هوشمندانه‌ای است؛ چرا که کاربر یک پاسخ مفید دریافت می‌کند، اما از توانایی‌های پیشرفته‌تری که می‌توانند مورد سوءاستفاده قرار بگیرند، محافظت می‌شود.

این fallback در کمتر از ۵ درصد جلسات اتفاق می‌افتد. برای بقیه کاربران، عملکرد Fable 5 عملاً برابر با Mythos 5 است.

سه حوزه اصلی تحت پوشش classifier قرار دارند:

امنیت سایبری. Mythos-class در شناسایی و بهره‌برداری از آسیب‌پذیری‌های نرم‌افزاری فوق‌العاده عمل می‌کند. classifier های Fable 5 نه‌تنها بهره‌برداری از آسیب‌پذیری، بلکه طیف گسترده‌تری از وظایف تهاجمی سایبری — شامل شناسایی، حرکت جانبی و فرار از سیستم‌های دفاعی — را پوشش می‌دهند. یک آزمون خارجی با بیش از ۱۰۰۰ ساعت تست انجام شد و هیچ jailbreak جهانی پیدا نشد.

زیست‌شناسی و شیمی. Mythos 5 در پیش‌بینی خواص ویروس‌های پیچیده، عملکردی بهتر از مدل‌های اختصاصی پروتئین داشت — بدون اینکه برای این کار آموزش دیده باشد. این توانایی dual-use است: در دست محققان، ابزاری ارزشمند برای توسعه درمان‌های ژنی است؛ در دست افراد نادرست، می‌تواند خطرناک باشد. به همین دلیل، اکثر درخواست‌های مرتبط با زیست‌شناسی و شیمی فعلاً به Opus 4.8 ارجاع داده می‌شوند.

Distillation. این classifier از تلاش‌های مقیاس‌بزرگ برای استخراج توانایی‌های Claude و استفاده از آن‌ها برای آموزش مدل‌های رقیب جلوگیری می‌کند.


Claude Mythos 5 چیست؟

Claude Mythos 5 همان مدل پایه‌ای است که Fable 5 بر آن بنا شده، اما با یک تفاوت کلیدی: محدودیت‌های سایبری آن برداشته شده است.

نام‌گذاری این دو مدل نیز بامعناست. «Fable» از ریشه لاتین fabula به معنای «آنچه گفته می‌شود» می‌آید — هم‌ریشه با کلمه یونانی mythos. تنها چیزی که این دو مدل را از هم جدا می‌کند، وجود یا عدم وجود همان safeguardها است.

Mythos 5 در حال حاضر تنها برای شرکای Project Glasswing — شامل سازمان‌های امنیت سایبری و ارائه‌دهندگان زیرساخت‌های حیاتی — در دسترس است. Anthropic قصد دارد به زودی دسترسی را به محققان زیست‌پزشکی تأییدشده نیز گسترش دهد، با این تفاوت که برای آن‌ها safeguardهای زیست‌شناسی برداشته می‌شود، اما محدودیت‌های سایبری همچنان باقی می‌ماند.


قابلیت‌های اصلی این مدل‌ها

Fable 5 و Mythos 5 در چند حوزه به صورت خاص برجسته هستند.

برنامه‌نویسی. شرکت Stripe گزارش داده که Fable 5 یک migration در پایگاه کد ۵۰ میلیون خطی Ruby را در یک روز انجام داد — کاری که یک تیم کامل بیش از دو ماه نیاز داشت. در بنچمارک FrontierCode که کیفیت کد تولیدی در محیط‌های واقعی را ارزیابی می‌کند، Fable 5 بالاترین امتیاز را در بین مدل‌های frontier کسب کرد.

وظایف طولانی‌مدت. این مدل‌ها می‌توانند ساعت‌ها روی یک پروژه کار کنند، پیشرفت خود را ارزیابی کنند و مسیر را در صورت نیاز اصلاح کنند. هر دو مدل از پنجره context یک میلیون توکن با خروجی تا ۱۲۸ هزار توکن در هر درخواست پشتیبانی می‌کنند. آزمایش با بازی Slay the Spire نشان داد که استفاده از حافظه مبتنی بر فایل، عملکرد Fable 5 را سه برابر بیشتر از Opus 4.8 بهبود می‌دهد.

پردازش تصویر. Fable 5 جدیدترین مدل state-of-the-art در حوزه بینایی است. این مدل توانست بازی Pokémon FireRed را تنها با تماشای اسکرین‌شات‌های خام و بدون هیچ ابزار کمکی به پایان برساند — کاری که مدل‌های قبلی Claude حتی با harness های پیچیده هم به سختی از پس آن برمی‌آمدند.

تحقیقات علمی. Mythos 5 فرآیند طراحی دارو را تا ۱۰ برابر سریع‌تر کرده و در ۹ مورد از ۱۴ هدف پروتئینی مورد مطالعه، کاندیداهای قوی شناسایی کرده است. همچنین اولین مدل Anthropic است که به طور مستمر فرضیه‌های علمی نوآورانه تولید می‌کند؛ یکی از این فرضیه‌ها درباره یک پروتئین باکتریایی بعداً توسط یک آزمایشگاه مستقل تأیید شد.

تحلیل مالی و کاری. در Finance Benchmark شرکت Hebbia برای استدلال در سطح ارشد، Fable 5 بالاترین امتیاز را در بین تمام مدل‌های آزمایش‌شده کسب کرد. شرکت IMC نیز گزارش داد که این مدل در تقریباً تمام معیارهای ارزیابی تحلیل معاملاتی نتایج عالی داشت.


سیاست جدید نگهداری داده

یکی از تغییرات مهمی که با این مدل‌ها همراه شده، الزام نگهداری ۳۰ روزه داده برای تمام ترافیک روی مدل‌های Mythos-class است.

Anthropic تأکید می‌کند که این داده‌ها برای آموزش مدل‌های جدید استفاده نمی‌شوند و تمام دسترسی‌های انسانی به آن‌ها ثبت می‌شود. هدف اصلی شناسایی jailbreak های پیچیده‌ای است که ممکن است در طول زمان و در چند مکالمه مختلف طراحی شده باشند — حملاتی که بررسی تک‌به‌تک جلسات قادر به شناسایی آن‌ها نیست.


قیمت‌گذاری و دسترسی

هر دو مدل با قیمت یکسان عرضه شده‌اند: ۱۰ دلار به ازای هر میلیون توکن ورودی و ۵۰ دلار به ازای هر میلیون توکن خروجی. این قیمت کمتر از نصف قیمت Claude Mythos Preview است.

از نظر دسترسی:

Claude Fable 5 از ۹ ژوئن ۲۰۲۶ از طریق Claude API و پلن‌های Enterprise مصرفی کاملاً در دسترس است. برای کاربران اشتراکی (Pro، Max، Team و Enterprise)، این مدل تا ۲۲ ژوئن بدون هزینه اضافه در دسترس است. از ۲۳ ژوئن، استفاده از آن نیاز به usage credit خواهد داشت. Anthropic اعلام کرده که به محض کافی شدن ظرفیت، Fable 5 را دوباره به‌عنوان بخش استاندارد پلن‌های اشتراکی اضافه خواهد کرد.

Claude Mythos 5 فعلاً تنها در اختیار شرکای Project Glasswing است و به زودی برای محققان زیست‌پزشکی تأییدشده نیز باز خواهد شد.


جمع‌بندی

Claude Fable 5 و Mythos 5 را می‌توان مهم‌ترین معرفی Anthropic در سال ۲۰۲۶ دانست — نه فقط به خاطر قدرت بیشتر، بلکه به خاطر رویکردی که پشت آن‌هاست.

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

این الگو نشان‌دهنده بلوغ صنعتی است — و احتمالاً در مدل‌های آینده نیز استاندارد خواهد شد.


منبع: اعلامیه رسمی Anthropic، ۹ ژوئن ۲۰۲۶

آموزشی

دوست داری چیزهای مختلف رو یاد بگیری؟ این بخش برای توئه

مدیریت متغیرهای محیطی در Next.js نوشته شده توسط Haleh Nakisa

مدیریت متغیرهای محیطی در Next.js

وقتی روی یک پروژه بزرگ یا حتی یک وب‌سایت شخصی کار می‌کنید، اطلاعات حساسی مثل کلیدهای API (API Keys)، آدرس دیتابیس‌ها و رمزهای عبور وجود دارن که به هیچ وجه نباید به صورت مستقیم (Hard-code) داخل کدهای شما قرار بگیرن. قرار دادن این اطلاعات داخل کد، نه تنها امنیت پروژه رو به خطر می‌اندازه، بلکه فرآیند تغییر اون‌ها را در محیط‌های مختلف (مثل محیط توسعه و محیط پروداکشن) به یک چالش بزرگ تبدیل می‌کنه.
اینجاست که فایل‌های .env به کار میان. در این مقاله می‌خوایم بررسی کنیم که فریم‌ورک Next.js چطور کار با متغیرهای محیطی رو برای ما راحت کرده، این فایل‌ها چه اولویت‌هایی دارن و چطور می‌تونیم به بهینه‌ترین شکل ممکن از اون‌ها استفاده کنیم.
چطور فایل‌های .env زندگی ما رو راحت‌تر می‌کنن؟
به زبان ساده، متغیرهای محیطی به شما اجازه میدن تنظیمات پروژه رو از خودِ کد جدا کنید. Next.js به صورت پیش‌فرض و بدون نیاز به نصب هیچ پکیج اضافی (مثل dotenv)، از این فایل‌ها پشتیبانی می‌کنه.
شما می‌تونید چندین فایل .env برای سناریوهای مختلف داشته باشید، اما نکته مهم اینه که بدونید Next.js با چه ترتیبی و بر اساس چه اولویتی این فایل‌ها رو می‌خونه.
ترتیب اولویت فایل‌های .env در Next.js (از بیشترین به کمترین):
نکست‌جی‌اس برای جابجایی بین محیط‌های مختلف (توسعه، پروداکشن و تست) بسیار هوشمند عمل می‌کنه. ترتیب خونده شدن فایل‌ها به این صورت هستش:
فایل‌های اختصاصی محیط با پسوند .local: مثل .env.development.local یا .env.production.local. این فایل‌ها بالاترین اولویت رو دارن و معمولاً در سیستم هر برنامه‌نویس به صورت محلی ذخیره می‌شن و نباید به گیت‌هاب push بشن.
فایل .env.local: این فایل در تمامی محیط‌ها (به جز محیط تست) اولویت بسیار بالایی داره و برای تعریف متغیرهای محلی عمومی استفاده میشه.
فایل‌های اختصاصی محیط: شامل .env.development (وقتی دستور next dev رو می‌زنید)، .env.production (وقتی پروژه با next start بالا میاد) و .env.test. نکست‌جی‌اس بر اساس وضعیت پروژه، فقط یکی از این فایل‌ها رو انتخاب می‌کنه و بقیه رو کاملاً نادیده می‌گیره.
فایل پایه .env: پایین‌ترین اولویت رو داره. این فایل به عنوان یک نسخه‌ی پشتیبان (Fallback) عمل می‌کنه؛ یعنی اگر متغیری در فایل‌های بالایی پیدا نشه، نکست‌جی‌اس این فایل رو چک می‌کنه.


دسترسی به متغیرها: مرز بین سرور و کلانیت
به صورت پیش‌فرض، تمام متغیرهایی که در فایل‌های .env تعریف می‌کنید فقط و فقط در سمت سرور (Node.js) قابل دسترسی هستن (مثلاً در API روت‌ها یا Server Components). این یک قابلیت امنیتی هستش تا اطلاعات حساس شما به مرورگر کاربر ارسال نشه.
اما اگر بخواید از یک متغیر در کامپوننت‌های سمت کلایت (Client Components) استفاده کنید، باید این کار رو انجام بدید:
کافیه اسم متغیر رو با عبارت NEXT_PUBLIC_ شروع کنید. با این کار، Next.js متوجه می‌شه که این متغیر حساس نیست و اجازه میده که در سمت کلایت هم بهش دسترسی داشته باشید:

# فقط در سمت سرور دسترسی دارد
ANALYTICS_SECRET_KEY=secret_123 

# هم در سرور و هم در کامپوننت‌های کلایت دسترسی دارد
NEXT_PUBLIC_API_URL=https://api.codoloper.com
ساخت پوشه Configs برای دسترسی بهتر:
صدا زدن مداوم process.env.NEXT_PUBLIC_API_URL در سراسر پروژه، علاوه بر شلوغ کردن کد، دو مشکل اساسی داره: اول اینکه هیچ پیشنهادی (Auto-complete) از سمت ادیتور دریافت نمی‌کنید و دوم اینکه احتمال غلط املایی بالا میره.
برای حل این مشکل مراحل زیر رو انجام بدید:
۱. در ریشه (Root) پروژه یک پوشه به نام configs ایجاد کنید.
۲. داخل اون یک فایل به نام global.ts بسازید.
۳. متغیرهای محیطی رو به صورت جدا در این فایل تعریف و اکسپورت کنید:
export const apiUrl = process.env.NEXT_PUBLIC_API_URL;

export const isDevelopment = process.env.NODE_ENV === "development";

export const isProduction = process.env.NODE_ENV === "production";
حالا هر کجای پروژه که به این متغیرها نیاز داشتید، به جای کار با process.env، خیلی راحت متغیر مورد نظرتون رو ایمپورت می‌کنید:
import { apiUrl, isProduction} from "@/configs/global";
با این کار کدهای تمیزتری هم دارید.
جمع‌بندی
مدیریت هوشمندانه متغیرهای محیطی در Next.js به ما این امکان رو میده که پروژه‌های امن‌تر و منعطف‌تری بسازیم. با درک درست از اولویت‌بندی فایل‌های .env و استفاده از قابلیت‌هایی مثل پیشوند NEXT_PUBLIC_ و رویکرد Centralized Config، فرآیند توسعه و دیپلوی پروژه آسونتر میشه.
نکته مهمِ اینکه: حتماً مطمئن شید که فایل‌های با پسوند .local در فایل .gitignore شما قرار دارن تا به اشتباه روی مخازن گیت آپلود نشن!
شما در پروژه‌هاتون چطور متغیرها رو مدیریت می‌کنید؟ آیا تا به حال با چالش لود نشدن متغیرها در سمت کلایت مواجه شدید؟ نظرات و تجربیات خودتون رو در بخش کامنت‌ها با ما در میون بذارید!
تفاوت React Element، JSX Element و React Node چیست؟ نوشته شده توسط Haleh Nakisa

تفاوت React Element، JSX Element و React Node چیست؟

اگر در حال توسعه پروژه‌های ری‌اکت یا نکست‌جی‌اس با TypeScript هستید، قطعا موقع نوشتن کامپوننت‌ها یا تعریف تمپلیت‌ها، به این سه تایپ (Type) برخوردید: ReactNode ،ReactElement و JSX.Element.

در این مقاله می‌خوایم به زبون ساده و با مثال‌های واقعی بررسی کنیم که این سه مفهوم دقیقاً چی هستن، چه تفاوتی با هم دارن و در چه سناریویی باید از کدومشون استفاده کنیم.
۱. مفهوم React Element:
یک React Element کوچک‌ترین واحد سازنده در یک اپلیکیشن ری‌اکت هستش. از نظر فنی، این تایپ یک شیء (Object) ساده و جاوااسکریپتیه که توصیف می‌کنه یک جزء از پورتال یا UI شما چطور باید به نظر برسه (مثلاً نوعش چیه، چه Propsهایی داره و فرزندانش کدوم هستن).
وقتی شما یک کامپوننت یا تگ HTML رو می‌نویسین، ری‌اکت در پشت صحنه اون رو به یک الگو تبدیل می‌کنه.
چه زمانی تولید می‌شه؟ هر زمانی که تابع React.createElement() فراخوانی شه.
ویژگی مهم: این تایپ نمی‌تونه شامل متن ساده (String)، عدد یا آرایه باشه؛ بلکه فقط و فقط یک آبجکت معتبر ری‌آکتیه.

// این یک ReactElement است
const element: React.ReactElement = <h1>سلام کادولوپر!</h1>; 

// این خطا ایجاد می‌کند چون رشته متنی به تنهایی ReactElement نیست
const invalidElement: React.ReactElement = "Hello World"; // Error!
۲. مفهوم JSX.Element:
JSX.Element و React Element: این دو تقریباً یک چیز هستن! در واقع JSX.Element یک متغیر سراسری (Global) هستش که توسط خود زبان جاوااسکریپت/تایپ‌اسکریپت (درست خارج از هسته ری‌اکت) تعریف میشه تا خروجی سینتکس‌های JSX رو تایپ‌دهی کنه. از نظر ساختاری، JSX.Element چیزی نیست بجز یک اینترفیس که مستقیماً از ReactElement ارث‌بری می‌کنه، اما با این تفاوت که تایپِ فیلدهای props و type اون به صورت پیش‌فرض any در نظر گرفته شده تا منعطف‌تر باشه.
// هر دو خط زیر از نظر عملکردی کاملاً یکسان هستند:
const buttonOne: React.ReactElement = <button>کلیک کنید</button>;
const buttonTwo: JSX.Element = <button>کلیک کنید</button>;
۳. مفهوم React Node:
می‌رسیم به بزرگ‌ترین تایپ در ری‌آکت: React Node.
تایپ ReactNode در واقع یک ابرمجموعه (Superset) هستش؛ یعنی هر چیزی که ری‌آکت توانایی رندر کردن اون رو روی صفحه داشته باشه، زیرمجموعه ReactNode قرار می‌گیره. به تعریف تایپ اون در هسته ری‌آکت نگاه کنید:
type ReactNode = ReactElement | string | number | Iterable<ReactNode> | ReactPortal | boolean | null | undefined;
همون‌طور که می‌بینید، یک ReactNode می‌تونه یک آبجکت ری‌اکتی، یک متن ساده، یک عدد، آرایه‌ای از المان‌ها، یا حتی مقادیر خالی مثل null و undefined باشه.
// تمام موارد زیر به عنوان ReactNode کاملاً معتبر هستند:
const nodeText: React.ReactNode = "یک متن ساده";
const nodeNumber: React.ReactNode = 1405;
const nodeElement: React.ReactNode = <div>یک المان کامپوننت</div>;
const nodeNull: React.ReactNode = null;
کجا از کدوم استفاده کنیم؟
الان که با ماهیت هرکدوم آشنا شدیم، بیاید ببینیم در پروژه‌های واقعی (مخصوصا موقع تعریف ابزارهای کاستوم و پروژه‌های تیمی) بهترین انتخاب کدوم میشه.
سناریوی اول: تعریف فیلد children در کامپوننت‌ها (Best Practice: ReactNode)
اگر در حال ساخت یک کامپوننتِ Wrapper مثل دکمه‌های عمومی، Layout اصلی سایت یا کامپوننت‌های Card هستید که قراره محتوای مختلفی درون خودش جا بده، همیشه از ReactNode استفاده کنید. این کار به بقیه برنامه‌نویسها اجازه میده تا هر چیزی (از متن ساده تا چند تگ تو در تو) رو داخل کامپوننت شما بفرستند:
type LayoutProps = {
  children: React.ReactNode; // بهترین انتخاب برای دریافت هر نوع محتوا
};

export default function Layout({ children }: LayoutProps) {
  return <main className="main-container">{children}</main>;
}
سناریوی دوم: محدود کردن خروجی به تگ‌های ساختاریافته (Best Practice: ReactElement)
تصور کنید در حال ساخت کامپوننتی به نام List هستید و می‌خواید کاربر فقط و فقط تگ‌های <ListItem /> رو به عنوان فرزند ارسال کنه و اجازه نداشته باشه رشته متنی ساده یا عدد خالی بفرسته. در این سناریو، ReactElement انتخاب بهتری هست:
type ListProps = {
  // کاربر نمی‌تواند متن ساده بفرستد، حتماً باید یک کامپوننت یا تگ معتبر باشد
  children: React.ReactElement; 
};
سناریوی سوم: تایپ‌دهی خروجی توابع یا هوک‌های کاستوم (Best Practice: JSX.Element)
اگر متدی نوشتید که وظیفه‌ش تولید و برگردوندن یک قطعه کد HTML یا کامپوننت هستش، تعیین JSX.Element به عنوان تایپ خروجی، خوانایی کد شما رو بالا می‌بره و مشخص می‌کنه که خروجی این تابع یک سینتکس JSX هستش:
const renderStatusIcon = (status: string): JSX.Element => {
  if (status === "success") return <SuccessIcon />;
  return <ErrorIcon />;
};
جمع‌بندی
انتخاب درست بین این سه تایپ، بستگی به میزان سخت‌گیری یا انعطاف‌پذیری لازم در کدهای شما داره. اگر دنبال انعطاف زیاد برای رندر انواع داده‌ها باشید، ReactNode انتخاب خوبیه. اما اگر می‌خواید ساختار رو محدود به آبجکت‌های معتبر طراحی UI کنید، ReactElement و JSX.Element بهترین گزینه‌ها هستن.
شما در پروژه‌های خودتون بیشتر با کدوم‌ از این تایپ‌ها سر و کار دارید؟ تا حالا به خاطر استفاده جابجا از اون‌ها به باگ‌های تایپ‌اسکریپتی خوردید؟ تجربیات خودتون رو در بخش نظرات با ما در میون بذارید!
انواع API ها - REST، GraphQL، gRPC: کدومش رو واقعاً باید انتخاب کنی؟ نوشته شده توسط عرفان دهقانی

انواع API ها - REST، GraphQL، gRPC: کدومش رو واقعاً باید انتخاب کنی؟

یه روز یکی از بچه‌های تیم اومد گفت «بیا کل بک‌اند رو GraphQL کنیم، REST قدیمیه». دو هفته بعد، همون آدم داشت با N+1 query کلنجار می‌رفت و آرزو می‌کرد کاش همون REST قدیمی رو نگه داشته بودیم. این داستان رو احتمالاً قبلاً جایی شنیدی، چون تقریباً هر تیمی یه نسخه از آن را تجربه کرده.

واقعیت این است که هیچ‌کدام از این سه‌تا «بهتر» نیستند؛ هرکدام برای یک نوع درد طراحی شده‌اند.

REST: همون که همه می‌شناسن

REST رو همه به‌خاطر سادگی‌اش دوست دارن. منبع‌محور است: هر URL یک resource را نشان می‌دهد و متدهای HTTP (GET، POST، PUT، DELETE) کاری که می‌خواهی روی آن انجام دهی را مشخص می‌کنند. کتابخانه‌ها همه‌جا هستند، کش کردن با HTTP caching معمولی کار می‌کند، و هر کسی که یک بار با API کار کرده، REST را بدون توضیح زیاد می‌فهمد.

مشکلش از

 همان‌جایی شروع می‌شود که اپلیکیشن‌ها پیچیده‌تر می‌شوند. فرض کن صفحه‌ی پروفایل کاربر را داری که هم اطلاعات کاربر، هم پست‌های اخیرش، هم تعداد فالوورها را نیاز دارد. در REST کلاسیک، این می‌شود سه (یا بیشتر) درخواست جدا، یا یک endpoint سفارشی که فقط برای همین صفحه ساخته‌ای و جای دیگری استفاده نمی‌شود. این پدیده اسم دارد: over-fetching وقتی داده‌ی اضافه می‌گیری، و under-fetching وقتی کم می‌گیری و باید درخواست دوم بزنی.

GET /users/42
GET /users/42/posts?limit=5
GET /users/42/followers/count

برای یک اپ ساده مشکلی نیست. برای یک اپ موبایل با شبکه‌ی ضعیف که هر round-trip اضافه چند صد میلی‌ثانیه هزینه دارد، همین چیزی است که کاربران را اذیت می‌کند.

GraphQL: یک endpoint، دقیقاً همون چیزی که خواستی

GraphQL همین مشکل را حل می‌کند با این ایده که فقط یک endpoint داشته باشی، و کلاینت دقیقاً مشخص کند چه فیلدهایی را می‌خواهد:

query {
  user(id: 42) {
    name
    posts(limit: 5) { title }
    followersCount
  }

یک درخواست، دقیقاً داده‌ای که لازم داری، نه کمتر نه بیشتر. تیم‌های فرانت‌اند معمولاً عاشق این می‌شوند چون دیگر برای هر تغییر کوچک در UI نباید از بک‌اند بخواهند یک endpoint جدید بسازد.

اما این آزادی قیمتی دارد. همان مثال N+1 که اول گفتم: اگر برای هر post بخواهی اطلاعات نویسنده‌اش را هم بگیری، resolver پیش‌فرض می‌تواند به‌ازای هر پست یک کوئری جدا به دیتابیس بزند. ده پست یعنی ده کوئری اضافه. راه‌حلش وجود دارد (مثل DataLoader برای batch کردن)، ولی این یعنی یک لایه‌ی پیچیدگی که در REST اصلاً مجبور نبودی به آن فکر کنی. کش کردن هم سرراست نیست؛ چون همه‌چیز از یک endpoint با متد POST می‌آید، کش‌های HTTP معمولی که برای REST جا افتاده‌اند، اینجا کار نمی‌کنند و باید کش را خودت در سطح اپلیکیشن مدیریت کنی.

gRPC: وقتی سرعت بین سرویس‌ها مهم‌تر از خوانایی است

gRPC داستان متفاوتی دارد. این یکی اصلاً برای مرورگر طراحی نشده (هرچند gRPC-Web هم هست)؛ هدف اصلی‌اش ارتباط بین سرویس‌ها در یک سیستم میکروسرویس است. به‌جای JSON متنی، از Protocol Buffers استفاده می‌کند که باینری و فشرده است، و روی HTTP/2 کار می‌کند که چندین استریم را روی یک کانکشن همزمان می‌برد.

نتیجه‌اش سرعت است؛ هم در حجم داده، هم در latency. قیمتش این است که دیگر نمی‌توانی با مرورگر یا curl ساده پاسخ را بخوانی؛ باید فایل .proto را داشته باشی و کد را generate کنی. برای ارتباط بین دو سرویس داخلی که هیچ‌کدام انسان نیست که مستقیم پاسخ را بخواند، این مشکلی نیست. برای یک API عمومی که توسعه‌دهنده‌های بیرونی باید با آن کار کنند، احتمالاً تجربه‌ی بدتری می‌سازد.

پس کدوم رو انتخاب کنیم؟

اگر یک API عمومی یا نسبتاً ساده می‌سازی که کلاینت‌های مختلف (وب، موبایل، شاید حتی توسعه‌دهنده‌های بیرونی) با آن کار می‌کنند و نیازهای داده‌ای‌شان شبیه هم است، REST هنوز انتخاب امن‌تری است. کسی که برای اولین‌بار با API‌ات روبه‌رو می‌شود، سریع‌تر می‌فهمدش.

اگر چند کلاینت با نیازهای داده‌ای خیلی متفاوت داری (مثلاً اپ موبایل که می‌خواهد کمترین داده ممکن را بگیرد، و داشبورد ادمین که می‌خواهد همه‌چیز را یک‌جا ببیند)، GraphQL این مشکل را با هزینه‌ی پیچیدگی بیشتر در بک‌اند حل می‌کند. فقط حواست به N+1 باشد.

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

نکته‌ی آخر: هیچ قانونی نمی‌گوید باید فقط یکی را انتخاب کنی. خیلی از سیستم‌های واقعی، REST را برای API عمومی نگه می‌دارند و gRPC را برای ارتباط داخلی بین سرویس‌ها به کار می‌برند. انتخاب درست همیشه یکی نیست؛ گاهی سه‌تاست، هر کدام جایی که واقعاً مزیت دارد.

تفاوت Type و Interface چیست و چه زمانی از کدام استفاده کنیم؟ نوشته شده توسط Haleh Nakisa

تفاوت Type و Interface چیست و چه زمانی از کدام استفاده کنیم؟

اگر به تازگی وارد دنیای TypeScript شدید یا حتی مدتیه که از اون تو پروژه‌هاتون (مثل Next.js یا React) استفاده می‌کنید، احتمالاً این سوال برای شما هم پیش اومده: «بالاخره برای تعریف ساختار داده‌ها از type استفاده کنم یا interface؟»
در نگاه اول، این دو کلمه کلیدی شباهت‌های زیادی به هم دارن و در اکثر مواقع کار یکسانی رو انجام میدن. اما در لایه‌های پایین‌تر، تفاوت‌های ساختاری و عملکردی مهمی دارن که شناخت اون‌ها، قطعا تو پروژه کمک کننده‌ست.
در این مقاله می‌خوایم این تفاوت‌ها رو موشکافی کنیم و ببینیم در سناریوهای واقعی، کدوم‌یک انتخاب بهتریه.
شباهت‌ها: 
قبل از اینکه سراغ تفاوت‌ها بریم، بهتره بدونیم که هر دو ابزار می‌تونن شکل یک شیء (Object) رو به راحتی توصیف کنن و هر دو از قابلیت‌هایی مثل ارث‌بری پشتیبانی می‌کنن:

// تعریف یک شیء با استفاده از Interface
interface UserInterface {
  id: number;
  name: string;
}

// تعریف همان شیء با استفاده از Type
type UserType = {
  id: number;
  name: string;
};
در هر دو حالت بالا، خروجی و رفتار TypeScript در مواجهه با یک کامپوننت یا تابع کاملاً یکسان هستش. اما مشکل از جایی شروع میشه که نیازهای پیچیده‌تری داشته باشیم.
تفاوت‌ها: چرا به هر دو نیاز داریم؟
۱. قابلیت ادغام خودکار یا Declaration Merging (کدوم بهتره: Interface)
بزرگ‌ترین و مهم‌ترین تفاوت ساختاری این دو اینه که interfaceها باز (Open) هستن، اما typeها بسته (Closed). یعنی شما می‌تونید یک interface رو چند بار با یک نام یکسان تعریف کنید و TypeScript به صورت خودکار تمام فیلدهای اون‌ها رو با هم ادغام می‌کنه:
interface Client {
  name: string;
}

interface Client {
  age: number;
}

// ادغام خودکار: حالا کلاینت هر دو فیلد را دارد
const newClient: Client = {
  name: "Ali",
  age: 25
};
اگر همین کار رو با type انجام بدید، بلافاصله با خطای دیتای تکراری (Duplicate identifier) مواجه میشد. این ویژگیِ interface برای زمان‌هایی که می‌خواید برای یک کتابخانه اکسترنال (مثل اضافه کردن فیلد به درخواست‌های Express یا تنظیمات تلویند) متغیر جدیدی اضافه کنید، حیاتیه.
۲. انواع داده‌های غیر شیء یا Primitive Types (کدوم بهتره: Type)
یک interface فقط و فقط میتونه شکل یک شیء (Object) یا تابع (Function) رو مشخص کنه. اما کلمه کلیدی type بسیار انعطاف‌پذیرتره و میتونه برای تعریف انواع الیاس‌ها (Aliases)، تایپ‌های ترکیبی (Union) یا چندوجهی (Intersection) استفاده شه:
// Union Types (تعریف تایپی که می‌تواند یکی از چند حالت باشد)
type Status = "pending" | "approved" | "rejected";
type ID = string | number;

// Tuple (آرایه‌ای با طول و تایپ مشخص)
type Point = [number, number];
انجام کارهای بالا با interface غیرممکنه.
۳. نحوه ارث‌بری و گسترش کد (Extending)
هر دو ابزار روش خاص خودشون رو برای گسترش دادن تایپ‌ها دارن. interface از کلمه کلیدی extends استفاده می‌کنه که از نظر فکری به شیءگرایی (OOP) نزدیک‌تره، در حالی که type از عملگر & (Intersection) استفاده می‌کنه:
// گسترش با Interface
interface Animal { name: string; }
interface Bear extends Animal { honey: boolean; }

// گسترش با Type
type AnimalType = { name: string; };
type BearType = AnimalType & { honey: boolean; };
بالاخره چه زمانی از کدوم استفاده کنیم؟ (Best Practices)
امروز تو دنیای توسعه وب، توافق‌های نانوشته اما استانداردی شکل گرفته که بر اساس اون‌ها میشه از فرمول زیر برای پروژه‌ها به استفاده کرد:
از Type استفاده کنید اگر:
•در حال طراحی کامپوننت‌های فرانت‌اند (مثل Props در ری‌اکت و نکست) هستید؛ چون تایپ‌ها برای این کار تمیزترن، جلوی ادغام‌های ناخواسته رو می‌گیرن و کار با قابلیت‌های کامپوننت رو راحت‌تر می‌کنن.
•نیاز به تعریف Union Types دارید (مثلاً وضعیت‌های یک دکمه یا کامپوننت: 'primary' | 'secondary' | 'danger').
•می‌خواید رفتارهای پیچیده‌ای مثل کدهای داینامیک، تایپ‌های شرطی (Conditional Types) یا الیاس‌های ساده برای کدهای پایه (Primitives) بسازید.
از Interface استفاده کنید اگر:
•ساختار داده‌های دیتابیس، مدل‌ها یا API (مثل خروجی‌های Prisma یا آبجکت‌های سمت بک‌آند) رو تعریف می‌کنید که فرمت کاملاً شیء‌گرا دارن.
•در حال نوشتن یک کتابخانه (Library) یا بسته نرم‌افزاری هستید و می‌خواید دیگران بتونن با قابلیت Declaration Merging، ویژگی‌های جدیدی به متغیرهای شما اضافه کنن و اون رو گسترش بدن.