tech-afternoon
1.23K subscribers
174 photos
6 videos
6 files
167 links
تِک‌افترنون، رویدادی گاه‌به‌گاه است با موضوعات حول معماری و توسعه نرم‌افزار، این کانال هم برای اشتراک اخبار، آموزش، نکاتی حول مهندسی نرم‌افزار، دیتابیس‌، تکنولوژی و مدیریت تولید محصولات نر‌م‌افزاری خواهد بود.
youtube.com/@AminTechTalks/videos
امین مصباحی
Download Telegram
🚀 تفاوت output، outcome و impact

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

«یکم بیشتر توضیح میدین منظورتون از Impact چیه؟»

به احترام پرسش خوب ایشون سعی می‌کنم در حد بضاعت پست تلگرامی توضیح بدم.

توی مباحث لیدرشیپ فنی، ۳ تا کلمه داریم که دونستن معانی اون‌ها مهمه:

💡 در مورد Output (خروجی)

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

⚙️ مثال:
تعداد خطوط کد نوشته‌شده، یا ماژول‌های تکمیل‌شده
ویژگی (Feature) جدیدی که به محصول اضافه شده
مستندات فنی یا طراحی رابط کاربری

ویژگی: خروجی معمولاً به‌راحتی قابل‌شمارش یا اندازه‌گیریه؛ مثلاً با شمارش تسک‌های انجام‌شده یا تعداد فیچرهای ارائه شده در هر اسپرینت.

===========================

💡 در مورد Outcome (نتیجه)

تعریف: نتیجه به تأثیرات و تغییراتی اشاره داره که به واسطهٔ یک خروجی در رفتار یا وضعیت کاربران، کسب‌وکار یا فرایندهای داخلی به وجود می‌یاد. Outcome معمولاً روی «ارزش» تمرکز داره؛ اینکه خروجی تولیدشده چه مشکلی را حل کرده یا چه بهبودی ایجاد کرده.

⚙️ مثال:
افزایش رضایت کاربران به‌دلیل اضافه شدن یک قابلیت مهم در نرم‌افزار
کاهش زمان پاسخ‌گویی سرور پس از بهینه‌سازی کد
بهبود نرخ تبدیل (Conversion Rate) یا رشد کاربران فعال روزانه (DAU)

ویژگی: نتیجه معمولاً به معنای دستیابی به بهبود یا حل مشکل مشخصی است. اندازه‌گیری اون اغلب به شاخص‌های عملکردی (KPIs) یا داده‌های تحلیلی وابسته است (مثلاً بررسی نرخ ریزش کاربران قبل و بعد از اضافه‌شدن فیچر جدید).

===========================

💡 در مورد Impact (تأثیر یا اثرگذاری کلان)

تعریف: Impact سطحی کلان‌تر از «نتیجه» است که نشون می‌ده تغییرات ایجادشده چه اثرات عمیق یا پایدار در جامعه، بازار، استراتژی کلان شرکت یا حتی صنعتی که شرکت توش فعالیت می‌کنه، داشته است. Impact فراتر از یک «دوره کوتاه» یا «مقیاس کوچک» است و غالباً در بلندمدت ارزیابی می‌شود.

⚙️ مثال:
تغییر جایگاه شرکت در بازار نرم‌افزار (مثلاً تبدیل شدن به یکی از پیشروان صنعت)
تأثیر مثبت بر جامعه: ایجاد اشتغال، بهبود زندگی مشتریان یا حل یک مشکل فراگیر اجتماعی
تحول فرایندهای یک سازمان بزرگ که مشتری شرکت شماست (مثلاً یک سیستم سازمانی که کیفیت خدمات دولتی رو ارتقا داده است)

ویژگی: تأثیر کلان ممکن است با معیارهای مالی (نظیر افزایش چشمگیر درآمد یا ارزش سهام) یا با شاخص‌های غیرمالی (مثل ارتقای آگاهی جمعی، تغییر رفتار اجتماعی) سنجیده بشه. گاهی برای سنجش دقیق Impact نیاز به گذر زمان و بررسی ابعاد گوناگون نتایج است.

===========================

⚙️ اینم بگم که گاهی ما تصور می‌کنیم فجایع و چرندیاتی که تولید کردیم impact یا outcome یا output بوده! اکثریت غالب شرکت‌های نرم‌افزاری‌ای که تپه‌ی سالم توی صنایع مختلف و سازمان‌های دولتی، بانک‌ها، و... باقی نگذاشتن، معتقدند که تاثیر عمیق و بسزایی با محصولات بی‌کیفیت و گاها آشغالشون گذاشتن، اینکه نتیجه بد شده، از کاهلی و وضع بد دیگران بوده!

لذا این خیلی خیلی مهمه که «ملاک سنجش و ارزش‌گذاری» عملکردمون «استاندارد و جهانی» باشه... وگرنه: «خود گویی و خود خندی... عجب مرد هنرمندی!»
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥104👍2
📇 سلسله‌مراتب مهندسی نرم‌افزار (بخش سوم, مایکروسافت!)

حالا که گوگل رو مرور کردیم، و مفهوم impact در سازمان رو دیدیم، بنا به نظر و پیشنهاد شما، بریم سراغ مایکروسافت ۲۲۸هزار کارمند داره که متناسب با ساختار و نیازهاش، نردبان شغلی خاص خودش رو داره:

۱. سطح L59 - Software Development Engineer I (SDE I)

📌 تجربه و دانش: فارغ‌التحصیل‌های تازه‌کار یا ۰ تا ۲ سال تجربه.
مسئولیت‌ها:
پیاده‌سازی تسک‌های مشخص‌شده تحت نظر مهندسان ارشد
یادگیری ابزارها و سیستم‌های داخلی مایکروسافت
شرکت در Code Reviewها و مستندسازی ساده
رفع باگ‌های جزئی و تست کد

مهارت‌ها:
آشنایی با #C یا ++C
فهم پایه از مفاهیم شیءگرایی

۲. سطح L60 - Software Development Engineer II (SDE II)

📌 تجربه و دانش: معمولاً ۲ تا ۵ سال تجربه، کسی که بتونه مشکلات فنی پیچیده‌تر و پروژه‌های کوچیک رو حل کنه.
مسئولیت‌ها:
توسعه ویژگی‌های جدید و بهینه‌سازی‌های بزرگ‌تر (مثلاً بهبود سرعت اجرای Azure Functions)
شروع به گرفتن تصمیمات طراحی در پروژه‌ها
همکاری با تیم‌های دیگر برای یکپارچه‌سازی سیستم‌ها

مهارت‌ها:
تسلط به طراحی APIها
آشنایی با Azure یا سرویس‌های ابری.

۳. سطح L61-L62 - Senior Software Engineer (SSE)

📌 تجربه و دانش: معمولاً بالای ۵ سال تجربه، کسی که بتونه استقلال بیشتری در تصمیم‌گیری‌های فنی داشته باشه
مسئولیت‌ها:
هدایت فنی پروژه‌های مهم (مثلاً توسعه قابلیت‌های جدید در Microsoft 365)
ارائه راه‌حل‌های بهینه برای مشکلات پیچیده.
طراحی معماری سیستم‌های توزیع‌شده (مثلاً بهبود زیرساخت Azure)
منتورینگ و کمک به SDEهای سطح پایین‌تر.

مهارت‌ها:
تخصص در حوزه‌هایی مثل ابر، AI یا امنیت
توانایی حل مسائل مقیاس سازمانی

