softwarephilosophy | Unsorted

Telegram-канал softwarephilosophy - Software Philosophy

3509

چکیده‌ای از مفاهیم به روز مهندسی نرم افزار برای مهندسین نرم‌افزار. معماری نوین نرم‌افزار، تکنولوژی‌های برنامه نویسی جدید

Subscribe to a channel

Software Philosophy

هوش مصنوعی، آماده‌ی آزمون؟ با skUnit بررسی‌اش کن!

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

🎬 داستان از کجا شروع شد؟
در دنیای دات‌نت، تست‌نویسی همیشه بخشی جدی و خشک بوده. اما وقتی پای هوش مصنوعی وسط می‌آیدد، دیگر نمی‌توانید فقط بگویید "این تابع درست کار کرد یا نه؟" باید بپرسید:
❓ آیا مدل واقعاً فهمید کاربر چه گفت؟
❓ آیا جوابش منطقی بود؟
❓ آیا توانست با ظرافت تابعی خاص را صدا بزند؟

حساسیت جایی بالاتر می‌رود که وقتی تغییری ایجاد می‌کنید و عمرا به سادگی بفهمدی تمام تغییرات قبلی درست کار می‌کند یا نه!

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


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

🔗 پیشنهاد می‌کنم سری به گیت‌هاب skUnit بزنین.
___________

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#نگار_قاسمی (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

________

Читать полностью…

Software Philosophy

مهاجرت از تایپ‌اسکریپت (۲.۵ میلیون خط کد) به سی‌شارپ

در بلاگ زیر، CTO شرکت Motion توضیح می‌دهد که چرا تصمیم گرفته‌اند کدهای خود را از #typescript به #csharp ببرند...
دلایلی که آورده بسیار قابل توجه هستند و ارزش خواندن و فکر کردن را دارند. ما هم تقریبا به دلایل مشابهی در چند سال گذشته پروژه‌های جاواسکریپتی خود را به سی‌شارپ منتقل کردیم.
حتی در دو پروژه اخیر که با شرکت‌های کانادایی بوده، اولین کار مهاجرت از کدهای #react به #blazor بوده است.

نظر شما چیه؟

🔗 در این صفحه می‌توانید مطلب کامل را بخوانید.

#مهران_داودی (لینکدین - بلاگ)

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

بازنویسی تاریخی در دنیای دات‌نت با 9 NET.!

تیم NuGet در مایکروسافت موفق شد الگوریتم Restore را در نسخه 9 NET. به‌طور کامل بازنویسی کند؛ نتیجه؟ افزایش سرعت تا ۱۶ برابر!

📉 زمان Restore برای پروژه‌های بزرگ از ۳۲ دقیقه به فقط ۲ دقیقه رسید!

چرا این اتفاق افتاد؟
- الگوریتم قبلی بیش از ۱۰ سال بدون تغییر باقی مانده بود.
- پروژه‌های بزرگ مثل TeamX با کندی شدید مواجه شده بودند.
- ساختار بازگشتی و حافظه‌بر باعث دیباگ سخت و مصرف منابع بالا شده بود.

چه تغییراتی اعمال شد؟
- حذف ساخت گراف کامل و جایگزینی با ساختار تخت و تصمیم‌گیری لحظه‌ای.
- بهینه‌سازی حافظه، کاهش تعداد تکرارها و حذف نودهای تکراری.
- اضافه شدن ویژگی‌هایی مثل transitive pinning و مدیریت بهتر خطاها.

📈 نتیجه نهایی:
- افزایش چشمگیر بهره‌وری توسعه‌دهندگان.
- صرفه‌جویی در منابع زیرساختی.
- آماده‌سازی برای مقیاس‌پذیری در پروژه‌های عظیم.

🔗 توضیحات کامل را در این لینک ببینید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

هوش‌مصنوعی به جز دمو!
تکنولوژی‌های هوش‌مصنوعی معمولا در دموها خیلی جذابن، ولی در استفاده واقعی، «واقعیِ واقعی»، لزوما به اون بامزگی نیستن!
تو این گفتگو قراره در مورد استفاده از هوش‌مصنوعی تو محصولات واقعی صحبت کنم. اینکه ما با چطور از LLM هایی که ذاتا با Hallucination همراه هستن تو محصولات تجاری استفاده می‌کنیم.
کمی هم در مورد معماری نرم‌افزاری و مدل تست‌نویسی semantic که توی @CrystaCode ازشون استفاده می‌کنیم می‌گم و توضیح می‌دم که چطور باعث می‌شه با این روش‌ها محصولات قابل اعتمادتر نوشت.

🔗 در این لینک با ما باشید.

Читать полностью…

Software Philosophy

تفاوت Add و AddAsync در EF Core به همراهی Hi/Lo!

اگه با Entity Framework Core کار می‌کنید، شاید برایتان سوال پیش آمده باشد که بهتر است از Add استفاده کنیم یا AddAsync؟
✅ متد Add فقط موجودیت را به Change Tracker اضافه می‌کند و هیچ ارتباطی با دیتابیس برقرار نمی‌کند تا زمانی که SaveChanges یا SaveChangesAsync صدا زده شود.

✅ متد AddAsync هم همین کار را می‌کند، با این تفاوت که در موارد خاص مثل استفاده از Value Generatorهایی مثل HiLo، ممکن است نیاز باشد در لحظه‌ی اضافه‌کردن، دیتابیس را صدا بزند. برای همین AddAsync به صورت غیرهمزمان طراحی شده است.

در نتیجه اگر از Value Generator خاصی استفاده نمی‌کنید، Add سریع‌تر و سبک‌تر است چون سربار ساخت Task و State Machine را ندارد. اما اگه احتمال می‌دهید EF نیاز داشته باشد در لحظه‌ی اضافه‌کردن با دیتابیس ارتباط بگیرد، AddAsync انتخاب بهتری است.

📌 نکته مهم: تفاوت اصلی در زمان اجرای SaveChanges اتفاق می‌افتد، نه هنگام Add یا AddAsync.

نتیجه‌گیری: در ۹۹٪ موارد، استفاده از Add کفایت می‌کند. AddAsync فقط برای سناریوهای خاص مثل HiLo یا Sequence Generatorها کاربرد دارد.


حال Hi/Lo چیست؟
با Hi/Lo می‌توانیم شناسه‌ها را سمت کلاینت تولید کنیم، بدون اینکه منتظر ذخیره شدن در دیتابیس بمانیم. EF یک مقدار بالا (Hi) از دیتابیس می‌گیرد و با یک آفست پایین (Lo) در حافظه، شناسه‌ها را تولید می‌کند.

🔗 نحوه استفاده از این فیچر را هم می‌توانید iamprovidence/hi-lo-with-entity-framework-05910f662164">اینجا به همراه توضیحات کامل بخوانید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

داینامیک (dynamic)

#csharp_for_beginners

نوع dynamic یک نوع static است اما وقتی متغیری از نوع dynamic باشد کنترل نوع کامپایلر نادیده گرفته می‌شود. یعنی معمولاً مانند نوع object رفتار می‌کند اما کامپایلر فرض می‌کند که هر عملی روی آن امکان‌پذیر است بدون اینکه نوع دقیق آن را بداند.
نتیجه این کار این است که وقتی با dynamic کار می‌کنید لازم نیست بدانید مقدار آن دقیقاً از کجا آمده مثلا از COM API یا یک زبان دینامیک یا از DOM HTML یا بازتاب (reflection).
اگر کد شما نادرست باشد خطا در زمان اجرا ظاهر می‌شود نه زمان کامپایل

