TGViewer
Channel Public Channel
C# Geeks (.NET)

C# Geeks (.NET)

@csharpgeeks

Subscribers
550
Photos
157
Videos
4
Links
177

Showing posts older than #694 · Back to latest

Older Posts 20 shown
Post #693 321
🚫 چه زمانی نباید از Design Patternها استفاده کنیم؟

یکی از بزرگ‌ترین اشتباهات برنامه‌نویس‌ها این است که فکر می‌کنند هر مسئله‌ای باید با یک Design Pattern حل شود.
در حالی که بسیاری از Patternها برای حل مشکلات پیچیده طراحی شده‌اند، نه برای پیچیده‌تر کردن کدهای ساده.
گاهی یک متد ساده یا یک if دقیقاً همان چیزی است که نیاز دارید. 👇
1️⃣ Adapter

❌ زیاده‌روی است وقتی:
فقط قرار است یک یا دو نوع داده را تبدیل (Map) کنید.
✅ به‌جای آن:
یک Mapper ساده یا Helper Method بنویسید.

2️⃣ Decorator

❌ زیاده‌روی است وقتی:
فقط می‌خواهید یک Validation یا Log ساده اضافه کنید.
✅ به‌جای آن:
از Pipeline، Middleware یا حتی منطق مستقیم استفاده کنید.

3️⃣ Facade

❌ زیاده‌روی است وقتی:
زیرسیستم شما API واضح و ساده‌ای دارد.
✅ به‌جای آن:
مستقیماً همان Service را فراخوانی کنید.

4️⃣ Abstract Factory

❌ زیاده‌روی است وقتی:
فقط یک یا دو نوع شیء می‌سازید.
✅ به‌جای آن:
از Constructor یا Factory Method ساده استفاده کنید.

5️⃣ Strategy

❌ زیاده‌روی است وقتی:
رفتار فقط چند حالت ساده دارد.
✅ به‌جای آن:
یک if/else یا switch کاملاً کافی است.

6️⃣ Builder

❌ زیاده‌روی است وقتی:
شیء فقط چند Property اختیاری دارد.
✅ به‌جای آن:
از Object Initializer یا پارامترهای Optional استفاده کنید.

7️⃣ Factory Method

❌ زیاده‌روی است وقتی:
منطق ساخت شیء بسیار ساده است.
✅ به‌جای آن:
از new یا یک Helper استفاده کنید.

8️⃣ Chain of Responsibility

❌ زیاده‌روی است وقتی:
جریان اجرای شما کوتاه و ثابت است.
✅ به‌جای آن:
یک Pipeline ساده از متدها بسازید.

9️⃣ Template Method

❌ زیاده‌روی است وقتی:
فقط بخش کوچکی از الگوریتم تغییر می‌کند.
✅ به‌جای آن:
از Delegate یا یک متد مشترک استفاده کنید.

🔟 Bridge

❌ زیاده‌روی است وقتی:
فقط یک بُعد تغییر در سیستم دارید.
✅ به‌جای آن:
ءComposition یا یک Interface ساده کافی است.

1️⃣1️⃣ Command

❌ زیاده‌روی است وقتی:
عملیات ساده هستند و نیازی به Queue، Undo یا Retry ندارند.
✅ به‌جای آن:
مستقیماً متد موردنظر را صدا بزنید.

1️⃣2️⃣ State

❌ زیاده‌روی است وقتی:
فقط چند State ساده دارید.
✅ به‌جای آن:
یک enum همراه با switch استفاده کنید.

1️⃣3️⃣ Proxy

❌ زیاده‌روی است وقتی:
فقط یک Wrapper کوچک نیاز دارید.
✅ به‌جای آن:
یک Helper یا Wrapper ساده بنویسید.

1️⃣4️⃣ Observer

❌ زیاده‌روی است وقتی:
فقط یک یا دو Receiver دارید.
✅ به‌جای آن:
از Callback یا فراخوانی مستقیم متد استفاده کنید.