۴. سطح L63-L64 - Principal Software Engineer

📌 تجربه و دانش: معمولاً ۸-۱۲ سال تجربه، فردی که می‌تونه چند تیم رو از نظر فنی هدایت کنه.
مسئولیت‌ها:
طراحی سیستم‌های با مقیاس بالا
رهبری تیم‌های فنی و ایجاد هماهنگی بین تیم‌های مختلف (مثلاً هماهنگی بین تیم‌های Xbox و کلود)
تعیین استراتژی فنی برای محصولات استراتژیک (مثلاً توسعه NET Core.)
نظارت بر روند توسعه و تأثیرگذاری در تصمیم‌گیری‌های کلان محصول.

مهارت‌ها:
دید کلان به چالش‌های کسب‌وکار و فناوری
توانایی مذاکره با مدیران ارشد (مثل VPها)

۵. سطح L65-L66 - Partner Software Engineer

📌 تجربه و دانش: یکی از بالاترین سطوح مهندسی فنی در مایکروسافت، معمولاً ۱۲+ سال تجربه.
مسئولیت‌ها:
تصمیم‌گیری‌های استراتژیک برای کل محصولات یا سرویس‌های بزرگ مایکروسافت.
ارتباط مستقیم با مدیران ارشد
هدایت چندین تیم مهندسی در راستای اهداف کلان.
طراحی سیستم‌های حیاتی (مثلاً معماری جدید Azure AI).

مهارت‌ها:
تخصص عمیق در یک حوزه (مثلاً Distributed Systems یا Quantum Computing).

۶. سطح L67 - Distinguished Engineer


📌 تجربه و دانش: افرادی که تأثیر مستقیمی روی کل صنعت دارن، تعداد این افراد خیلی کمه (مثال: دیوید فولر)
مسئولیت‌ها:
مشارکت در تعیین استراتژی‌های بلندمدت مایکروسافت
هدایت تحقیقات پیشرفته و توسعه فناوری‌های آینده
تعامل با مدیران اجرایی و تأثیرگذاری در مسیر کلی شرکت
انتشار مقالات یا ثبت اختراعات کلیدی.

مهارت‌ها:
تخصص عمیق در یک حوزه (مثلاً Distributed Systems یا Quantum Computing).
رهبری بدون نیاز به عنوان رسمی (با Influence و Respect).

۷. سطح L68+ - Microsoft Technical Fellow

📌 تجربه و دانش: بالاترین سطح فنی در مایکروسافت! این افراد تأثیرگذارترین چهره‌های تکنولوژی شرکت هستن (اینقدر که مدخل ویکی‌پدیا دارن!)
مسئولیت‌ها:
نوآوری‌های کلان در فناوری
ارائه راهبردهای تکنولوژیکی در سطح جهانی
ارتباط مستقیم با CEO و تعیین مسیر استراتژیک شرکت
هدایت نوآوری‌های انقلابی (مثلاً پروژه‌های کوانتومی یا HoloLens)

مهارت‌ها:
بینش استراتژیک در سطح صنعت
شبکه ارتباطی با دانشگاه‌ها و دولت‌ها


🔀 مایکروسافت دو مسیر مجزا برای پیشرفت داره:
مسیر فنی (IC - Individual Contributor) که از SDE I تا Technical Fellow میره.
مسیر مدیریتی که از Engineering Manager تا VP of Engineering ادامه پیدا می‌کنه.

برخلاف گوگل که سلسله‌مراتبش با L3, L4, … مشخصه، در مایکروسافت عناوینش از SDE I تا Technical Fellow سازماندهی شدن.
همون‌طور که توی گوگل دیدیم، توی مایکروسافت هم هر چی بالاتر می‌ری، مهارت‌های غیر فنی مثل لیدرشیپ و تصمیم‌گیری استراتژیک اهمیت بیشتری پیدا می‌کنن.

💬 بحث؟ نظر؟
قسمت بعدی و پایانی این بحث، یک شرکت کوچک و متوسط رو به صورت کلی توضیح می‌دم.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍1
📇 سلسله‌مراتب مهندسی نرم‌افزار (بخش چهارم و پایانی, شرکت‌های SME!)

🛠 چرا سلسله‌مراتب مهندسی برای شرکت‌های کوچک و متوسط مهمه؟
شرکت‌های کوچک و متوسط (SMEs) معمولاً چابک‌تر از غول‌هایی مثل گوگل و مایکروسافت هستن، ولی اگر نقش‌ها شفاف نباشه، افراد جای رشد نداشته باشن و سازمان فاقد ساختار منطقی باشه، انگیزه تیم پایین میاد و رشد شرکت متوقف می‌شه. آدم‌ها می‌رن یا فسیل می‌شن! و دیگه نقطه قوت چابکی تبدیل می‌شه به اسباب درجا زدن...

👨‍💻 هدف از طراحی نردبان شغلی اینه که:
مسیر پیشرفت مشخص باشه
افراد بدونن برای ارتقا به چه مهارت‌هایی نیاز دارن و پوزیشن‌ها سلیقه‌ای پخش نشده
شرکت بتونه استعدادها رو پرورش بده، نه فقط استخدام و اخراج کنه
هم رشد فردی اتفاق بیفته، هم رشد سازمانی

🔹 سلسله‌مراتب پیشنهادی برای یک شرکت پویا و مقیاس‌پذیر

۱. سطح Junior Software Engineer 👶

📌 ویژگی‌ها: ۰ تا ۲ سال تجربه، تسلط روی اصول برنامه‌نویسی و یکی دو تکنولوژی
🔹 مسئولیت‌ها:
یادگیری استانداردهای کدنویسی و فرآیندهای شرکت
توسعه تسک‌های کوچک تحت نظر افراد ارشد
نوشتن تست‌های ساده و رفع باگ‌های سطحی
🎯 شرایط ارتقا: تسلط به ابزارهای توسعه شرکت، بهبود درک معماری نرم‌افزارها

۲. سطح Software Engineer 👨‍💻 (مهندس نرم‌افزار)

📌 ویژگی‌ها: ۲ تا ۵ سال تجربه، توانایی توسعه ویژگی‌های مستقل
🔹 مسئولیت‌ها:
پیاده‌سازی و بهینه‌سازی بخش‌های اصلی اپلیکیشن
مشارکت در طراحی‌های کوچک و کدنویسی با کیفیت بالا
همکاری با تیم‌ها یا نقش‌های دیگه مثل QA و DevOps
🎯 شرایط ارتقا: ارائه راه‌حل‌های بهینه‌تر (نه شوآف!) و درک بهتر از طراحی سیستم‌ها

۳. سطح Senior Software Engineer 🔥 (مهندس نرم‌افزار ارشد)

📌 ویژگی‌ها: ۵ تا ۸ سال تجربه، مهارت در حل مشکلات پیچیده
🔹 مسئولیت‌ها:
معماری و طراحی سیستم‌های قابل مقیاس
هدایت کد ریویوها و منتورینگ اعضای تازه‌کار
بهینه‌سازی عملکرد و افزایش کیفیت کد
🎯 شرایط ارتقا: توانایی تصمیم‌گیری‌های فنی مهم، رهبری پروژه‌های بزرگ‌تر

۴. سطح Lead Engineer / Tech Lead 🚀 (رهبر فنی تیم)