مثال:

class ExampleClass
{
public void exampleMethod1(int i) { }
public void exampleMethod2(string str) { }
}

static void Main(string[] args)
{
ExampleClass ec = new ExampleClass()
dynamic dynamic_ec = new ExampleClass()
dynamic_ec.exampleMethod1(10, 4)
dynamic_ec.someMethod("some argument", 7, null)
dynamic_ec.nonexistentMethod()
}


نتیجه عمل روی متغیر dynamic
بیشتر عملیات روی dynamic باز هم نتیجه‌ای از نوع dynamic می‌دهند مثلا

dynamic d = 1
var testSum = d + 3


در اینجا testSum خودش dynamic خواهد بود، اما بعضی از عملیات‌ها نتیجه‌ای غیر dynamic دارند مثل تبدیل به نوع خاص یا ساخت شی با آرگومان‌های dynamic.

var testInstance = new ExampleClass(d)


در اینجا نوع testInstance برابر ExampleClass خواهد بود نه dynamic

کاربردها
داینامیک زمانی مفید است که بخواهید دیر-بایندینگ (late binding) داشته باشید یعنی تصمیم‌گیری نوع و فراخوانی متدها یا پراپرتی‌ها در زمان اجرا انجام شود نه کامپایل.
برای Interop یا COM زمانی که با APIهای COM کار می‌کنید dynamic دیگر لازم نیست هر بار casting انجام دهید.
برای زبان‌های دینامیک یا DOM یا reflection وقتی ساختار داده یا API تان در زمان اجرا معلوم می‌شود dynamic انعطاف بیشتری می‌دهد.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

باکسینگ (Boxing) و آنباکسینگ (Unboxing)

#csharp_for_beginners

باکسینگ (Boxing)

باکسینگ Boxing زمانی اتفاق می‌افتد که یک مقدار از نوع‌های مقداری مثل int یا double به یک نوع مرجع مانند object تبدیل شود. در این فرایند یک شیء جدید در حافظهٔ heap ایجاد می‌شود و مقدار داخل آن قرار می‌گیرد. بعد از انجام باکسینگ Boxing، مقدار اولیه و مقدار قرار داده‌شده داخل شیء دو داده‌ی جداگانه خواهند بود و این عملیات به دلیل ایجاد شیء جدید از نظر عملکردی هزینه‌بر است.

نمونه کد:

int i = 123;
object o = i; // جعبه‌سازی
i = 456;
Console.WriteLine(i);
Console.WriteLine(o);


آنباکسینگ (Unboxing)
اما Unboxing تبدیل برعکس Boxing است و زمانی رخ می‌دهد که بخواهیم مقدار موجود در یک شیء از نوع object را دوباره به نوع مقداری اصلی خود تبدیل کنیم. این کار باید به صورت صریح انجام شود، یعنی لازم است نوع مقصد را حتماً با cast مشخص کنیم. در زمان اجرای برنامه بررسی می‌شود که آیا شیء واقعاً حاصل یک عملیات Boxing از همان نوع مقداری مورد انتظار هست یا خیر. اگر بررسی موفق باشد، مقدار ذخیره ‌شده در heap به یک متغیر مقداری کپی می‌شود. اما اگر شیء تهی (null) باشد یا نوع واقعی آن با نوعی که انتظار داریم مطابقت نداشته باشد، برنامه خطاهایی مانند NullReferenceException یا InvalidCastException تولید می‌کند.

نمونه کد:
int i = 123;
object o = i; // جعبه‌سازی

try
{
int j = (int)o; // ازجعبه‌سازی درست
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}


نمونهٔ خطا:
int i = 123;
object o = i;

try
{
short x = (short)o; // خطای InvalidCastException
}
catch (InvalidCastException e)
{
Console.WriteLine("Incorrect unboxing");
}


باکسینگ Boxing و آنباکسینگ Unboxing به دلیل تخصیص حافظه و بررسی نوع در زمان اجرا از نظر عملکردی هزینه‌بر هستند. در بخش‌هایی از برنامه که این عملیات زیاد انجام می‌شود ممکن است باعث کاهش کارایی شوند. برای جلوگیری از این مشکل، استفاده از Genericها می‌تواند بسیار مؤثر باشد زیرا تبدیل‌های غیرضروری را حذف می‌کند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

شیء (Object) در سی‌شارپ

#csharp_for_beginners

در زبان سی‌شارپ، یک شیء نماینده‌ی یک نمونه (instance) از یک نوع است، که این نوع می‌تواند یک کلاس (class) یا یک ساختار (struct) باشد. یک کلاس یا ساختار مانند نقشه‌ای (blueprint) است که مشخص می‌کند نوع، چه داده‌ها و رفتارهایی دارد، و شیء بخشی از حافظه است که مطابق این نقشه ایجاد و پیکربندی می‌شود. برنامه ممکن است چندین شیء از یک کلاس ایجاد کند.

شیء‌ها همچنین می‌توانند در متغیرها، آرایه‌ها یا مجموعه‌ها ذخیره شوند. کد مشتری (client code) از این متغیرها برای فراخوانی متدها و دسترسی به خصوصیات عمومی شیء استفاده می‌کند.

نمونه‌های ساختار (Struct) و کلاس (Class)

کلاس‌ها
- کلاس‌ها نوع ارجاعی (reference type) هستند.
- متغیر یک شیء کلاس آدرس حافظه آن شیء در heap مدیریت‌شده را نگه می‌دارد.
- اگر یک متغیر کلاس به متغیر دیگر نسبت داده شود، هر دو متغیر به همان شیء اشاره می‌کنند.
- نمونه‌های کلاس معمولاً با عملگر new ایجاد می‌شوند.

مثال:

Person person1 = new Person("Leopold", 6);
Person person2 = person1;
person2.Name = "Molly";
// حالا person1.Name هم "Molly" است، زیرا هر دو به یک شیء اشاره دارند


استراکت‌ها
- استراکت‌ها نوع مقداری (value type) هستند.
- متغیر یک struct، یک کپی کامل از شیء را نگه می‌دارد.
- نمونه‌های struct می‌توانند با new ایجاد شوند، اما الزامی نیست.

مثال:
Person p1 = new Person("Alex", 9);
Person p2 = p1;
p2.Name = "Spencer";
// p1 تغییر نکرده است، زیرا p2 کپی مستقل است


نکات مهم حافظه
- حافظه‌ی کلاس‌ها در managed heap ذخیره می‌شود و توسط garbage collector بازیابی می‌شود.
- حافظه‌ی structها معمولاً در stack ذخیره می‌شود و هنگام خروج از محدوده از بین می‌رود.
- این تفاوت دلیل رفتار متفاوت در کپی و مقایسه بین کلاس و struct است.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

اجرای ویندوز داخل داکر!

اگر با داکر (Docker) کار می‌کنید، پروژه Dockur/Windows یک ابزار فوق‌العاده برایتان خواهد بود. این پروژه متن‌باز به شما اجازه می‌دهد نسخه‌های مختلف ویندوز را داخل یک کانتینر داکر اجرا کنید، بدون اینکه نیاز به ماشین مجازی یا نصب‌های پیچیده داشته باشید.