1️⃣5️⃣ Composite

❌ زیاده‌روی است وقتی:
قرار نیست با Itemها و Groupها رفتار یکسانی داشته باشید.
✅ به‌جای آن:
منطق List و Item را جدا نگه دارید.

1️⃣6️⃣ Visitor

❌ زیاده‌روی است وقتی:
مدل دائماً تغییر می‌کند و تعداد عملیات کم است.
✅ به‌جای آن:
ءPattern Matching یا switch انتخاب بهتری است.

1️⃣7️⃣ Prototype

❌ زیاده‌روی است وقتی:
کپی گرفتن از اشیاء ساده است.
✅ به‌جای آن:
از Copy Constructor یا Mapper استفاده کنید.

1️⃣8️⃣ Flyweight

❌ زیاده‌روی است وقتی:
مصرف حافظه مشکل اصلی سیستم نیست.
✅ به‌جای آن:
از Objectهای معمولی و Cache هدفمند استفاده کنید.

1️⃣9️⃣ Interpreter

❌ زیاده‌روی است وقتی:
قوانین سیستم کم و ثابت هستند.
✅ به‌جای آن:
از Parser ساده یا Configuration Table استفاده کنید.

2️⃣0️⃣ Singleton

❌ زیاده‌روی است وقتی:
فقط یک سرویس مشترک می‌خواهید.
✅ به‌جای آن:
آن را به‌صورت Singleton در DI Container ثبت کنید، نه اینکه الگوی Singleton را پیاده‌سازی کنید.

2️⃣1️⃣ Mediator

❌ زیاده‌روی است وقتی:
فقط چند سرویس محدود با هم تعامل دارند.
✅ به‌جای آن:
از فراخوانی مستقیم Service به Service استفاده کنید.

🎯 جمع بندی

ءDesign Patternها ابزار هستند، نه هدف.
بهترین معماری، معماری‌ای نیست که بیشترین Pattern را داشته باشد؛ بلکه معماری‌ای است که ساده‌ترین راه‌حل ممکن را برای مسئله‌ی واقعی انتخاب کند.
همان‌طور که Martin Fowler می‌گوید:
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." 💡
گاهی بهترین Pattern، استفاده نکردن از Pattern است. 😉
Post #691 319
نرم‌افزار هیچ‌وقت «تمام‌شده» نیست. و دقیقاً به همین دلیل است که باید در مسیر، موفقیت‌های کوچک را جشن گرفت.

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

من دیده‌ام افرادی که اجازه داده‌اند یک یا دو سال از زندگی کاری‌شان در یک حالت کاریِ بی‌وقفه و فرسایشی محو شود و آن را «طبیعی» بنامند. خودم هم این را تجربه کرده‌ام. یک روز نگاه می‌کنی و می‌بینی بخش بزرگی از مسیر شغلی‌ات گذشته، بدون اینکه حتی لحظه‌ای توقف کرده باشی تا احساس خوبی نسبت به آن داشته باشی.

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

کار قرار نیست متوقف شود تا به تو تبریک بگوید. پس این کار را باید خودت برای خودت بسازی.
Post #690 309
یکی از اشتباهاتی که در بسیاری از پروژه‌های NET. دیده می‌شود، استفاده از "throw" برای خطاهای قابل انتظار (Expected Errors) است.

فرض کنید کاربر می‌خواهد سفارشی ثبت کند، اما موجودی کالا کافی نیست.

❌ این یک Exception نیست:
throw new OutOfStockException();

✅ این یک نتیجه‌ی قابل انتظار از منطق کسب‌وکار است:
return Result.Failure(Errors.Product.OutOfStock);