📌 ویژگی‌ها: ۷ تا ۱۰ سال تجربه، تخصص در طراحی و راهبری سیستم‌های پیچیده
🔹 مسئولیت‌ها:
راهبری تیم‌های توسعه از نظر فنی
تصمیم‌گیری در انتخاب تکنولوژی‌ها و معماری‌های نرم‌افزار
تعامل با مدیران محصول و تضمین اجرای درست پروژه‌ها
🎯 شرایط ارتقا: تجربه کافی در مدیریت تیم‌های مهندسی، درک استراتژی فنی

۵. سطح Software Architect 🏛 (معمار نرم‌افزار)

📌 ویژگی‌ها: ۱۰+ سال تجربه، توانایی طراحی سیستم‌های بزرگ و توزیع‌شده
🔹 مسئولیت‌ها:
طراحی معماری نرم‌افزار و مستندسازی راهکارهای فنی
مشاوره به تیم‌های مهندسی برای اتخاذ بهترین شیوه‌ها
حل چالش‌های مقیاس‌پذیری و بهینه‌سازی سیستم‌ها
🎯 شرایط ارتقا: داشتن دیدگاه کلان و استراتژیک به سیستم‌های نرم‌افزاری

۶. سطح Engineering Manager 🎯 (مدیر مهندسی)

📌 ویژگی‌ها: مهارت در هم مدیریت افراد، هم درک فنی سیستم‌ها
🔹 مسئولیت‌ها:
مدیریت و هدایت تیم‌های توسعه و تخصیص منابع
تسهیل همکاری بین تیم‌های مختلف (مثلاً محصول، DevOps، QA)
اجرای فرآیندهای رشد و ارتقای مهندسان نرم‌افزار
🎯 شرایط ارتقا: اثبات توانایی در هدایت چند تیم و موفقیت در اجراهای استراتژیک

۷. سطح CTO (Chief Technology Officer) 🏆 (مدیر ارشد فناوری)

📌 ویژگی‌ها: بالاترین سطح فنی، توانایی هدایت کل دپارتمان مهندسی
🔹 مسئولیت‌ها:
تعیین مسیر فنی و تکنولوژیک شرکت
تصمیم‌گیری در مورد فناوری‌های آینده و رشد تیم مهندسی
ارتباط با سایر مدیران اجرایی و سرمایه‌گذاران برای هم‌راستا کردن استراتژی فنی با کسب‌وکار
🎯 شرایط ارتقا: تجربه گسترده در رهبری فناوری و ایجاد محصولات موفق

چند نکته خیلی مهم برای اجرای این مدل در شرکت‌های کوچک و متوسط:
🔹 انعطاف‌پذیری حفظ بشه! یه استارتاپ ۱۰ نفره قطعاً نیازی به CTO یا چندین سطح از روز اول نداره، ولی وقتی رشد کنه، نیازش ایجاد می‌شه.
🔹 جایگاه‌های میانی حذف نشن! بین یه Junior و یه Senior باید مسیر رشد منطقی باشه، وگرنه انگیزه تیم کم می‌شه.
🔹 فرهنگ یادگیری و رشد ایجاد بشه! مسیر پیشرفت افراد نباید صرفاً روی «سال‌های تجربه» باشه، بلکه توانایی و خروجی مهم‌تره.
🔹 وقتی برخی پوزیشن‌ها رو به هر دلیلی ندارید، هیچ اشکالی نداره از مشاور «شایسته» استفاده کنید، خیلی بهتر از اینه که چون کسی رو ندارید بهش برچسب سنیور یا معمار یا کوفت بچسبونیم.
🔹 پوزیشن‌های لیدرشیپ، فقط مهارت فنی نیاز ندارن، باید بتونه تعامل سازنده و مناسب با سایرین داشته باشن و کمک به رشد بقیه کنن

💎 برای بار شونصدم: سیبی که زود چیده بشه تا ابد کال و غیرقابل استفاده می‌مونه! عین آدمی که زودتر از موعد جایگاه بالاتر بگیره.

😊 پایان این بحث
خوشحال می‌شم فیدبک بدید 🌱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🏆2
یه اصطلاحی برای توصیف کالاهای تندمصرف داریم به نام FMCG یا Fast-Moving Consumer Goods که سریع فروش می‌رن، عموما ارزون هستن. مثل مواد غذایی و نوشیدنی، لوازم نظافت و...

برای محتوای دیجیتال هم اصطلاح «محتوای زودگذر» یا ephemeral content استفاده می‌شه. یعنی محتوایی که مثل اینستاگرام (به‌خصوص استوری‌ها) یا مطالب تلگرام منتشر می‌شه، که معمولاً به سرعت توسط کاربر مصرف می‌شه. خیلی از این محتواها فقط برای چند ساعت یا چند روز قابل مشاهده هستن یا اهمیتشون رو از دست می‌دن.

چند وقته درگیر این سوال شدم که آیا اصلا تلگرام جای درستی بود برای نوشتن محتوای فنی؟ جایی که گاها مجبورم از کلمات یا علائم نگارشی حذف کنم که توی یک پست جا بشه! یا اینکه بهتر بود تلگرام برای اعلان مطلب جدید در یک پلتفرم مناسب‌تر مثل بلاگ استفاده می‌شد؟ آیا مثلا مخاطب امروز این کنال، چقدر از محتوایی که ۲ ماه پیش نوشته شده و هنوز از نظر کاربردی منقضی نشده مطلع میشه یا در معرض انتخابش قرار میگیره؟

خلاصه اینکه اگر پیشنهاد و نظری که کمک کنه داشتید خوشحال می‌شم بگید... 😊
8👍41
🤣26🤓1
🧪مقایسه دو مکتب معروف Unit Testing یعنی کلاسیک (Detroit) و لندن (Mockist)

1️⃣ تست «پیاده‌سازی» در مقابل تست «قرارداد»

🎩 کلاسیک: تست «فقط خروجی و رفتار نهایی» رو مورد ارزیابی قرار می‌ده؛ نیازی به دونستن جزئیات داخلی نیست. مثلاً اگر کد توابع کمکی رو تغییر بدیم ولی نتیجه نهایی تغییر نکنه، تست‌ها تغییر نخواهند کرد و فقط اگه Assertمون پاس شه، تست پاس شده.

🎡 لندن: تست‌ها بر اساس نحوه‌ی فراخوانی وابستگی‌ها و جزئیات پیاده‌سازی دقیق نوشته می‌شن. این یعنی تغییرات جزئی در داخل کلاس (حتی بدون تغییر در خروجی نهایی) ممکنه باعث شکست تست‌ها بشه؛ حتی اگه مثلا مقدار برگشتی یک متد دقیقا همونی باشه که قبلا بوده.

2️⃣مکان‌یابی باگ

🎩 کلاسیک: ممکنه چند تست باهم شکست بخورن چون وابستگی‌ها واقعی هستند. در نتیجه پیدا کردن مشکل ممکنه کمی زمان بیشتری ببره.

🎡 لندن: چون تست‌ها به صورت دقیق تعاملات کلاس‌ها رو چک می‌کنن، در صورت خطا معمولا به سرعت متوجه می‌شیم که مشکل کجاست.

3️⃣ مدیریت وابستگی‌های پیچیده

🎩 کلاسیک: برای تست‌های واقعی باید تمامی وابستگی‌ها پیاده‌سازی بشن که اگر تعدادشون زیاد باشه کار زمان‌بر میشه؛ ولی از طرفی این موضوع می‌تونه نشونه‌ای از طراحی پیچیده یا ناسالم سیستم باشه.