ویژگی‌های برجسته:
- نصب خودکار ویندوز با انتخاب نسخه دلخواه (از XP تا Windows 11 و حتی Windows Server 2025)
- پشتیبانی از زبان‌های مختلف از جمله فارسی
- امکان اتصال از طریق مرورگر یا Remote Desktop
- قابلیت تنظیم مقدار RAM، CPU، اندازه دیسک و حتی عبور USB و دیسک‌های فیزیکی
- مناسب برای توسعه‌دهندگان، تست‌کنندگان نرم‌افزار و علاقه‌مندان به مجازی‌سازی

🌍 این پروژه در GitHub بیش از ۴۵ هزار ستاره گرفته و توسط هزاران نفر استفاده می‌شود. برای استفاده فقط کافی است Docker و KVM روی سیستم شما فعال باشد.

📦 نحوه استفاده:
با یک فایل Docker Compose ساده یا دستور CLI می‌توانید کانتینر را اجرا کرده و از طریق مرورگر به دسکتاپ ویندوز دسترسی پیدا کنید. همه چیز به صورت خودکار نصب می‌شود!

🔗 لینک پروژه در گیت‌هاب:
dockur/windows در GitHub1

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

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

🎯 سرویس پرداخت یکپارچه Stripe

اگر قصد دارید در پروژه‌های خارجی یا بین‌المللی پرداخت آنلاین را پیاده‌سازی کنید، یکی از بهترین گزینه‌ها استفاده از سرویس قدرتمند Stripe است. این سرویس در بسیاری از کشورها و پلتفرم‌های جهانی کاربرد دارد و مستندات جامعی برای توسعه‌دهندگان ارائه کرده است.

در این راهنما که از مستندات رسمی Stripe تهیه شده، مراحل راه‌اندازی محیط توسعه برای زبان سی‌شارپ توضیح داده شده است. این مراحل شامل موارد زیر است:

🔧 نصب Stripe CLI
ابزاری خط فرمان برای تعامل مستقیم با APIهای Stripe بدون نیاز به نوشتن کدهای اضافی.

🧰 نصب Stripe SDK برای سی‌شارپ
کتابخانه‌ای برای ارسال درخواست‌های API از داخل پروژه‌های دات‌نت، بدون نیاز به نوشتن کدهای تکراری.

🚀 استفاده از API
ساخت یک محصول و تعیین قیمت آن با استفاده از SDK، به‌صورت مرحله‌به‌مرحله و قابل اجرا در محیط تست.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

و اینک NET Conf Watch Party! 🎂🍰🥂

دات‌نت‌کانف امسال امروز (سه‌شنبه ۲۰ آبان) ساعت ۷:۳۰ شروع می‌شه. ما قراره تو آنلاین با هم رویداد رو تماشا کنیم. از ساعت ۷ لینک تیمز رو می‌فرستیم که هر کی دوست داشت بیاد.
نیم ساعت اول یکم گپ می‌زنیم و با هم آشنا می‌شیم تا رویداد شروع بشه.

هماهنگی و لینک تیمز تو این گروه انجام می‌شه: @SoftwarePhilosophyGroup

#مهران_داودی (http://ow.ly/GwIl309lFEm)

کانال تلگرام:
@SoftwarePhilosophy

___

Читать полностью…

Software Philosophy

پروپوزال WebMCP، باز هم همکاری مایکروسافت و گوگل!

پیشنهاد می‌کنم حتما این پروپوزال را دنبال کنید، چون تاثیر زیادی در آینده یکپارچگی مرورگرهایی مثل Edge و Chrome با ابزارهای هوش‌مصنوعی خواهد داشت.

هوش مصنوعی دارد نحوه تعامل ما با وب را متحول می‌کند. این بار WebMCP، پیشنهادی از تیم‌های Microsoft و Google، قرار است این تعامل را شفاف‌تر و قابل‌کنترل‌تر کند. با WebMCP، توسعه‌دهندگان می‌توانند مجموعه‌ای از اکشن‌ها (مثل play، pause، add-todo و ...) را به‌صورت MCP Tools مستقیم از طریق API مرورگر در اختیار ایجنت‌های هوش‌مصنوعی قرار دهند.

یعنی به‌جای اینکه AI با حدس و گمان از روی DOM یا اسکرین‌شات‌ها عمل کند، می‌تواند از خود کد اپلیکیشن استفاده کند و دقیقاً همان کاری را انجام دهد که توسعه‌دهنده مشخص کرده است. WebMCP نه ‌تنها دقت و امنیت تعاملات را بالا می‌برد، بلکه نقش توسعه‌دهنده را در عصر عامل‌های هوشمند زیاد می‌کند و عملا قسمتی از کار برنامه‌نویسی‌ وب به غیرساخت صفحات، فراهم کردن WebMCP های مناسب خواهد بود.

🔗 در این صفحه بیشتر بخوانید.

#mcp #llm #ai

#مهران_داودی (لینکدین - بلاگ)

@SoftwarePhilosophy
______

Читать полностью…

Software Philosophy

تجربه کار با Map و پکیج‌های مختلف در Blazor و Angular

تیم ما در سال‌های اخیر زمان زیادی را برای کار کردن با Map توی بیلیزور گذراند و تجربه‌های خوبی به دست آورده‌ایم. انواع مختلف نیازمندی‌های Map را توانستیم با MapBox GL و Wrapper سی‌شارپی‌ای که برایش نوشتیم پیاده سازی کنیم.

اخیرا هم در پروژه دیگری که Angular است از Map استفاده کردیم و چون نیاز خیلی ساده‌ای داشتیم از Leaflet استفاده کردیم.

🔗 در این پست لینکدین بیشتر در مورد این تجربه صحبت کردم و توضیح دادم که دلیل استفاده از هر کدام چه بوده است. خوشحال می‌شوم اگه تجربه کار در این زمینه را دارید با ما به اشتراک بگذارید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

ساختارها در سی‌شارپ

#csharp_for_beginners

ساختار یا struct نوعی value type در زبان سی‌شارپ است که برای نگهداری داده‌ها و رفتار مرتبط با آن‌ها استفاده می‌شود.
وقتی متغیری از نوع struct ساخته می‌شود، داده‌ها مستقیماً درون آن متغیر ذخیره می‌شوند، نه در یک شیء جداگانه در heap.
در نتیجه، وقتی یک struct به متد ارسال یا از متد بازگردانده می‌شود، کل مقدار آن کپی می‌گردد.
به همین دلیل، struct برای انواع داده‌ای کوچک و مستقل مناسب است.
در مقابل، اگر نوعی داده رفتار پیچیده یا اندازه‌ی بزرگ دارد، معمولاً کلاس گزینه‌ی بهتری است.

مثال ساده از تعریف ساختار


public struct Coords
{
public Coords(double x, double y)
{
X = x
Y = y
}

public double X { get }
public double Y { get }

public override string ToString() => $"({X}, {Y})"
}



یک نوع دیگر به نام readonly struct & readonly