چرا؟
🔹 ساختن Exception شامل ایجاد Stack Trace است که هزینه‌ی CPU و حافظه دارد.
🔹 پرتاب و Catch کردن Exception مسیر اجرای برنامه را کندتر می‌کند.
🔹 درواقع Exception برای اتفاقات غیرمنتظره طراحی شده است، نه اعتبارسنجی قوانین کسب‌وکار.

قاعده‌ای که همیشه از آن استفاده می‌کنیم:
✅ Expected Error → "Result"


• موجودی کافی نیست.
• کاربر پیدا نشد.
• اعتبارسنجی ناموفق بود.
• سفارش قبلاً پرداخت شده است.

❌ Unexpected Error → "throw"


• قطع شدن Database
• خطای شبکه
• باگ برنامه
• شرایطی که هرگز نباید رخ دهند

به این ترتیب:
✔️ کد خواناتر می‌شود.
✔️ جریان اجرای برنامه شفاف‌تر است.
✔️ از هزینه‌ی غیرضروری Exceptionها جلوگیری می‌شود.
✔️ و Performance در سناریوهای پرتکرار بهتر خواهد بود.

پس Result برای کنترل جریان عادی برنامه است و Exception برای شرایط استثنایی.
Post #689 298
Post #688 312
The best abstraction is the one you don't have to write. 😉☕️
Post #687 369
یکی از اشتباه‌ ترین تصور هایی که اوایل مسیر داشتم این بود که فکر می‌کردم هر مسئله‌ای باید یک راه‌ حل درست داشته باشد.
یک جواب.
یک تصمیم صحیح.
یک انتخاب واضح.
اما هرچه بیشتر در پروژه‌ های واقعی کار کردم، بیشتر فهمیدم که بسیاری از تصمیم‌ های مهندسی این‌ گونه نیستند.
مثلاً:
آیا باید Monolith بمانیم یا به سمت Microservice برویم؟
آیا باید Cache اضافه کنیم؟
آیا باید سیستم را Rewrite کنیم؟
آیا باید این Feature را Generic طراحی کنیم؟

جالب است که برای همه این سوال‌ ها می‌توان مثال‌ هایی پیدا کرد که پاسخ «بله» درست باشد.
و مثال‌ هایی که پاسخ «خیر» درست باشد.
همان‌ جا بود که فهمیدم بخش بزرگی از مهندسی نرم‌ افزار، پیدا کردن پاسخ درست نیست.فهمیدن سوال درست است.
چون خیلی وقت‌ ها قبل از اینکه راه‌ حل اشتباهی انتخاب کنیم،
در حال حل کردن مسئله اشتباهی هستیم.
ساعت‌ ها روی Performance کار می‌کنیم، در حالی که گلوگاه اصلی جای دیگری است.
معماری را پیچیده می‌کنیم، در حالی که مشکل واقعی فرآیند های تیم است.
سیستم را Scale می‌کنیم، در حالی که مسئله از یک Query اشتباه شروع شده است.
شاید به همین دلیل است که مهندسان باتجربه، معمولاً زودتر از بقیه راه‌ حل ارائه نمی‌دهند.
آن‌ها مدت بیشتری روی فهمیدن مسئله وقت می‌گذارند.
چون می‌دانند انتخاب بهترین راه‌ حل برای یک مسئله اشتباه،
هنوز هم یک اشتباه است.
Post #686 230

Forwarded from thisisnabi.dev [Farsi]

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

جدای از اینکه خوب هست یا بد، نگاه من اینه که در مصاحبه جزئیات رو از سوال کننده بخواید، خیلی از تصمیم ها بخاطر یک جزئیات کوچک می توانند رد بشن.

در کنار این پرداختن به جزییات سطح آگاهی شما رو به تصویر میکشه.

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

@thisisnabi_dev
Post #685 296
Post #684 244

Forwarded from thisisnabi.dev [Farsi]

4. Batch Processing

من این منابع برام جذاب بوده.
1. Designing Data-Intensive Applications E2
- Storage and Retrieval [4]
- Batch Processing [11]