🎡 لندن: با استفاده از Mock‌ها می‌شه وابستگی‌های «سطح اول» رو شبیه‌سازی کرد بدون اینکه لازم باشه کل گراف وابستگی‌ها رو راه‌اندازی کنیم.


🤔 اگر کنجکاوی که با کد هم تفاوتش رو ببینی: ری‌اکشن ⚙️
Please open Telegram to view this post
VIEW IN TELEGRAM
24🔥2👍1
🥸 هر چیزی رو توی اینترنت دیدیم باور نکنیم، خصوصا اگر فنی «به نظر» اومد!

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

یه چالشی چند ساله مطرحه که با زبون‌های مختلف کوچک‌ترین hello world باینری رو چجوری می‌شه نوشت (مثلا جایگزینی printf با puts توی سی یا جایگزینی println با syscall_write توی راست و حذف لایبری‌های اضافه و بهبود لینکینگ و...

لذا نشستم کد راست رو بازنویسی کردم و با ۱۴ کیلوبایت جمع شد. ولی آیا اینکه منم یه توییت بزنم بگم دیدی کد راست (مینیمال راست) من از کد سی کوچیک‌تر شد، درسته؟ خیر! بلکه چرندی به چرندیات افزوده‌ام.

چرا؟ چون اونوقت باید کد مینیمال سی رو مقایسه کنیم که احتمالا باز نسبت به کد ۱۴ کیلوبایتی راست چیزی بین نصف تا یک‌سوم باید کوچیک‌تر شه.

ولی چرا باز هم سی کوچیک‌تر از راسته؟ مگه قرار نبود «عصر، عصر راست‌نویسی» باشه؟ 😁

- راست static linking داره
- راست runtime safety داره

من سورس کدم رو توی کامنت می‌گذارم. ولی اصلا نکته این مطلب اینا نبود! اینه که هر چیزی رو توی اینترنت یا از همکار و دوستمون دیدیم حتی اگر با عدد و رقم و کد آمیخته بود، تفکر انتقادیمون رو نسبت بهش حفظ کنیم 😊
👍7🔥6👏2
📎💡 توضیح ساده Read Your Own Writes Consistency یا (RYW) توی سیستم‌های توزیع‌شده

وقتی یه سیستم بزرگ داریم با تعداد زیاد کاربر یا درخواست همزمان، یکی از چالش‌های اصلی اینه که هر کاربر بتونه تغییراتی که خودش ایجاد کرده رو بلافاصله ببینه. مثلاً وقتی توی یه شبکه اجتماعی پست میذارید، انتظار دارید همون لحظه پستتون رو ببینید، نه اینکه چند ثانیه صبر کنید. به این قابلیت میگن Read Your Own Writes یا RYW (خیلی‌جاها own حذف می‌شه و در نتیجه read your writes می‌شه RYW).

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

⚙️راهکارها:

*️⃣استفاده از region-aware routing یعنی تمام درخواست‌های کاربر به یک منطقه مشخص هدایت بشه تا از تأخیرهای ناشی از تبادل داده بین مناطق مختلف جلوگیری بشه.

*️⃣استفاده از CRDTها (Conflict-Free Replicated Data Types) برای ادغام تغییرات هم به کار می‌رن تا توی مواقعی که چندین کاربر همزمان روی یه داده تغییر ایجاد می‌کنن، همگی به صورت یکپارچه به‌روز بشن

*️⃣استفاده از Session Token یعنی اطلاعاتی در مورد آخرین تغییراتی که کاربر ایجاد کرده رو نگه توی این توکن‌ها نگهداری کنیم.

یه روش دیگه که خیلی جالب عمل می‌کنه، استفاده از خواندن مبتنی برQuorum-Based Reads With Vector Clocks هست. توی این روش، وقتی می‌خوایم یه داده رو بخونیم، از چند سرور درخواست می‌دیم و آخرین نسخه رو بر اساس زمان‌بندی منطقی انتخاب می‌کنیم. همچنین تکنیک‌هایی مثل read repair وجود دارن که وقتی می‌بینیم داده‌ها به‌روز نیستن، به‌طور خودکار اون‌ها رو دوباره از دیتابیس اصلی می‌خونن و تازه می‌کنن. (برای این مورد باید پراکنده جغرافیایی وسیعی داشته باشیم تا توجیه پیدا کنه).

در نهایت، باید بگم که رسیدن به یه سیستم با Read Your Own Writes consistency توی مقیاس بزرگ نیازمند برنامه‌ریزی دقیق و نظارت مداوم هست. نمونه‌های موفق توی دنیای واقعی مثل پلتفرم‌های شبکه‌های اجتماعی، سایت‌های تجارت الکترونیک و ابزارهای همکاری آنلاین ثابت کردن که با استفاده از این تکنیک‌ها، می‌شه تجربه کاربری فوق‌العاده‌ای رو تضمین کرد. ولی برای سیستم‌هایی که مثلا توی یک کشور و حتی توی یک دیتاسنتر هستن اگر چالش RYW داشته باشیم، احتمالا و تکیه می‌کنم احتمالا یه مشکلی توی طراحی و پیاده‌سازی داریم...
Please open Telegram to view this post
VIEW IN TELEGRAM
👍92🔥2👏1
‼️استانداردسازی خطاهای REST API با Problem Details (RFC 7807)

وقتی بحث طراحی REST API میاد وسط، خیلیا فقط به CRUD فکر می‌کنن و اینکه یه سری endpoint که دیتا می‌گیرن و کوئری پاسخ می‌دن. اینکه API کار کنه و خطا نده کافی نیست، اگر استاندارد نباشه مشکلاتی متعاقب خودش به بار میاره که مفصله. استانداردهای طراحی API کمک می‌کنن که APIها قابل پیش‌بینی، خوانا و سازگار باشن. برای همین هم REST API‌های اصولی، معمولاً از الگوهای استاندارد استفاده می‌کنن.

یکی از مشکلات رایج طراحی API، مدیریت و ارسال خطاهاست. خیلی از APIها به شکل‌های مختلف خطا برمی‌گردونن؛ یکی JSON میده، یکی XML، یکی فقط یه متن ساده، و بعضی‌ها هم فقط یه HTTP Status Code. اینجاست که RFC 7807 وارد می‌شه!

تعریف RFC 7807: استاندارد کردن جزئیات خطاها توی REST API

در حقیقت RFC 7807 استانداردیه که توش تعریف شده چطور APIها می‌تونن جزئیات خطاها (Problem Details) رو به صورت JSON یا XML برگردونن، به‌جای این که هر کی واسه خودش یه فرمتی اختراع کنه. فرمت پیشنهادی این شکلیه:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"status": 403,
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/transactions/67890"
}


اجزای کلیدی:

الف: type: یه URL که نشون میده این نوع خطا چیه (میشه مستندات مربوطه رو اینجا گذاشت)
ب: title: یه توضیح کوتاه و ثابت درباره‌ی نوع خطا
پ: status: همون HTTP Status Code که برمی‌گرده
ت: detail: توضیح دقیق‌تر در مورد این خطای خاص
ث: instance: آدرسی که خطا در اون رخ داده

مزایای استفاده از Problem Details

*️⃣استاندارد بودن: همه جا یه فرمت ثابت داریم -> نرم‌افزار مونیتورینگ لاگ براش فرقی نمی‌کنه API از کجا و چه زبونی اومده، جزئیات خطا رو درست تشخیص می‌ده
*️⃣توسعه‌پذیری: می‌تونیم فیلدهای سفارشی اضافه کنیم
*️⃣مستندسازی بهتر: فرمت مشخص باعث میشه مستندات بهتری داشته باشیم
*️⃣پشتیبانی فریم‌ورک‌ها: اکثر فریم‌ورک‌های مدرن ازش پشتیبانی می‌کنن
*️⃣قابلیت اتوماسیون: ابزارها می‌تونن به راحتی خطاها رو پردازش کنن