می‌توان یک ساختار را با کلیدواژه readonly تعریف کرد تا تغییرناپذیر باشد.
در یک readonly struct تمام فیلدها باید readonly باشند و تمام ویژگی‌ها (properties) باید فقط getter داشته باشند یا از نوع init باشند. در این حالت ساختار دیگر قابل تغییر نیست و اطمینان حاصل می‌شود که داده‌ها پس از ساخت ثابت باقی می‌مانند.

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

مثال از readonly struct

public readonly struct Coords
{
public Coords(double x, double y)
{
X = x
Y = y
}

public double X { get; init; }
public double Y { get; init; }

public readonly override string ToString() => $"({X}, {Y})"
}


آرایه‌های درون‌خطی (inline arrays)

از نسخه‌ی سی‌شارپ ۱۲ به بعد، امکان تعریف آرایه‌های درون‌خطی در قالب struct فراهم شده است. در این نوع ساختار، فقط یک فیلد داخلی وجود دارد که شامل یک بلوک پیوسته از عناصر داده است. این ویژگی برای موقعیت‌هایی که نیاز به سرعت بالا و دسترسی سریع به حافظه وجود دارد مفید است.

مقداردهی اولیه و مقدار پیش‌فرض struct

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

اگر برای ساختار سازنده‌ی بدون پارامتر تعریف شود، باز هم دستور default آن را فراخوانی نمی‌کند و مقدار پیش‌فرض برای هر فیلد اعمال می‌شود.
از سی‌شارپ ۱۱ به بعد اگر سازنده مقداری برای فیلدها تعیین نکند، کامپایلر به صورت خودکار آن‌ها را با مقدار پیش‌فرض مقداردهی می‌کند.

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



🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

فراتر از چت‌بات‌ها، نزدیک‌تر به انسان

در دنیایی که هوش مصنوعی هر روز مرزهای تازه‌ای را فتح می‌کند، مدل جدید GPT-4o از شرکت OpenAI نقطه‌ی عطفی در مسیر تعامل طبیعی‌تر میان انسان و ماشین به شمار می‌آید. این مدل چندوجهی با توانایی پردازش همزمان متن، تصویر و صوت، تجربه‌ای بی‌سابقه از گفت‌وگوهای هوشمند و واکنش‌های لحظه‌ای را فراهم کرده است. نسخه جدید Realtime API نیز با بهره‌گیری از قدرت GPT-4o، امکان ساخت دستیارهای صوتی با واکنش سریع، صدای طبیعی و درک عمیق‌تر از زبان انسانی را فراهم می‌کند.

ویژگی‌های برجسته gpt-realtime:
- تبدیل گفتار به گفتار (Speech-to-Speech): برخلاف مدل‌های قبلی که گفتار را به متن و بعد دوباره به گفتار تبدیل می‌کردند، این مدل مستقیماً گفتار تولید می‌کند. این باعث کاهش تأخیر و طبیعی‌تر شدن مکالمه می‌شود.
- درک بهتر دستورها: مدل می‌تواند دستورهای پیچیده را دقیق‌تر دنبال کند، مثل گفتن جملات با لحن خاص یا تکرار دقیق اطلاعات مثل شماره‌ها و حروف.
- توانایی چندزبانه: می‌تواند وسط جمله زبان را عوض کند و حتی نشانه‌های غیرکلامی مثل خنده را تشخیص بدهد.
- صداهای جدید: دو صدای جدید به نام‌های Cedar و Marin معرفی شده‌اند که طبیعی‌ترین کیفیت گفتار را دارند.

قابلیت‌های جدید Realtime API:
- پشتیبانی از تصاویر: حالا می‌توانید عکس یا اسکرین‌شات را همراه با صوت یا متن ارسال کنید تا مدل بتواند درباره آن تصویر صحبت کند.
- تماس تلفنی با SIP: امکان تماس صوتی واقعی از طریق پروتکل SIP فراهم شده است.
- اتصال به سرورهای MCP: برای استفاده از ابزارهای خارجی بدون نیاز به تنظیمات پیچیده.
- قیمت‌گذاری جدید: هزینه‌ها ۲۰٪ کاهش پیدا کرده و کنترل بیشتری روی طول مکالمه‌ها برای کاهش هزینه فراهم شده است.

🔗 برای آشنایی بیشتر این مطلب را مطالعه کنید.

———
⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#نگار_قاسمی (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy
_______

Читать полностью…

Software Philosophy

گزارش از دیتابیس لازم داری؟ فقط حرف بزن!

تصور کنید وارد یک پنل مدیریتی می‌شوید، فقط یک جمله ساده تایپ می‌کنید:
«نمایش مشتریانی که بیش از ۵ خرید داشته‌اند»
و بدون اینکه حتی یک خط SQL بنویسید، جدول دقیق با تمام اطلاعات جلو روی شما ظاهر می‌شود.
نه نیاز به دانش دیتابیس دارید، نه وقت گذاشتن برای نوشتن کوئری‌های پیچیده.
این آینده نیست. این حال حاضر توسعه نرم‌افزار با هوش مصنوعی‌ست.
با ظهور مدل‌های زبانی قدرتمند مثل GPT-4، تعامل با داده‌ها وارد مرحله‌ای جدید شده است. حال می‌توانیم با زبان طبیعی، مثل حرف زدن با یک همکار، از دیتابیس اطلاعات بگیریم.

مرحله اول: دریافت ساختار دیتابیس
برای اینکه GPT-4 بتواند کوئری دقیق تولید کند، ابتدا باید ساختار جدول‌ها و ستون‌ها را بشناسد. با استفاده از EF Core، می‌توان لیستی از جدول‌ها و فیلدها را استخراج کرد و به مدل ارسال کرد.

public async Task<string> GetAllTableSchemas()
{
// دریافت اطلاعات جدول‌ها از دیتابیس
}


مرحله دوم: تبدیل زبان طبیعی به SQL
در این مرحله، جمله‌ای مانند "نمایش مشتریانی که بیش از ۵ خرید داشته‌اند" به GPT-4 ارسال می‌شود. مدل با توجه به ساختار دیتابیس، کوئری SQL مناسب تولید می‌کند.
public async Task<string> GenerateSQLQuery(string userPrompt)
{
var prompt = $"Given the following database schema: {schema}, write a SELECT SQL query for: {userPrompt}";
var response = await openAiClient.GetCompletionAsync(prompt);
return response.Text;
}


مرحله سوم: اجرای کوئری و نمایش نتیجه
کوئری تولیدشده روی دیتابیس اجرا می‌شود و نتیجه به کاربر نمایش داده می‌شود. این بخش می‌تواند به‌صورت جدول، نمودار یا حتی فایل خروجی طراحی شود.
public async Task<DataTable> ExecuteQuery(string sql)
{
using var connection = new NpgsqlConnection(connectionString);
var command = new NpgsqlCommand(sql, connection);
var reader = await command.ExecuteReaderAsync();
// تبدیل نتیجه به DataTable
}



⚠️ نکته‌ای که باید در نظر بگیرید این است که فقط کوئری‌های SELECT مجاز هستند تا از تغییر یا حذف داده‌ها جلوگیری شود.

برای دیدن نمونه عملی این پروژه، مقاله اصلی در DZone را ببینید.

___________

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#نگار_قاسمی (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

________

Читать полностью…

Software Philosophy

دلیگیت (delegate)

#csharp_for_beginners