2. Fundamentals of Data Engineering
- Designing Good Data Architecture [3]
- Storage [6]
- Ingestion [7]


Update 1:
تعطیلات سردتون نکنه، اگر چالش های قبلی رو نرسیدید بهترین وقته برای ریبیس شدن.

@thisisnabi_dev
Post #683 271
Post #682 333
#مهندس_فکر_کن
قسمت:3️⃣

🎯مصاحبه‌کننده:
فرض کنید یک سرویس دارید که روزانه میلیون‌ها درخواست را پردازش می‌کند.
ناگهان یکی از اعضای تیم متوجه می‌شود که در بعضی شرایط نادر، دو Thread همزمان وارد یک بخش حساس از کد می‌شوند و باعث ایجاد داده ناسازگار می‌شوند.
برای حل این مشکل چه مراحلی را باید طی کرد؟
Post #681 403
🔐 چرا شرکت‌های بزرگ یک Identity Provider جداگانه می‌سازند؟

اوایل پروژه همه چیز ساده است.
کاربر لاگین می‌کند، JWT می‌گیرد و تمام.
اما وقتی تعداد سرویس‌ها بیشتر می‌شود، ناگهان هر سرویس شروع می‌کند به مدیریت کاربران، نقش‌ها، دسترسی‌ها، Refresh Tokenها و Social Loginها.
همین‌جاست که مفهوم Identity Provider (IdP) وارد می‌شود.
به جای اینکه هر سرویس خودش مسئول احراز هویت باشد، یک سرویس مرکزی فقط روی Authentication و Authorization تمرکز می‌کند.
🏗 معماری سنتی
User
↓
Service A
↓
Database

User
↓
Service B
↓
Database

هر سرویس منطق احراز هویت خودش را دارد.
🏗 معماری با Identity Provider
User
↓
Identity Provider
↓
Access Token

↓
┌─────────┼─────────┐
↓ ↓ ↓
Service A Service B Service C

تمام سرویس‌ها فقط اعتبار Token را بررسی می‌کنند و دیگر درگیر فرآیند Login نیستند.
✅ مزایا
1️⃣ Single Sign-On (SSO)

کاربر یک بار وارد می‌شود و به همه سیستم‌ها دسترسی پیدا می‌کند.
2️⃣ تمرکز روی امنیت

تمام منطق امنیتی در یک نقطه قرار می‌گیرد:
• Password Policy
• MFA
• OAuth
• OpenID Connect
• Account Lockout
• Device Management
3️⃣ کاهش کد تکراری

دیگر لازم نیست هر سرویس:
• Login Endpoint
• Refresh Token Logic
• Password Reset
• Email Verification
را جداگانه پیاده‌سازی کند.
4️⃣ توسعه‌پذیری بیشتر

اضافه کردن Google Login، GitHub Login یا Azure AD فقط در IdP انجام می‌شود.
تمام سرویس‌ها به صورت خودکار از آن بهره می‌برند.
5️⃣ مدیریت متمرکز دسترسی‌ها

ءRoleها، Permissionها و Claimها در یک نقطه نگهداری می‌شوند.

❌ معایب
1️⃣ Single Point Of Failure

اگر IdP از دسترس خارج شود، ورود کاربران مختل می‌شود.
2️⃣ پیچیدگی بیشتر

دیگر با یک پروژه ساده طرف نیستید.OAuth2، OIDC، Token Exchange و Security Flowها وارد سیستم می‌شوند.
3️⃣ نیاز به مانیتورینگ قوی

ءIdentity Provider یکی از حساس‌ترین سرویس‌های سازمان خواهد شد.
4️⃣ چالش Revocation

حذف دسترسی کاربران در معماری JWT توزیع‌شده همیشه ساده نیست.
🚀 Flow اصولی پیاده‌سازی
مرحله 1️⃣
کاربر درخواست Login ارسال می‌کند.
POST /connect/token