🔗 متن استاندارد

💬 نظر شما چیه؟ از Problem Details استفاده می‌کنید؟ اگر کد مثال می‌تونه کمک کنه: ⚙️

#API_Design
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7
🥸 اندر احوالات تست‌نویسی، باب TUnit

پسری را به کارگه کدنویسی همی بردندی تا شیوه‌ی کُدگری پیشه کند، استاد بگفت: «بِکُد، سپس بِتِست!» شاگرد مدتی استاده، بُکید، خسته شد؛ لَختی درنگ کرد و از برای تستیدن پرسید:

«استاد رخصت می‌دهی تا با MSTest بِتِستَم؟»
استاد بدو گفت: «بِتِست!»

باز مدتی بِتِستید، خسته شد، گفت: «استاد، اجازت باشد تا این بار به NUnit بگرایم و بِتِستم؟»
استاد گفت: «بِتِست!»

باز مدتی بِتِستید، باز خسته شد، گفت: «استاد، دلم هوای XUnit کرده است، رخصت می‌دهی تا به آن بِتِستم؟»
استاد گفت: «بِتِست!»

دیگر نایی در تنش نمانده بود، گفت: «استاد! مرا زین همه آزمون، امان ده! باشد که آخرین بار به TUnit 🧪بِتِستم و آنگاه بیاسایم؟»
💎 استاد گفت: «تو بِتِست، بمیر و بِتِست!»

* بِتِست: فعل امر تست نوشتن
* بُکید: فعل ماضی کد نوشتن، سوم شخص مفرد


درسته که مهم، تست نوشتنه، حالا بسته به نیازمون unit، integration, e2e, behaviour, stress, یا...
حالا اگر روی این موضوع توافق داریم، ولو به «تو بِتِست، بمیر و بِتِست!» و کنجاوید بدونید TUnit آیا یه قرطی‌بازی جدیده و یه بابایی آخر هفته بیکار بوده یه چیزی نوشته و چهار روز دیگه هم ولش می‌کنه، یا اینکه نه! یه نیازی بوده که با وجود MSTest و NUnit و XUnit یه لایبری تست‌نویسی جدید به وجود اومد؟!

اگر سواله، بگید تا بیشتر در موردش بگم و یه مقایسه با اون ۳ تا پیرمرد داشته باشم...

ری‌اکشن برای توضیح بیشتر: ⚙️

💬 تجربه، نظر؟
Please open Telegram to view this post
VIEW IN TELEGRAM
17👍1
این روزها تقریبا یکسالگی TUnit است. یه کتابخونه جدید برای نوشتن Unit، Integration، Acceptance و هر جور تست دیگه‌ای توی دات‌نت. حدود ۱۹۱هزار دانلود NuGet داشته و توسعه‌اش فعلا خیلی فعاله و جزو گیت‌هاب ترند هست.

ولی چرا؟
خب می‌دونیم که NUnit عملا پورت شده‌ی JUnit جاوا است، و xUnit انشعابی بهبود یافته از NUnit.
خود NUnit که باقیمانده دوران SharpTestEx و Lin Unit و NUnitEx و NUnitAsp است که حتی ریپوهاشون هم هفت کفن پوسوندن، نزدیک به ۲۰ سال قدمت داره. درسته که همواره به‌روز شده و پوست‌اندازی داشته و امروز یه محصول بالغه؛ ولی مدت‌هاست تغییرات بزرگی نداره و فقط باگ و بوگ (بوگ به مفهوم باگچه، و باگ کوچک است) برطرف می‌کنه. (تاریخچه JUnit هم برمی‌گرده به یه پرواز بین زوریخ و آتلانتا در سال ۱۹۹۷! و الان نسل پنجم خودش رو تجربه می‌کنه)

واقعیت اینه که دنیای تست از نظر مفهوم و ساختار تغییرات انقلابی خاصی نداشته. لذا این لایبری‌ها هم فرصت داشتن تا بالغ و پایدار بشن.

چی‌ شد که TUnit متولد شد؟
اون لک‌لکی که TUnit رو توی گیت‌هاب git push کرد، و خودش هم می‌گه از NUnit و xUnit الهام گرفته، چند تا هدف داشت:
- یکی کدبیس مدرن از ابتدا
- بهبود سرعت اجرای تست

دقت کنید که این داستان «هیچ ربطی» به تیمی که هنوز توی بدیهیات تست‌نویسی گیر کرده و کاوریجش ۳۰ درصده نداره! بلکه برای تیمیه که می‌خواد از یک کتابخونه برای همه نوع تستش استفاده کنه، هزاران تست داره و سرعت اجرای تست‌ها می‌تونه تجربه توسعه‌دهنده و دواپس رو بهبود بده.
مثلا: TUnit از source generators تا جای امکان به جای reflection استفاده می‌کنه و AOT رو به خوبی پشتیبانی می‌کنه.

مثال دوم: کدبیس مدرنش به شما Hooks, Events روی کل Lifecycles تست می‌ده؛ یعنی قبل و بعد از ،TestDiscover ،TestSession، Assembly، Class، Test. مثلا شما با ایونت مطلع می‌شید تست شروع شد، تست وارد فلان مرحله شد و... این هم به درد تست‌نویس می‌خوره هم به‌درد اون بدبختی که پایپ‌لاین DevOps شما رو توسعه می‌ده.

مثال سوم: از بیخ به شما اجازه پاس دادن انواع داده برای تست رو میده. این به معنای ناتوانی xUnit نیست، بلکه پیاده‌سازی راحت‌تر و مدرن‌تره. وقتی شما سرعت 321.7 میلی‌ثانیه TUnit در مقابل ۱۴ ثانیه xUnit به کارتون میاد، که اولا «واقعنکی» (به معنی خیلی واقعی) تست می‌نویسید. دوم اینکه تعداد زیادی تست دارید و... البته این تفاوت زیاد، فقط در برخی موارد است چون TUnit قابلیت AOT دارد و در خیلی از موارد تفاوت حداقل هنوز اینقدرها نیست.

ولی این سرعت توسعه مداوم و یکپارچگی با IDEها وقابلیت Analyzer درونی اونم از ابتدای راه و اقبالی که جامعه دات‌نت بهش داشته، آینده خوبی براش رقم می‌زنه. خدا از من نگذره اگر ذره‌ای قصد «امروزه عصر، عصر توسعه تست با TUnit است» داشته باشم... 😅 ایها‌الناس: شما «بِتِست، بمیر و بِتِست!»

ریپو
مستندات
👍182
طراحی API و مفهوم Idempotency

معنی idempotent : شاید بشه «همانندپذیر» رو معادل خوبی براش دونست؛ توی ریاضی «عدد ۱ در عملیات ضرب» همانندپذیر هست، چون هر چند بار که یک در خودش ضرب شه، باز هم ۱ به دست میاد. ولی ۲ اینطور نیست چون ۲ اگر در خودش ضرب شه می‌شه ۴.
پس idempotent عملیاتی هست که چندین بار اجرا کردنش، نتیجه‌ای مشابه با یک بار اجرا کردنش داره.