دلیگیت‌ها (delgate) در زبان سی‌شارپ نوعی داده‌اند که مرجع به یک یا چند متد را نگه می‌دارند. Delegateها شبیه اشاره‌گر تابع هستند اما به‌صورت شیءگرا پیاده‌سازی شده‌اند. این ویژگی باعث می‌شود فقط متدهایی با امضای مشخص بتوانند به یک delegate متصل شوند.

برای تعریف یک delegate از کلمه کلیدی delegate استفاده می‌شود. تعریف delegate مشابه امضای یک متد است و مشخص می‌کند چه نوع متدی می‌تواند به آن نسبت داده شود:

public delegate void Callback(string message);


این delegate می‌تواند به هر متدی متصل شود که یک پارامتر از نوع string دریافت کند و مقدار بازگشتی نداشته باشد.

پس از تعریف delegate، می‌توان یک نمونه از آن ایجاد کرد و یک متد سازگار را به آن نسبت داد.

static void DelegateMethod(string message)
{
Console.WriteLine(message);
}

Callback handler = DelegateMethod;


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

handler("Hello World");


یکی از کاربردهای مهم delegate استفاده از آن به‌عنوان callback است. در این حالت، delegate به‌عنوان پارامتر به یک متد دیگر ارسال می‌شود.

static void MethodWithCallback(int a, int b, Callback callback)
{
callback("Result: " + (a + b));
}


متد بالا بدون اطلاع از جزئیات متد callback، آن را در زمان مناسب اجرا می‌کند.

Delegateها می‌توانند چندین متد را به‌صورت هم‌زمان نگه دارند. به این نوع delegate، multicast delegate گفته می‌شود.

Callback handler = DelegateMethod;
handler += AnotherMethod;


در این حالت، هنگام فراخوانی delegate، هر دو متد اجرا می‌شوند.

Delegateها اشیاء هستند و می‌توان آن‌ها را ذخیره کرد، به متدها ارسال کرد یا در propertyها استفاده کرد. همچنین eventها در C# بر پایه delegate ساخته می‌شوند و از همین سازوکار برای اطلاع‌رسانی استفاده می‌کنند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

سلسله مطالب مرتبط با موضوع MCP ها:

ساخت سرورهای MCP با Azure Functions

مطالب قبلی:

ساخت یک MCP Server‌ ساده با سی‌شارپ
نگاهی‌ کمی فلسفی‌تر به MCP
لایو تکمیلی در مورد MCP و LLM ها

پروتکل MCP (Model Context Protocol) راهی نو برای ارتباط بین مدل‌های هوش مصنوعی و ابزارهای کاربردی فراهم کرده. حالا با استفاده از Azure Functions می‌توانید خیلی راحت سرورهای MCP بسازید و آن‌ها را به صورت ریموت اجرا کنید!

ویژگی‌های جذاب:
- استفاده از ویژگی [McpToolTrigger] برای تبدیل فانکشن‌ها به ابزارهای قابل استفاده توسط LLMها.
- ذخیره و بازیابی داده‌ها از Azure Blob Storage با چند خط کد.
- اتصال مستقیم به VS Code و GitHub Copilot برای تعامل هوشمند با کدها.


فقط کافی است پروژه نمونه را کلون کنید، دستور azd up را اجرا کنید و سرور MCP شما روی Azure بالا می‌آید! بعد می‌توانید با Copilot صحبت کنید و بخواهید کدهای انتخاب‌شده شما را ذخیره کند یا دوباره برایتان بیاورد.

📚‌ آموزش کامل و کد نمونه را می‌توانید در وبلاگ رسمی دات‌نت بخوانید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

کلید اصلی در EF Core: عدد یا GUID؟

وقتی با EF Core کار می‌کنیم، یکی از تصمیم‌های مهم اولیه انتخاب نوع کلید اصلی (Primary Key) است. دو گزینه رایج داریم:
🔹 عدد صحیح (int یا long)
🔹 شناسه یکتا گلوبال (GUID)

هر کدام از این دو گزینه مزایا و معایب خود را دارند:

✅ عدد صحیح (int/long):
- عملکرد بهتر در جستجو و ایندکس‌گذاری
- خوانایی بیشتر برای انسان‌ها
- حجم کمتر (۴ یا ۸ بایت)

❌ اما:
- در سیستم‌های توزیع‌شده ممکن است باعث تداخل شود.
- قابل پیش‌بینی بودن مقادیر می‌تواند امنیت را کاهش دهد.

✅ نوع GUID:
- یکتایی گلوبال، مناسب برای سیستم‌های توزیع‌شده.
- ادغام راحت داده‌ها از منابع مختلف.
- امنیت بیشتر به خاطر غیرقابل پیش‌بینی بودن.
- می‌توانیم سمت کد موقع ایجاد آبجکت جدید دیتابیسی یک Id جدید اضافه کنیم. Guid.NewGuid که پرفورمنسی بهتر است.

❌ اما:
- عملکرد ضعیف‌تر نسبت به int
- حجم بیشتر (۱۶ بایت)
- سخت‌تر برای خواندن و تایپ دستی

🔍 جمع‌بندی:
تصمیم شخصی من با توجه به موضوعاتی که گفته شد این است که از GUID استفاده کنم تا دیگر به ازای هر Add نیازی نباشد که یک بار دیگر سمت دیتابیس بروم و خب فواید دیگری هم برای Guid دارم و آن پرفورمنسی که در مورد int صحبت شد برای من آنچنان Game Changer نبوده است و مزایای int نسبت به مزایای Guid برای من کمتر است

انتخاب شما چی است؟

🔗 توضیحات تکمیلی را engrabdullahabdullah/choosing-the-right-primary-key-in-ef-core-int-vs-guid-64463b57c169">اینجا بخوانید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

تولید اطلاعات نادرست با اعتماد به نفس بالا!

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

تصور کنید از یک مدل زبانی می‌پرسید: «چه کسی اولین بار نظریه نسبیت را مطرح کرد؟» و پاسخ می‌دهد: «ایزاک نیوتن در سال ۱۸۷۹». این پاسخ نه‌تنها اشتباه است (چون نظریه نسبیت متعلق به آلبرت اینشتین است)، بلکه با لحنی قاطع ارائه می‌شود که می‌تواند مخاطب را گمراه کند.

چرا مدل‌ها دچار توهم می‌شوند؟
🔘 هدف آموزشی مدل‌ها: پیش‌بینی واژه‌ی بعدی
- مدل‌های زبانی بر اساس احتمال واژه‌ی بعدی آموزش می‌بینند، نه بر اساس صحت اطلاعات.
- این یعنی مدل‌ها بیشتر «حدس» می‌زنند تا «اطلاع» داشته باشند.
🔘نبود داده‌های منفی یا بازخورد اصلاحی
- در فرآیند آموزش، مدل‌ها معمولاً فقط با داده‌های مثبت تغذیه می‌شوند.
- اشتباهاتشان اصلاح نمی‌شود مگر در مراحل خاصی مثل fine-tuning یا RLHF.

🔘تشویق به تولید پاسخ‌های روان و کامل
- مدل‌ها برای تولید پاسخ‌هایی جذاب و کامل پاداش می‌گیرند، حتی اگر دقیق نباشند.
- ابراز «ندانستن» اغلب امتیاز کمتری دارد.

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

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