مرحله 2️⃣
ءIdentity Provider اعتبار کاربر را بررسی می‌کند.
مرحله 3️⃣
ءAccess Token و Refresh Token صادر می‌شود.
Access Token
Refresh Token

مرحله 4️⃣
ءClient توکن را به سرویس‌ها ارسال می‌کند.
Authorization: Bearer xxx

مرحله 5️⃣
هر سرویس فقط Signature و Claims را اعتبارسنجی می‌کند.
مرحله 6️⃣
در صورت انقضای Access Token، از Refresh Token برای دریافت Token جدید استفاده می‌شود.

📋 نکاتی که حتماً باید رعایت شوند

🔸 ءAccess Token کوتاه‌عمر باشد
(۵ تا ۱۵ دقیقه)
🔸 ءRefresh Token قابلیت Rotation داشته باشد
🔸 ءJWT Secret یا Private Key به صورت امن نگهداری شود
🔸 ءMFA برای حساب‌های حساس فعال شود
🔸 ءRate Limiting روی Endpointهای Login اعمال شود
🔸 ءAudit Log تمام عملیات امنیتی ذخیره شود
🔸 از OAuth2 و OpenID Connect استاندارد استفاده شود

⭐️ برای بهتر شدن Identity Provider چه کارهایی انجام دهیم؟
✅ Key Rotation خودکار
✅ MFA و Passwordless Authentication
✅ Device Tracking
✅ Session Management
✅ Distributed Cache برای Token Validation
✅ Audit Logging و Monitoring
✅ Revocation List برای ابطال Tokenها
✅ High Availability و Replicaهای متعدد
✅ استفاده از OpenIddict یا Keycloak به جای ساخت همه چیز از صفر

💡 مهم‌ترین نکته:
ءIdentity Provider فقط یک سرویس Login نیست.
در سیستم‌های بزرگ، IdP به قلب امنیت کل سازمان تبدیل می‌شود.
هرچه زودتر احراز هویت را از Business Domainها جدا کنید، توسعه سرویس‌ها ساده‌تر و امنیت سیستم قابل مدیریت‌تر خواهد شد.

🔖هشتگ‌ها:
#identityserver #oauth2 #jwt #security #microservices #modularmonolith #aspnetcore
Post #680 285
در یکی از پروژه‌ها یک تصمیم کوچک گرفتیم:
برای افزایش سرعت توسعه، Validationها را از سمت Backend به Frontend منتقل کنیم.
در لحظه همه چیز منطقی بود.UI سریع‌تر بازخورد می‌داد.API ساده‌تر شد.تیم Frontend هم راضی بود.
اما چند ماه بعد، همان تصمیم کوچک خودش را در جای دیگری نشان داد.
چند کلاینت مختلف وجود داشت.موبایل.وب.سرویس‌های داخلی.
و هرکدام بخشی از Validation را به شکل متفاوتی پیاده‌سازی کرده بودند.
نتیجه چه شد؟
یک منطق تجاری در چند جای مختلف تکرار شد.
و هیچ‌کدام ۱۰۰٪ با دیگری هماهنگ نبود.
باگ‌هایی ظاهر می‌شد که در یک کلاینت دیده می‌شد اما در دیگری نه.
و دیباگ کردن آن‌ها به مرور سخت‌تر شد.
نکته جالب این بود که تصمیم اولیه اشتباه نبود.
در آن مقطع حتی بهترین گزینه به نظر می‌رسید.
اما فرض اصلی آن تصمیم این بود:
«یک نقطه مرکزی برای اعمال منطق وجود ندارد.»
و همین فرض بعداً تغییر کرد.
در مهندسی نرم‌افزار، بسیاری از مشکلات از جایی شروع می‌شوند که یک تصمیم کوچک بدون توجه به پیامدهای توزیع‌شده گرفته می‌شود.
چون سیستم‌ها فقط یک کدبیس نیستند.
یک اکوسیستم از کلاینت‌ها، سرویس‌ها و رفتارهای همزمان هستند.
شاید به همین دلیل است که طراحی خوب فقط درباره محل قرار گرفتن منطق نیست.
درباره این است که آن منطق در چند جا باید زندگی کند،
و چطور باید با تغییرات آینده کنار بیاید.
Post #679 392
🚀 یک Junior Developer باید ۵ الگوی معماری را بداند
⚙️ یک Middle Developer باید ۸ الگوی معماری را بداند
🏗 یک Senior Developer باید ۲۰ الگوی معماری را بداند