یکی از دغدغه‌های اصلی توی سیستم‌هایی مثل پرداخت‌ یا عملیات حساس، اینه که وقتی کاربر چندبار یک درخواست رو می‌فرسته، سیستمو نباید چندبار اون رو پردازش کنه. به بیان ساده‌تر، API ما باید idempotent باشه؛ یعنی خروجی و اثرش هر بار یکسان باشه، حتی اگر درخواست رو چند بار ارسال کنیم (حالا چه سهوی، چه تعمدی و با قصد بد!) مثلا کاربر اگر API پرداخت رو چند بار فراخوانی کنه ممکنه چند بار وجه از حسابش کسر بشه یا مواردی از این دست.

روش‌های طراحی APIهای Idempotent

1️⃣ استفاده از Idempotency-Key
یکی از روش‌های رایج برای حل این مشکل استفاده از یک کلید منحصر به فرد به نام Idempotency-Key است. وقتی کاربر یک درخواست حساس (مثلاً پرداخت) رو ارسال می‌کنه، یک کلید یکتا همراه درخواست ارسال میشه. سرور وقتی درخواست رو دریافت می‌کنه، اول چک می‌کنه که آیا قبلاً درخواستی با اون کلید دریافت شده یا نه.
POST /payments
Headers: {
"Idempotency-Key": "abc123"
}
Body: {
"amount": 1000,
"currency": "IRR"
}


2️⃣ روش Optimistic Concurrency Control
استفاده از کنترل همزمانی خوشبینانه (Optimistic Concurrency Control). هر موجودیت (entity) یه نسخه یا شناسه تغییر (مثلاً ETag) داره. وقتی کاربر می‌خواد تغییراتی رو روی اون موجودیت اعمال کنه، نسخه موجودیت رو همراه درخواست می‌فرسته.
اگر نسخه‌ای که فرستاده شده با نسخه فعلی مطابقت داشته باشه، تغییر اعمال میشه؛ در غیر این صورت، یعنی کسی یا چیزی قبلاً تغییر ایجاد کرده و سرور خطا برمی‌گردونه.

PUT /orders/123
Headers: {
"If-Match": "v1"
}
Body: {
"status": "paid"
}

3️⃣ روش Conditional Requests
از Conditional Requests می‌شه استفاده کرد، یعنی با استفاده از هدرهای HTTP مثل If-None-Match یا If-Modified-Since وقتی کاربر درخواست می‌ده، سرور بررسی می‌کنه که آیا داده‌های موجود تغییر کرده یا نه.
اگر داده تغییر نکرده باشه، سرور یک پاسخ مشابه برمی‌گردونه بدون اینکه دوباره عملیات رو انجام بده. مثلا: فرض کن کاربر می‌خواد اطلاعات پروفایل خودش رو آپدیت کنه. همراه درخواست هدر If-Unmodified-Since ارسال میشه که نشان دهنده آخرین باریه که اطلاعات تغییر کرده‌اند. اگر اطلاعات بین اون زمان تغییر نکرده باشه، عملیات به درستی انجام میشه؛ در غیر این صورت، سرور خطا میده که نشان میده اطلاعات به‌روزرسانی نشده یا تغییر کرده.

💬 نظر؟ بحث؟ گپ بزنیم؟

#API_Design
Please open Telegram to view this post
VIEW IN TELEGRAM
👍175
🤪 در باب تفکیک انتقاد از هجمه!

ℹ️ این مطلب فنی نیست، رفرنس‌محور هم نیست، و تحلیل و نوشتار شخصی ( و طبیعتا محتمل‌به‌خطا) است!

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

شاید خیلی از ما ترجیح ندیم که ویدیو خیلی عمومی بسازیم و خودمون رو خواسته یا ناخواسته در معرض دید عموم قرار بدیم. ولی در مقیاس محدودتر امکان داره برای هر کدوم از ما پیش بیاد. امکان داره در یک گپ ۳ نفره توی شرکت یه سوتی سهوی بدیم؛ و احتمالا نمی‌پسندیم اون ۲ نفر حاضر در اون جمع کوچیک؛ ما رو دستمایه مسخره کردن یا قضاوتشون قرار بدن.

حالا بیایم این شرایط و فضا رو که کم‌وبیش دیده‌ایم یه مقدار بشکافیم...

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

- خواستگاه تعداد زیادی از این بازخوردها، ولو اینکه خیلی موجه و منطقی به نظر بیان، باز هم خشم است!

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

- هیچ اظهار نظری، اعم از یک نظر اشتباه، ناقص یا حتی مضحک در مورد یک تکنولوژی؛ یا یک شیوه صحبت کردن یا یک تُپُق یا... اینقدر ناموسی و مهم نیست... چرا فکر نکنیم یک نفر از ۸ میلیارد جمعیت زمین یه نظری داده! چقدر موثره مگه؟! اگر من اومدم اینجا در مورد API Design یا ... یه مزخرفی گفتم، شما برو تحقیق کن درستش رو یاد بگیر، یا درستش رو جایی بنویس...

- این روزها و سال‌ها جامعه ما (و حتی جهان) این‌قدر آکنده از خشم و تفرقه است که ای کاش ما سهمی حتی در حد یک لایک یا کامنت ولو بامزه، در این حجم از نجاست خشم و نفرت نداشته باشیم

🌱 نقد سازنده در هر موضوعی ۴ تا مولفه‌ی «لاینفک» داره: ۱: پرداختن به موضوع به جای مصداق ۲: همراه داشتن راه‌حل منطقی ۳: پرهیز از تعصب و خشم و هیجان ۴: باور به حق آزاداندیشی، هر کسی آزاده تا هر باور و نظری داشته باشه، و در صورت ضرر به دیگران، قانون باید براش تصمیم بگیره و بس.

💬 اگر این مطلب رو خوندید، اولا متشکرم 😊 دوم اینکه خوشحال می‌شم نظرتون رو بدونم...
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84
✍️مرور چند روش رایج صفحه‌بندی (Pagination) در API Design

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

و این خیلی مهم می‌شه که روش استاندارد و یکسانی داشته باشیم تا یکی شماره صفحه و تعداد رو توی GET نگیره یکی توی POST تا بتونیم هم جلو بار اضافی به سرور رو بگیریم هم کاربری یا توسعه‌دهنده‌ای که با API سر و کار داره دیوانه نشه!

1️⃣ روش Offset & Limit (یا Page & Size)

GET /users?limit=10&offset=20

این روش ساده و سرراسته، و امکان دسترسی مستقیم به صفحه دلخواه رو فراهم می‌کنه. ولی وقتی دیتاست خیلی بزرگ شه، مستعد درخواست‌های عمدی یا سهوی کند کننده است! یا اگر داده‌ها مرتب تغییر کنن، شما یا یه چیزی از قلم می‌ندازی یا تا بری صفحه ۲، دیتای صفحه ۱ افتاده توی صفحه ۲! (نرخ بالای تغییرات) کوئری‌اش هم اینجوریه:
-- SQL Server:
SELECT * FROM users
ORDER BY id
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;

-- PostgreSQL:
SELECT * FROM users
ORDER BY id
LIMIT 10 OFFSET 20;

-- MongoDB:
db.users.find()
.sort({ id: 1 })
.skip(20)
.limit(10);


2️⃣ روش Cursor-based Pagination
توی این روش به جای استفاده از offset، از یک نشانگر (cursor) استفاده می‌کنیم که به عنوان مرجع برای ادامه‌ی داده‌ها عمل می‌کنه. معمولاً این cursor می‌تونه آخرین مقدار یک فیلد کلیدی مثل id یا تاریخ ایجاد باشه.
GET /users?limit=10&cursor=eyJpZCI6IDIwMH0=