🟣 استفاده از داده‌های منفی در آموزش
- آموزش مدل‌ها با نمونه‌هایی از پاسخ‌های اشتباه و اصلاح‌شده، به آن‌ها کمک می‌کند تا بهتر تشخیص دهند چه چیزی نادرست است.

🟣 ارزیابی چندلایه
- علاوه بر دقت زبانی، باید معیارهایی مثل «درستی اطلاعات»، «منبع‌پذیری» و «فروتنی شناختی» نیز سنجیده شوند.

🟣 افزایش شفافیت مدل‌ها
- مدل‌ها باید بتوانند توضیح دهند که چرا یک پاسخ را داده‌اند یا از کجا آن را گرفته‌اند.

🔗 در اینجا می‌توانید بیشتر بخوانید.
___________

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#نگار_قاسمی (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

________

Читать полностью…

Software Philosophy

تغییر مهم در NET 9. برای توسعه‌دهندگان HTTP

در نسخه جدید NET 9.، رفتار پیش‌فرض HttpClientFactory تغییر کرده است و به‌جای استفاده از HttpClientHandler از SocketsHttpHandler به‌عنوان هندلر اصلی استفاده می‌شود (البته در پلتفرم‌هایی که قابلیت پشتیبانی داشته باشند).

🔧 این تغییر باعث می‌شود تا کدهایی که قبلاً هندلر را به HttpClientHandler تبدیل می‌کردند، با خطای InvalidCastException مواجه شوند.

مثلا کد زیر خطایی که گفته شد را خواهد داد:

services.AddHttpClient("test")
.ConfigurePrimaryHttpMessageHandler((h, _) =>
{
((HttpClientHandler)h).UseCookies = false;
});


✅ دلیل این تغییر؟ بهبود مدیریت اتصال‌ها و حل مشکلات مربوط به تغییرات DNS در کلاینت‌های Singleton. اکنون SocketsHttpHandler با ویژگی PooledConnectionLifetime به‌طور پیش‌فرض تنظیم می‌شود تا اتصال‌ها به‌صورت دوره‌ای بازسازی شوند.

🔗 توضیحات تکمیلی را اینجا بخوانید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

ساخت اپلیکیشن‌های هوش مصنوعی با Chroma در NET.

اگر دنبال ارتقای پروژه‌های NET. با قابلیت‌های جستجوی هوشمند هستید، حالا می‌توانید از Chroma استفاده کنید، یک پایگاه داده متن‌باز مخصوص اپ‌های AI!

📌‌ اما Chroma چیست؟
پایگاه داده‌ای برای ذخیره‌سازی embeddingها، جستجوی vector، فیلتر متادیتا، full-text search و بازیابی multi-modal (چند رسانه‌ای). مناسب برای پیاده‌سازی قابلیت‌هایی مثل جستجوی semantic و RAG.

🛠‌ چگونه از Chroma استفاده کنیم؟
با پکیج ChromaDB.Client در سی‌شارپ می‌توانید به راحتی به دیتابیس وصل شوید، مجموعه‌ای بسازید، داده‌ها را اضافه کنید و با vector search، اطلاعات مرتبط را پیدا کنید.

۱. نصب
۲. ساخت یک ChromaClient

using ChromaDB.Client;

var configOptions = new ChromaConfigurationOptions(uri: "http://localhost:8000/api/v1/");
using var httpClient = new HttpClient();
var client = new ChromaClient(configOptions, httpClient);

۳. ساخت کالکشن

var collection = await client.GetOrCreateCollection("movies");

var collectionClient = new ChromaCollectionClient(collection, configOptions, httpClient);

۴. ادامه نمونه کدها به همراه توضیحات رو می‌توانید از این لینک مشاهده کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

آشنایی با دو قابلیت جدید در ویژوال استودیو

اگر با Razor در توسعه وب کار می‌کنید، خبر خوب اینکه دو قابلیت جدید در Visual Studio و VS Code اضافه شده که حسابی کار شما را راحت‌تر می‌کند:

🔹‌ «استخراج کامپوننت» (Extract to Component):
با این قابلیت می‌توانید فقط با چند کلیک، بخش‌هایی از کد HTML را به یک کامپوننت جداگانه تبدیل کنید. دیگر نیازی به کپی‌پیست و ساخت دستی فایل نیست!

🔹‌ «توکنایزر جدید سی‌شارپ» با پشتیبانی از Roslyn:
این به‌روزرسانی باعث می‌شود Razor بهتر بتواند کدهای سی‌شارپ را پردازش کند؛ از جمله raw string literals، رشته‌های verbatim و حتی دستورهای پیش‌پردازنده.

📌 این قابلیت‌ها فعلاً در نسخه‌های جدید Visual Studio و NET 9. فعال هستند و قرار است در NET 10. به‌صورت پیش‌فرض فعال باشند.

🔗 بیشتر بخوانید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

تاپل‌ها در سی‌شارپ

#csharp_for_beginners