👉 Junior Developer 👨‍💻

در این مرحله، الگوها به شما کمک می‌کنند ساختار و جریان سیستم را درک کنید. 📚
1️⃣ Layered Architecture
🎨 UI → 🧠 Application → 📦 Domain → 🔧 Infrastructure
تفکیک شفاف مسئولیت‌ها.

2️⃣ Client–Server
🌐 Frontend در مقابل Backend
🔌 APIها به عنوان قرارداد
📨 درخواست‌های Stateless

3️⃣ Monolith
📦 یک واحد قابل استقرار
🛠 ساده برای توسعه، دیباگ و درک
✅ بهترین انتخاب پیش‌فرض

4️⃣ Basic CRUD Architecture
➕ Create
📖 Read
✏️ Update
❌ Delete
پایه و اساس اکثر سیستم‌های کسب‌وکار.

5️⃣ Synchronous Request–Response
🔄 ارتباط ساده مبتنی بر HTTP
🔍 ردیابی و دیباگ آسان

👉 Middle Developer 👨‍💻

درک کنید که سیستم‌ها چگونه ساختاربندی و به یکدیگر متصل می‌شوند. 🏗

1️⃣ Modular Monolith
📦 مرزبندی شفاف درون یک Deployable
🧩 ماژول‌های مستقل بدون پیچیدگی سیستم‌های توزیع‌شده

2️⃣ API Gateway
🚪 نقطه ورود واحد برای کلاینت‌ها
🔀 Routing
🔐 Authentication
⏱️ Rate Limiting
📊 Aggregation
3️⃣ CQRS (Command Query Responsibility Segregation)
✍️ جداسازی مدل‌های خواندن و نوشتن
📈 بهبود Performance و Scalability در صورت نیاز واقعی

4️⃣ Event-Driven Architecture
📨 ارتباط ناهمگام (Asynchronous)
🔗 ءCoupling کمتر بین اجزا

5️⃣ Publish / Subscribe
📢 تولیدکننده‌ها مصرف‌کننده‌ها را نمی‌شناسند
📡 مناسب برای سناریوهای Fan-Out

6️⃣ Point-to-Point Async Integration
📬 صف‌ها بین سرویس‌ها
✅ تحویل قابل اعتماد پیام‌ها

7️⃣ Outbox Pattern
📦 تضمین ارسال پیام همراه با سازگاری پایگاه داده
🚫 جلوگیری از مشکل Dual-Write

8️⃣ Replication Pattern
📖 ءRead Replica برای مقیاس‌پذیری خواندن
🟢 افزایش Availability

👉 Senior Developer 👨‍💻

در این سطح، سیستم‌هایی طراحی می‌کنید که در مقیاس بزرگ و تحت بار واقعی دوام بیاورند. 🚀
در اینجا معماری دیگر فقط درباره Patternها نیست؛
بلکه درباره Trade-offها و پیامدهای هر تصمیم است. ⚖️

1️⃣ Saga Pattern
🔄 مدیریت تراکنش‌های توزیع‌شده
🩹 جبران خطا (Compensation) به جای Rollback

2️⃣ Anti-Corruption Layer (ACL)
🛡 محافظت از Domain در برابر سیستم‌های خارجی
🚫 جلوگیری از آلودگی مدل دامنه