این روش کارایی بهتری توی داده‌های بزرگ داره، یکی از دلایلش اینه که نیازی سورت کردن داده و بعدش رد کردن تعدادی رکورد نداره! بلکه مستقیم (با کمک ایندکس البته) می‌ره سراغ رکورد مورد نظر و تامام. اگر داده‌ها مرتب تغییر کنن، باز کاربر مسیر خودش رو پیمایش می‌کنه و داده‌های تکراری نمی‌بینه یا داده‌هایی رو از دست نمی‌ده.
ولی: پیچیدگی پیاده‌سازیش بیشتره. صفحه ۵ الزامان برای همه و در همه زمان‌ها یک داده‌ رو نشون نمی‌ده.
برای مقیاس بزرگ این روش مناسب‌تره، اون بار تحمیلی سورت و skip توی مقیاس بزرگ کمرشکنه!

3️⃣روش Seek-pagination (Keyset Pagination)
روش seek-pagination یا keyset pagination به روش cursor-based شباهت داره، ولی به صورت صریح از شرایط WHERE استفاده می‌کنه تا رکوردهایی که بعد از آخرین مقدار دیده شده قرار دارن رو برگردونه.
GET /orders?limit=10&last_id=1000

در اینجا فرض می‌کنیم که last_id نشان‌دهنده‌ی آخرین id دیده شده در صفحه قبلی هست. سرور از شرط WHERE id > 1000 استفاده می‌کنه تا رکوردهای بعدی رو برگردونه.

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


4️⃣روش Time-Based Pagination
GET /events?since=2023-10-01&until=2023-10-08


5️⃣روش Hypermedia (HATEOAS) Links
Link: </items?cursor=def456>; rel="next", </items?cursor=abc123>; rel="prev"


6️⃣روش Metadata in Responses
{
"data": [...],
"pagination": {
"total": 1000,
"next_cursor": "def456",
"has_more": true
}
}


💬 اولندش بحث؟ نظر؟ تجربه؟ دُوُمَندش ۴ و ۵ و ۶ رو توضیح ندادم که الکی مثلا کنجکاوی ایجاد کنم، هزاران و میلیان‌ها ری‌اکشن ⚙️ بدید که توضیح بدم و بگم چرا روش HATEOAS روش منطبق با REST principles ذیل discoverability است!! 😅 سِوُمَندش دون بپاشم برای پرداختن عمیق‌تر به اهمیت ایندکس و درک ساختاریش، بعد از یخورده مطلب حول طراحی API نوشتم...

#API_Design
Please open Telegram to view this post
VIEW IN TELEGRAM
34👍3🤓1
tech-afternoon
✍️مرور چند روش رایج صفحه‌بندی (Pagination) در API Design وقتی با داده‌های بزرگ سر و کار داریم، نمایش اطلاعات به صورت صفحه‌بندی شده خیلی مهم‌تر از حالت عادیه که دریافت داده از سمت سرور بار قابل توجهی نداره (چه سمت واکشی داده، چه سمت ارسال به سمت کلاینت) و…
✍️2️⃣ توضیح روش‌های ۴ تا ۶ صفحه‌بندی (Pagination) در API

4️⃣ روش Time-Based Pagination
وقتی داده‌هامون به ترتیب زمان ثبت می‌شن (مثلاً رویدادهای یک سیستم لاگ یا خبرنامه‌های زنده)، می‌تونیم با استفاده از پارامترهایی مثل since و until بازه‌ی زمانی دلخواهمون رو مشخص کنیم.
مثال:

GET /events?since=2025-01-01&until=2025-01-10

اینجا API رو طوری طراحی می‌کنیم که همه‌ی رویدادهایی که بین اول تا دهم ژانویه اتفاق افتاده رو برگردونه.

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

5️⃣ روش Hypermedia (HATEOAS) Links
روش HATEOAS (Hypermedia As The Engine Of Application State) یکی از اصول کلیدی REST هست. توی این روش، پاسخ‌های API شامل لینک‌هایی به صفحات بعدی یا قبلی هستند. این لینک‌ها معمولاً در هدر یا بدنه‌ی پاسخ قرار می‌گیرند و به کلاینت می‌گن «برای ادامه اینجا رو ببین» یا «صفحه قبلی اینجاست».
مثال:
Link: </items?cursor=def456>; rel="next", </items?cursor=abc123>; rel="prev"

توی این مثال، لینک‌های next و prev به کلاینت کمک می‌کنن بدون اینکه خودشون URL ها رو بسازن، به صفحات بعدی یا قبلی دسترسی پیدا کنن.

بزرگ‌ترین مزیتش علاوه بر استاندارد بودن، اینه که کلاینت‌ها نیازی به دونستن ساختار URL‌ها ندارن؛ API خودش مسیر بعدی رو بهشون میگه. در ضمن به راحتی می‌شه لینک‌های مختلف (مثلاً first، last، یا حتی لینک‌های مرتبط) رو اضافه کرد.از طرفی مدیریت و تولید این لینک‌ها به دقت نیاز داره تا همه‌ی روابط درست تعریف بشه؛ و استفاده از هدرهای HTTP اضافی ممکنه برای برخی کلاینت‌ها و ابزارها پیچیده باشه.


6️⃣ روش Metadata in Responses
توی این روش، به جای ارسال اطلاعات صفحه‌بندی در هدر، کل متادیتا (مثل تعداد کل رکوردها، cursor بعدی، و وضعیت وجود صفحه‌ی بعدی) رو توی بدنه‌ی پاسخ JSON می‌گنجونیم. این کار باعث می‌شه کلاینت به راحتی اطلاعات لازم رو از یک جا دریافت کنه.

{
"data": [...],
"pagination": {
"total": 1000,
"next_cursor": "def456",
"has_more": true
}
}

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

💬 نظر؟ بریم سراغ موضوع دیگه: 🤓
یا روی API Design ادامه بدیم: ⚙️

اگر روی API Design بمونیم:
- موضوع API Documentation و Discoverability
- استراتژی‌های مدیریت نسخه‌بندی API در طول زمان (API Evolution)
Please open Telegram to view this post
VIEW IN TELEGRAM
21🔥1
📎در باب API Documentation و Discoverability

بیاین فرض کنیم REST API ماه مثل منو رستورانه؛ API Documentation همون فهرستیه که جزئیات هر غذا (یا توی این مورد، هر endpoint) رو شرح می‌ده، مثلاً ورودی‌ها، خروجی‌ها، خطاهای احتمالی و ...

از طرفی، Discoverability یعنی این که چطور می‌تونیم به راحتی بفهمیم کدوم endpoint ها وجود دارن و چه امکاناتی رو فراهم می‌کنن. این باعث میشه که توسعه‌دهنده‌ سریع‌تر بتونه از API استفاده کنه و به روزرسانی‌ها رو در زمان مناسب متوجه بشه. این روز‌ها هم که به جز توی پروژه‌ها و تیم‌های کوچیک، افراد و حتی تیم‌هایی که API رو توسعه می‌دن و API رو مصرف می‌کنن؛ از هم جداست. پس باید به فکر اون بیچاره‌ای که می‌خواد API رو سمت خودش استفاده کنه هم باشیم؛ هم Documentation و هم Discoverability رو پاس بداریم (به فکر اعصاب افراد و وقت خودمون باشیم)

⚙️ مفهوم API Documentation؟
- راهنمای ورودی و خروجی: چه پارامترهایی نیاز دارین و خروجی چجوری خواهد بود. خصوصا وقتی آبجکت‌های پیجیده و بزرگ تبادل می‌شه، این موضوع مهم خواهد بود.
- مثال‌های کاربردی: نشون دادن نمونه درخواست و پاسخ.
- خطاها: توضیح اینکه چه خطاهایی ممکنه پیش بیاد و چطور می‌تونین اونا رو مدیریت کنین.


⚙️ مفهوم Discoverability (قابلیت کشف API)
وقتی از Discoverability صحبت می‌کنیم، منظورمون اینه که API هایمون به راحتی قابل دسترسی و شناسایی باشه. این یعنی:
- سازماندهی مناسب: ساختار واضح و منظم برای endpointها.
- استفاده از استانداردها: مثل OpenAPI Specification که باعث میشه ابزارهای مختلف بتونن مستندات شما رو بخونن و حتی تست کنند.
- امکانات جستجو: مثلاً داشبوردهایی که امکان فیلتر کردن و جستجو در مستندات رو فراهم می‌کنن.


نگاهی به اکوسیستم:

استاندارد OpenAPI Specification: یه استاندارد باز برای توصیف APIها که اکثر ابزارهای مدرن از اون استفاده می‌کنن. و تقریبا مهم‌ترین استاندارد این حوزه است.

ابزارهای Swagger UI / Swagger Editor: ابزاری برای نمایش مستندات API به صورت تعاملی (از OpenAPI به خوبی پشتیبانی می‌کنه)

ابزار Redoc: یه ابزار خوب برای ارائه مستندات API سازگار با OpenAPI به صورت آنلاین.

پلتفرم Postman: علاوه بر تست API، مستندات خوبی از APIها ایجاد می‌کنه، فضای مناسبی برای اشتراک API + Doc + Test + ... برای تیم‌ها و شرکت‌ها داره و کلا یک پلتفرم برای API سازمان است و محدود به یه تولز برای GET و POST نیست... پیشرو این داستانه و بعدتر Insomnia و ابزارهای مشابه هم با قوت و کاستی‌های خاص خودشون اومدن

* ابزارهایی مثل API Blueprint هم بودن که اهمیت یا استقبال زیادی نداشتن و به حاشیه رونده شدن.

برای گو: swaggo و go-swagger
برای پایتون: خود FastAPI به صورت ضمنی
برای دات‌نت: دقت کنید که دات‌نت در نسخه ۹ به بعد هم کمافی‌السابق OpenAPI رو پشتیبانی می‌کنه، بحث‌ها سر جایگزینی اون UI سابقی است که Swagger UI تولید می‌کرد. و جایگزین‌هایی برای تولید Swagger UI و Redoc و Scaler ارائه شده.

💬 نظر؟ تجربه؟ سوال؟

📌 درضمن، به‌زودی شیوه ارائه مطالب تغییر می‌کنه، توی وبلاگ خواهم نوشت که امکانات بهتری برای پیدا کردن مطالب و دسته‌بندی‌ها و تجربه مطالعه داره و اینجا اعلانش رو قرار خواهم داد. برای همین هم این کد کوچیک رو نوشتم تا از مطالب کانال تلگرامی خروجی Markdown بگیرم که سریع‌تر مطالب فعلی رو منتقل کنم... اگر ایده یا پیشنهاد یا نقدی دارید خوشحال می‌شم.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍113
✍️ مقایسه روش‌های نسخه‌بندی API

1️⃣روش URL Versioning
GET /v1/products HTTP/1.1
Host: api.example.com

ساده و واضح، نسخه‌بندی توی URL به راحتی قابل تشخیص و دیدنه. و پیاده‌سازیش خیلی ساده و مورد پشتیبانی اکثر فریم‌ورک‌هاست.

جاهایی که نرخ تغییرات زیاده، نگهداری و مدیریت دشوار می‌شه

2️⃣ روش Header Versioning
GET /products HTTP/1.1
Host: api.example.com
X-API-Version: 1


جداسازی نسخه‌بندی از URL، باعث می‌شه URL ثابت بمونه؛ و انعطاف‌پذیری بالاتر برای مدیریت نسخه‌بندی.
نیاز به تنظیمات اضافی در سمت کلاینت برای ارسال header. نیاز به دقت بیشتری برای مشاهده و شناسایی داره.

3️⃣ روش Media Type Versioning
GET /products HTTP/1.1
Host: api.example.com
Accept: application/vnd.myapi.v1+json

انطباق بالا با استانداردهای RESTful. و انعطاف‌پذیری توی انتخاب انواع خروجی (مثلاً تغییر application/xxx).
پیچیدگی توی تنظیم و پیکربندی. و ممکنه برای یه عده از برنامه‌نویس‌ها کمی گیج‌کننده باشه.
=======================
چطوری API هامون رو بدون نیاز به breaking changes توسعه بدیم؟

۱. روش Feature Flags
استفاده از feature flags این امکان رو میده که ویژگی‌های جدید رو به صورت تدریجی به کاربران عرضه کنیم و در صورت بروز مشکل، به سرعت اونها رو غیرفعال کنیم (توی محصولات بزرگ این روش خیلی مرسومه).

مثال:
زمان توسعه یک endpoint جدید، می‌تونید با اضافه کردن یک feature flag، به صورت تدریجی این ویژگی رو برای گروه‌های خاصی فعال کنید.

۲. روش API Gateway Transformations
با API Gateway می‌شه درخواست‌ها و پاسخ‌ها رو بین نسخه‌های مختلف API تغییر داد و این امکان رو می‌ده که نسخه‌های قدیمی API رو بدون مشکل پشتیبانی کنیم.

مثال:
فرض کنین نسخه‌ی جدید API ساختار پاسخ‌ها رو تغییر داده؛ با استفاده از API Gateway می‌تونیم داده‌های نسخه قدیمی رو به فرمت نسخه جدید تبدیل کنیم بدون اینکه نیاز به تغییر کدهای کلاینت داشته باشیم (البته خوبه این کار رو تا زمان ارتقاء نسخه‌های کلاینت دنبال کنیم و دایمی نباشه).

۳. روش Backward Compatibility
توسعه API به شیوه‌ای که تغییرات جدید باعث breaking change نسخه‌های قبلی نشه. برای این کار، معمولا:
- اضافه کردن فیلدهای جدید به داده‌های خروجی به جای تغییر یا حذف فیلدهای قدیمی.
- استفاده از ورژن‌بندی تدریجی (rollout) برای نسخه‌های جدید.

=======================

آقا/خانم... این داستان API یه موضوع حیاتیه. با استفاده از روش‌هایی مثل URL versioning، Header versioning و Media Type versioning می‌تونیم ساختار API رو بهینه کنیم. همچنین، به کمک تکنیک‌هایی مثل feature flags، API gateway transformations و حفظ backward compatibility، می‌تونیم تغییرات رو به صورت تدریجی اعمال کنیم بدون اینکه کاربران موجود با خطا مواجه بشن.

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

💬 سوال؟ نظر؟ تجربه؟

اگر موافقید تا اینجا API Design بس باشه، یه مدت تنوع بدیم...
Please open Telegram to view this post
VIEW IN TELEGRAM
👍106
This media is not supported in your browser
VIEW IN TELEGRAM
موضوع پست‌های بعدی رو حدس بزنید 😁
😁11🤣3