در زبان برنامه‌نویسی سی‌شارپ، از نسخه‌های جدید‌تر مفهومی با نام تاپل‌ها معرفی شده است؛ این امکان فراهم می‌کند که چند مقدار مرتبط را به‌صورت کم‌حجم و منسجم در کنار هم نگه‌دارید. به‌طور خاص، این مقاله به نوع داده‌ای به نام «تاپل مقدار» (value-tuple) می‌پردازد که در سند رسمی مایکروسافت تحت عنوان «Tuple types (C# reference)» معرفی شده است.

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


(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");


برابری (Tuple equality)ها چگونه مقایسه می‌شوند

تاپل‌ها از عملگرهای == و != پشتیبانی می‌کنند؛ این مقایسه اعضای متناظر (به ترتیب) را با اپراتور مقایسه انجام می‌دهد. نام فیلدها در مقایسه دخیل نیستند؛ به همین دلیل دو تاپل با نام‌های متفاوت اما همان ترتیب و مقادیر، برابر در نظر گرفته می‌شوند.

مثال صفحه

(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right); // True


نام‌گذاری فیلدهای تاپل (Tuple field names)، جزئیات مهم

نحوهٔ تعیین نام فیلدها
نام فیلدها را می‌توان صریحاً هنگام مقداردهی یا در تعریف نوع تاپل مشخص کرد:

var t = (Sum: 4.5, Count: 3);
Console.WriteLine($"Sum of {t.Count} elements is {t.Sum}.");

یا:

(double Sum, int Count) d = (4.5, 3);


تاپل‌های زبان بر پایهٔ System.ValueTuple هستند؛ یعنی نوع مقدار (value type) و اعضای آن به‌صورت فیلدهای عمومی پیاده‌سازی شده‌اند. نتیجهٔ مستقیم این پیاده‌سازی این است که تاپل‌ها mutable value types هستند، یعنی می‌توان مقادیر فیلدهای‌شان را تغییر داد.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

لینک «با هم کنفرانس دات‌نت رو ببینیم»!!!

https://teams.microsoft.com/l/meetup-join/19%3a46ecfc4157634db68224484eb717f3ed%40thread.tacv2/1762875140672?context=%7b%22Tid%22%3a%2224fbf492-43a9-4a8f-ba7b-6f12fa9b8d87%22%2c%22Oid%22%3a%22aca9b64a-ea78-46f4-a5b4-b3afd7832f63%22%7d

Читать полностью…

Software Philosophy

کلاس لیست (List)

#csharp_for_beginners

کلاس «لیست» یا List در فضای نام System.Collections.Generic قرار دارد و یکی از پرکاربردترین ساختارهای داده در چارچوب ‎.NET است. این کلاس نمایان‌گر مجموعه‌ای از عناصر هم‌نوع (دارای نوع مشخص) است که می‌توان به هر کدام از آن‌ها از طریق شماره‌ی ایندکس دسترسی داشت.
علاوه بر این، کلاس لیست امکاناتی برای افزودن، حذف، جستجو، مرتب‌سازی و مدیریت داده‌ها در اختیار برنامه‌نویس قرار می‌دهد.

پارامتر نوع
لیست از نوع عمومی (Generic) است و دارای پارامتری به نام T می‌باشد.
این پارامتر مشخص می‌کند که نوع داده‌ای که قرار است در لیست نگهداری شود چیست (مثلاً عدد صحیح، رشته، شیء و غیره).

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

ویژگی‌های اصلی لیست
• ظرفیت (Capacity): تعداد کل عناصری که لیست می‌تواند بدون تغییر اندازه در خود جای دهد.
• تعداد (Count): تعداد واقعی عناصری که در حال حاضر در لیست وجود دارند.
• اندیس (Item): اجازه می‌دهد تا با استفاده از شماره‌ی اندیس، به یک عنصر دسترسی پیدا کرده یا مقدار آن را تغییر دهیم.

متدهای مهم در لیست
کلاس لیست دارای ده‌ها متد کاربردی است. در ادامه مهم‌ترین آن‌ها آورده شده است

افزودن (Add): یک عنصر جدید را به انتهای لیست اضافه می‌کند.
افزودن مجموعه‌ای از عناصر (AddRange): چندین عنصر را به انتهای لیست اضافه می‌کند.
فقط‌خواندنی (AsReadOnly): نمایی فقط برای خواندن از لیست ایجاد می‌کند که قابل تغییر نیست.
جستجوی دودویی (BinarySearch): با استفاده از الگوریتم جستجوی دودویی، عنصری را در لیست مرتب‌شده پیدا می‌کند.
پاک‌کردن (Clear): همه‌ی عناصر موجود در لیست را حذف می‌کند.
شامل بودن (Contains): بررسی می‌کند که آیا یک عنصر خاص در لیست وجود دارد یا نه.
کپی کردن (CopyTo): عناصر لیست را در آرایه‌ای دیگر کپی می‌کند.
افزایش ظرفیت (EnsureCapacity): اطمینان حاصل می‌کند که ظرفیت لیست به اندازه‌ی کافی برای اضافه شدن عناصر جدید وجود دارد.
وجود شرطی (Exists): بررسی می‌کند آیا عنصری مطابق یک شرط مشخص در لیست وجود دارد یا نه.
یافتن اولین مورد (Find): اولین عنصری که با شرط داده‌شده مطابقت دارد را برمی‌گرداند.
یافتن همه‌ی موارد (FindAll): تمام عناصری که شرط را برآورده می‌کنند بازمی‌گرداند.
یافتن اندیس (FindIndex / FindLastIndex): موقعیت اولین یا آخرین عنصر مطابق شرط را برمی‌گرداند.
برای هر عنصر (ForEach): عملی را روی تمام عناصر اجرا می‌کند.
دریافت بازه (GetRange): بخش مشخصی از لیست را به‌صورت یک لیست جدید برمی‌گرداند.
درج (Insert / InsertRange): عنصری یا مجموعه‌ای از عناصر را در موقعیت مشخصی از لیست قرار می‌دهد.
حذف (Remove): اولین وقوع یک عنصر مشخص را حذف می‌کند.
حذف شرطی (RemoveAll): همه‌ی عناصری که شرط خاصی را برآورده می‌کنند حذف می‌کند.
حذف بر اساس اندیس (RemoveAt / RemoveRange): عنصری در یک موقعیت یا بازه‌ای از عناصر را حذف می‌کند.
معکوس‌کردن (Reverse): ترتیب عناصر را برعکس می‌کند، می‌تواند کل لیست یا بخشی از آن باشد.
مرتب‌سازی (Sort): عناصر را به ترتیب صعودی یا بر اساس مقایسه‌کننده‌ی دلخواه مرتب می‌کند.
تبدیل به آرایه (ToArray): عناصر لیست را در قالب یک آرایه بازمی‌گرداند.
بهینه‌سازی حافظه (TrimExcess): ظرفیت لیست را به تعداد واقعی عناصر کاهش می‌دهد تا از مصرف بی‌مورد حافظه جلوگیری شود.
بررسی شرط برای همه (TrueForAll): بررسی می‌کند آیا همه‌ی عناصر شرط مشخصی را برآورده می‌کنند یا خیر.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

تعریف Enum

#csharp_for_beginners

یک Enum در واقع نوع داده‌ای سفارشی است که مجموعه‌ای از ثابت‌های عددی نام‌گذاری‌شده را در خود نگه می‌دارد. برای مثال:

enum Season
{
Spring,
Summer,
Autumn,
Winter
}


در اینجا، اعضا به ترتیب دارای مقادیر عددی 0، 1، 2 و 3 هستند. نوع پایه‌ی Enum به‌صورت پیش‌فرض int است، اما می‌توان آن را تغییر داد.

تعیین نوع پایه و مقادیر صریح


می‌توان نوع پایه و مقادیر اعضا را به‌صورت دستی مشخص کرد:

enum ErrorCode : ushort
{
None = 0,
Unknown = 1,
ConnectionLost = 100,
OutlierReading = 200
}


در این مثال، نوع پایه ushort است و هر عضو مقدار خاص خود را دارد.

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

تبدیل عددی به Enum مجاز است، اما اگر مقدار عددی به هیچ عضو مشخصی مربوط نباشد، نتیجه ممکن است نامعتبر باشد.

کاربردهای Enum

۱. انتخاب از میان چند مقدار مشخص
یک Enum زمانی مفید است که بخواهیم متغیری یکی از چند مقدار مشخص را بگیرد. مثلاً برای وضعیت سفارش یا فصل سال:

enum OrderStatus
{
Pending,
Processing,
Shipped,
Delivered
}


۲. استفاده به‌صورت ترکیبی (Flags)
گاهی لازم است چند مقدار با هم ترکیب شوند. در این حالت از ویژگی [Flags] استفاده می‌کنیم و مقادیر را به‌صورت توان‌های دو تعریف می‌کنیم:

[Flags]
public enum Days
{
None = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64,
Weekend = Saturday | Sunday
}



جمع‌بندی
ابزار Enum یکی از ابزارهای ساده اما قدرتمند در سی‌شارپ است که به شما کمک می‌کند مجموعه‌ای از مقادیر ثابت را با نام‌های قابل فهم تعریف کنید. این کار باعث افزایش خوانایی، کاهش خطا و بهبود نگهداری کد می‌شود. با رعایت چند قاعده‌ی ساده —مثل داشتن عضو صفر، اعتبارسنجی مقادیر و استفاده‌ی درست از [Flags]— می‌توان Enumهایی ساخت که در پروژه‌های واقعی بسیار کاربردی و ایمن باشند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

🎬 برنامه‌نویسی ویدیو با React!

اگر دنبال راهی خلاقانه برای ساخت ویدیو با کدنویسی هستید، ریپازیتوری Remotion یک انتخاب بی‌نظیر است. این فریم‌ورک قدرتمند به شما اجازه می‌دهد با استفاده از React و تکنولوژی‌های وب مثل CSS، SVG، Canvas و حتی WebGL، ویدیوهای کاستوم بسازید.


برای شروع فقط کافی است دستور زیر را اجرا کنید:

npx create-video@latest


و مابقی ماجرا را در گیت هاب می‌توانید ببینید.

📚 مستندات کامل و API Reference در remotion.dev در دسترس است.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#حامد_حاجیلو (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…

Software Philosophy

ساخت شرط‌های پویا با OR در LINQ to SQL

در بسیاری از پروژه‌های نرم‌افزاری، نیاز داریم تا بر اساس ورودی‌های کاربر، فیلترهایی را به صورت پویا روی داده‌ها اعمال کنیم. یکی از چالش‌های رایج، ترکیب چند شرط با عملگر OR در کوئری‌های LINQ است، به‌ویژه زمانی که از LINQ to SQL استفاده می‌کنیم.

مشکل کجاست؟
در LINQ، وقتی چند .()Where پشت سر هم استفاده می‌کنیم، شرط‌ها به صورت AND ترکیب می‌شوند. اما اگر بخواهیم چند شرط را با OR ترکیب کنیم، نمی‌توانیم به راحتی از .()Or استفاده کنیم، چون <<Expression<Func<T, bool چنین متدی ندارد.

راه‌حل: استفاده از Expression.OrElse
برای ساخت شرط‌های OR، باید از Expression.OrElse استفاده کنیم و پارامترهای مشترک را با دقت جایگزین کنیم. در ادامه، روشی ارائه می‌شود که لیستی از شرط‌ها را دریافت کرده و آن‌ها را با OR ترکیب می‌کند:

public static Expression<Func<T, bool>> OrElse<T>(IEnumerable<Expression<Func<T, bool>>> expressions)
{
var parameter = Expression.Parameter(typeof(T), "x");
Expression? body = null;

foreach (var expr in expressions)
{
var visitor = new ReplaceParameterVisitor(expr.Parameters[0], parameter);
var visitedBody = visitor.Visit(expr.Body);
body = body == null ? visitedBody : Expression.OrElse(body, visitedBody);
}

return body != null
? Expression.Lambda<Func<T, bool>>(body, parameter)
: x => false;
}

class ReplaceParameterVisitor : ExpressionVisitor
{
private readonly ParameterExpression _oldParam;
private readonly ParameterExpression _newParam;

public ReplaceParameterVisitor(ParameterExpression oldParam, ParameterExpression newParam)
{
_oldParam = oldParam;
_newParam = newParam;
}

protected override Expression VisitParameter(ParameterExpression node)
{
return node == _oldParam ? _newParam : base.VisitParameter(node);
}
}


مثال:
فرض کنید می‌خواهید لیستی از افراد را فیلتر کنید که یا سن‌شان بالای ۳۰ باشد، یا نام‌شان با "ن" شروع شود، یا فعال باشند:
var filters = new List<Expression<Func<Person, bool>>>
{
p => p.Age > 30,
p => p.Name.StartsWith("ن"),
p => p.IsActive
};

var combined = OrElse(filters);
var result = db.People.Where(combined);

این کوئری به صورت زیر در SQL ترجمه می‌شود:
WHERE Age > 30 OR Name LIKE 'ن%' OR IsActive = 1


🔗 جهت آشنایی و مطالعه بیشتر اینجا و اینجا را می‌توانید ببینید.
___________

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

#نگار_قاسمی (لینکدین)

کانال تلگرام:
@SoftwarePhilosophy

________

Читать полностью…

Software Philosophy

اپراتورها در سی‌شارپ

#csharp_for_beginners

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

دسته‌های اصلی اپراتورها
۱. اپراتورهای حسابی: برای انجام محاسبات ریاضی مثل جمع، تفریق، ضرب، تقسیم و باقی‌مانده استفاده می‌شوند.
۲. اپراتورهای مقایسه‌ای: برای مقایسه دو مقدار به‌کار می‌روند، مثل بزرگ‌تر، کوچک‌تر یا برابر بودن.
۳. اپراتورهای منطقی بولی: برای ترکیب و معکوس کردن مقادیر درست و نادرست (true/false) استفاده می‌شوند.
۴. اپراتورهای بیت‌به‌بیت و شیفت: برای کار روی بیت‌های داخلی داده‌های عددی کاربرد دارند.
۵. اپراتورهای برابری: برای بررسی مساوی یا نامساوی بودن دو مقدار استفاده می‌شوند.
۶. اپراتورهای انتساب و ترکیبی: برای مقداردهی متغیرها یا ترکیب یک عملیات با انتساب به‌کار می‌روند، مانند += یا -=.
۷. اپراتور شرطی سه‌تایی: یک عبارت شرطی است که بین دو مقدار یکی را انتخاب می‌کند.
۸. اپراتورهای Null: برای بررسی نال بودن و جایگزین کردن مقدار پیش‌فرض استفاده می‌شوند.
۹. اپراتورهای دسترسی به عضو، ایندکس، افزایش یا کاهش و تبدیل نوع: برای دسترسی به اعضای یک شیء، کار با آرایه‌ها، افزایش/کاهش مقدار یا تبدیل نوع داده به نوع دیگر استفاده می‌شوند.

اولویت و جهت اجرای اپراتورها
اپراتورها در سی‌شارپ اولویت‌های مختلفی دارند. اپراتورهایی با اولویت بالاتر زودتر اجرا می‌شوند. اگر چند اپراتور در یک سطح اولویت باشند، ترتیب اجرا توسط جهت ارجاع مشخص می‌شود. اکثر اپراتورهای دوتایی از چپ به راست اجرا می‌شوند، اما برخی مانند انتساب و اپراتور شرطی از راست به چپ اجرا می‌شوند.
به‌عنوان مثال، عبارت a + b - c به‌صورت (a + b) - c محاسبه می‌شود، ولی عبارت x = y = z به شکل x = (y = z) ارزیابی خواهد شد

ترتیب ارزیابی عملوندها
به‌طور پیش‌فرض، عملوندهای یک اپراتور از چپ به راست محاسبه می‌شوند. با این حال، برخی اپراتورها شرطی هستند و ممکن است همه عملوندها محاسبه نشوند.
• در اپراتور && اگر عملوند سمت چپ برابر false باشد، سمت راست دیگر بررسی نمی‌شود.
• در اپراتور || اگر عملوند سمت چپ true باشد، سمت راست اجرا نمی‌شود.
• در اپراتور ?? یا ??=، اگر مقدار سمت چپ نال نباشد، سمت راست محاسبه نمی‌شود.
• در اپراتور شرطی سه‌تایی ?: فقط یکی از شاخه‌ها اجرا می‌شود.
• در عملگرهای شرطی نال مانند ?. یا ?[]، اگر شیء سمت چپ نال باشد، ادامه‌ی عبارت متوقف می‌شود

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______

Читать полностью…
Subscribe to a channel