3️⃣ Strangler Fig Pattern
🌱 مدرن‌سازی تدریجی
🔄 جایگزینی امن سیستم‌های Legacy

4️⃣ Sidecar Pattern
📦 مدیریت Cross-Cutting Concernها خارج از Business Logic
📈 Observability
🔐 Security
🛡 Resilience
5️⃣ Service Discovery Pattern
📍 کشف پویا محل سرویس‌ها
⚙️ ضروری در مقیاس بزرگ

6️⃣ Sharding Pattern
🗂 تقسیم داده‌ها برای افزایش مقیاس‌پذیری نوشتن
⚠️ پیچیده اما قدرتمند

7️⃣ Replication + Sharding Trade-offs
⚖️ Consistency در برابر Availability
⚡️ Latency در برابر Correctness

8️⃣ چه زمانی نباید از یک Pattern استفاده کرد؟
❌ Microservices خیلی زود
❌ CQRS بدون نیاز واقعی
❌ Eventها بدون Observability

9️⃣ مسیر تکامل سیستم‌ها
📦 Monolith
➡️ Modular Monolith
➡️ Microservices
🚀 تغییرات تدریجی، نه بازنویسی‌های بزرگ
💡 دانستن Patternها شما را Senior نمی‌کند.

ءSenior بودن یعنی بدانید:
✅ چه زمانی از یک Pattern استفاده کنید.
✅ چه زمانی از آن استفاده نکنید.
✅ و هزینه هر تصمیم معماری را قبل از پرداختن آن بشناسید.
Post #678 239

Forwarded from .NET Fun

سال‌ها منتظرش بودیم؛ Union Types بالاخره به C# آمدند، اما...


@DotNetIsFun
Post #677 424
Post #675 318
در یکی از پروژه‌ها، یک توسعه‌دهنده جدید به تیم اضافه شده بود.
چند هفته بعد از شروع کارش، در یکی از جلسات گفت:
«چرا این بخش سیستم اینقدر پیچیده طراحی شده؟»
چند نفر از اعضای قدیمی تیم لبخند زدند.
یکی از آن‌ها گفت:
«چون تو هنوز داستانش رو نمی‌دونی.»
و واقعاً همین‌طور بود.پشت آن طراحی عجیب، چند سال تصمیم‌گیری، محدودیت، شکست، تغییر نیازمندی و تجربه پنهان شده بود.
اتفاق جالبی که بارها در پروژه‌ها دیده‌ام این است که ما معمولاً فقط نتیجه تصمیم‌ها را می‌بینیم.
نه شرایطی که آن تصمیم‌ها در آن گرفته شده‌اند.
برای همین گاهی قضاوت کردن خیلی آسان به نظر می‌رسد.
«من بودم اینطوری طراحی نمی‌کردم.»
«این معماری اشتباهه.»
«این کد باید از اول نوشته بشه.»
اما حقیقت این است که بیشتر سیستم‌ها در شرایط ایده‌آل ساخته نمی‌شوند.
در محدودیت زمان ساخته می‌شوند.
در محدودیت بودجه.
در فشار کسب‌وکار.
در شرایطی که اطلاعات کامل در دسترس نیست.
و شاید یکی از نشانه‌های بلوغ حرفه‌ای این باشد که قبل از قضاوت یک تصمیم، سعی کنیم زمینه شکل‌گیری آن را بفهمیم.
نه برای اینکه از هر تصمیمی دفاع کنیم.
برای اینکه بدانیم طراحی سیستم‌ها را فقط با نگاه کردن به کد نمی‌شود ارزیابی کرد.
باید داستان پشت آن کد را هم فهمید.
چون خیلی وقت‌ها چیزی که امروز اشتباه به نظر می‌رسد،
دیروز بهترین تصمیم ممکن بوده است.
Post #674 294
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →