<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های احسان پژومان</title>
        <link>https://virgool.io/feed/@m_96552081</link>
        <description>دانشجوی مهندسی کامپیوتر و علاقه مند به مهندسی نرم افزار</description>
        <language>fa</language>
        <pubDate>2026-04-15 06:43:48</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/2566669/avatar/kke9gw.jpg?height=120&amp;width=120</url>
            <title>احسان پژومان</title>
            <link>https://virgool.io/@m_96552081</link>
        </image>

                    <item>
                <title>کنفرانس دات نت ۲۰۲۵: از دات نت ۱۰ تا قابلیت‌های جدید C# ۱۴ و EF Core ۱۰</title>
                <link>https://virgool.io/@m_96552081/%DA%A9%D9%86%D9%81%D8%B1%D8%A7%D9%86%D8%B3-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-%DB%B2%DB%B0%DB%B2%DB%B5-%D8%A7%D8%B2-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-%DB%B1%DB%B0-%D8%AA%D8%A7-%D9%82%D8%A7%D8%A8%D9%84%DB%8C%D8%AA-%D9%87%D8%A7%DB%8C-%D8%AC%D8%AF%DB%8C%D8%AF-c-%DB%B1%DB%B4-%D9%88-ef-core-%DB%B1%DB%B0-gpqrr9z8qric</link>
                <description>کنفرانس دات نت 2025 یکی از مهم‌ترین رویدادهای سال برای توسعه‌دهندگان و علاقه‌مندان دنیای مایکروسافت بود؛ رویدادی که مثل همیشه به‌صورت رایگان و کاملاً آنلاین برگزار شد و فرصتی فراهم کرد تا جامعه جهانی توسعه‌دهندگان با آخرین دستاوردها، قابلیت‌ها و مسیر آینده اکوسیستم دات نت آشنا شوند.در این رویداد، نسخه جدید دات نت و Visual Studio،قابلیت‌های تازه C# و ابزارهای مرتبط با هوش مصنوعی، همگی با رویکردی عملی و آینده‌محور معرفی شدند. هدف این مقاله، مرور دقیق و خلاصه‌وار مهم‌ترین نکات، ویژگی‌ها و اتفاقاتی است که در کنفرانس دات نت 2025 مطرح شد؛ نکاتی که می‌توانند مسیر توسعه نرم‌افزار را در سال‌های پیش‌رو تحت تأثیر قرار دهند.تغییرات مهم ASP.NET Core 10اعتبارسنجی در minimal apiاپلیکیشن های minimal api به دلیل سبک و سریع بودن همیشه محبوب برنامه نویسان بوده است اما بزرگترین ایراد آن پشتیبانی نکردن از کتابخانه های دات نت برای اعتبارسنجی بود که کدنویسی را بسیار طولانی و طاقت فرسا میکرد.app.MapPost(&quot;/create&quot;, async (Employee employee) =&gt;
{
    // ❌ تمام اعتبارسنجی داده ها باید به صورت دستی انجام میشد


    var errors = new List&lt;string&gt;();

    if (string.IsNullOrWhiteSpace(employee.FirstName))
        errors.Add(&quot;FirstName is required.&quot;);

    if (string.IsNullOrWhiteSpace(employee.LastName))
        errors.Add(&quot;LastName is required.&quot;);

    if (errors.Any())
        return Results.BadRequest(errors);

    return Results.Ok(employee);
});
اما اکنون از کتابخانه های اعتبارسنجی دات نت مثل DataAnnotations،AbstractValidator و ... میتوانید در اپلیکیشن های minimal api استفاده کنید.public class Employee
{
    [Required]
    [StringLength(50)]
    public string FirstName;

    [Required]
    [StringLength(50)]
    public string LastName;
}builder.Services.AddValidation();app.MapPost(&quot;/create&quot;, (Employee employee) =&gt;
{
    // ✔ No manual checks needed
    // If model is invalid, .NET automatically returns 400 BAD REQUEST
    return Results.Ok(employee);
});پشتیبانی بهبود یافته از رویداد های ارسالی سمت سرور (SSE)رویدادهای ارسالی از سرور (server-side events) یا اختصارا SSE یک روش ارتباطی یک طرفه و بی‌درنگ است که در آن سرور داده ها را از طریق یک اتصال HTTP طولانی‌مدت به سمت کلاینت ارسال میکند.سوال :چرا به SSE نیاز داریم؟به طور نرمال، مرورگر معمولا اینگونه عمل میکند:کاربر : &quot;سرور؛ داده جدیدی دریافت کردی؟&quot;سرور :&quot;نه&quot;کاربر : &quot;سرور؛ داده جدیدی دریافت کردی؟&quot;سرور :&quot;نه&quot;به این فرایند polling گفته میشود؛ polling باعث اتلاف پهنای باند شبکه، CPU و منابع سرور میشود.سرویس SSE با اجازه دادن به سرور برای ارسال خودکار به‌روزرسانی‌ها این مشکل را حل کرده است.دات نت 10 یک api جدید داخلی برای SSE معرفی کرده است:TypedResults.ServerSentEvents(...)که ارسال جریان داده های لحظه‌ای را بسیار آسان تر کرده است.در اینجا به طور مثال یک سرویس فرضی نوشته ایم که قیمت سهام را هر 2 ثانیه بروزرسانی میکند:public record StockPriceEvent(string Id, string Symbol, decimal Price, DateTime Timestamp);

public class StockService
{
    public async IAsyncEnumerable&lt;StockPriceEvent&gt; GenerateStockPrices(
       [EnumeratorCancellation] CancellationToken cancellationToken)
    {
       var symbols = new[] { &quot;MSFT&quot;, &quot;AAPL&quot;, &quot;GOOG&quot;, &quot;AMZN&quot; };

       while (!cancellationToken.IsCancellationRequested)
       {
          var symbol = symbols[Random.Shared.Next(symbols.Length)];
          var price = Math.Round((decimal)(100 + Random.Shared.NextDouble() * 50), 2);
          var id = DateTime.UtcNow.ToString(&quot;o&quot;);

          yield return new StockPriceEvent(id, symbol, price, DateTime.UtcNow);

          await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
       }
    }
}برای ایجاد یک endpoint که جریان داده‌های آپدیت شده را برگرداند از TypedResults.ServerSentEvents استفاده میکنیم :builder.Services.AddSingleton&lt;StockService&gt;();

app.MapGet(&quot;/stocks&quot;, (StockService stockService, CancellationToken ct) =&gt;
{
    return TypedResults.ServerSentEvents(
       stockService.GenerateStockPrices(ct),
       eventType: &quot;stockUpdate&quot;
    );
});اکنون کاربران با اتصال به این endpoint میتوانند به صورت بلادرنگ بروزرسانی قیمت های سهام را دریافت کنند.و نمونه خروجی به صورت زیر میشود:event: stockUpdate
data: {&quot;Id&quot;:&quot;2025-11-25T12:00:01.1234567Z&quot;,&quot;Symbol&quot;:&quot;AAPL&quot;,&quot;Price&quot;:137.45,&quot;Timestamp&quot;:&quot;2025-11-25T12:00:01.1234567Z&quot;}

event: stockUpdate
data: {&quot;Id&quot;:&quot;2025-11-25T12:00:03.1234567Z&quot;,&quot;Symbol&quot;:&quot;GOOG&quot;,&quot;Price&quot;:145.12,&quot;Timestamp&quot;:&quot;2025-11-25T12:00:03.1234567Z&quot;}

event: stockUpdate
data: {&quot;Id&quot;:&quot;2025-11-25T12:00:05.1234567Z&quot;,&quot;Symbol&quot;:&quot;AMZN&quot;,&quot;Price&quot;:121.78,&quot;Timestamp&quot;:&quot;2025-11-25T12:00:05.1234567Z&quot;}

event: stockUpdate
data: {&quot;Id&quot;:&quot;2025-11-25T12:00:07.1234567Z&quot;,&quot;Symbol&quot;:&quot;MSFT&quot;,&quot;Price&quot;:152.33,&quot;Timestamp&quot;:&quot;2025-11-25T12:00:07.1234567Z&quot;}
ویژگی‌های جدید C# 14قابلیت Extension membersExtension member ها نسخه پیشرفته تر و بهبود یافته تر متدهای extension هستند که پیشتر در نسخه سوم سی شارپ معرفی شدند. در سی شارپ 14 شما نه تنها میتوانید توابع را گسترش دهید؛ بلکه میتوانید یک نوع(type) را با متدها، ویژگی‌ها(properties) و اعضای استاتیک گسترش دهید؛ بدون اینکه کد اصلی را تغییر دهید.قبل از سی شارپ 14، فقط میتوانستید متدها را با استفاده از کلاس های static و کلیدواژه this اضافه کنید:public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string value)
    {
        return string.IsNullOrEmpty(value);
    }

    public static string Truncate(this string value, int maxLength)
    {
        if (string.IsNullOrEmpty(value) || value.Length &lt;= maxLength)
            return value;

        return value.Substring(0, maxLength);
    }
}string name = &quot;Hello World&quot;;
if (!name.IsNullOrEmpty())
{
    Console.WriteLine(name.Truncate(5)); // Hello
}
در سینتکس جدید سی شارپ 14، میتوانید از بلوک های extension که خواناتر و سازمان‌یافته تر است استفاده کنید.در این روش یک بار نوع دریافت کننده(receiver) را مشخص کنید سپس چندین عضو را داخل همان بلوک تعریف کنید:public static class StringExtensions
{
    extension(string value)
    {
        public bool IsNullOrEmpty()
        {
            return string.IsNullOrEmpty(value);
        }

        public string Truncate(int maxLength)
        {
            if (string.IsNullOrEmpty(value) || value.Length &lt;= maxLength)
                return value;

            return value.Substring(0, maxLength);
        }
    }
}داخل بلوک، value به نمونه ای که متد روی آن اعمال میشود اشاره دارد.class Program
{
    static void Main()
    {
        string name = &quot;Ehsan&quot;;

        bool isEmpty = name.IsNullOrEmpty();   // extension member
        string shortName = name.Truncate(3);   // extension member

        Console.WriteLine(isEmpty);    // False
        Console.WriteLine(shortName);  // &quot;Ehs&quot;
    }
}در مورد بعد، میتوانید ویژگی‌ها(properties) و اعضای استاتیک نیز داخل بلوک اضافه کنید.properties باعث میشوند کد شما خواناتر و گویاتر باشد.مثلا: برای بررسی اینکه یک مجموعه خالی است یا نه:public static class CollectionExtensions
{
    extension&lt;T&gt;(IEnumerable&lt;T&gt; source)
    {
        public bool IsEmpty =&gt; !source.Any();
        public bool HasItems =&gt; source.Any();
        public int Count =&gt; source.Count();
    }
}IEnumerable&lt;int&gt; numbers = new List&lt;int&gt;();
if (numbers.IsEmpty)
{
    Console.WriteLine(&quot;هیچ موردی یافت نشد.&quot;);
}در اینجا یک کلاس توسعه دهنده برای Product نوشتیم و اعضای استاتیک را داخل بلوک تعریف کردیم:public static class ProductExtensions
{
    extension(Product)
    {
        public static Product CreateDefault() =&gt;
            new Product
            {
                Name = &quot;Unnamed Product&quot;,
                Price = 0,
                StockQuantity = 0,
                Category = &quot;Uncategorized&quot;,
                CreatedDate = DateTime.UtcNow
            };

        public static bool IsValidPrice(decimal price) =&gt;
            price &gt;= 0 &amp;&amp; price &lt;= 1000000;

        public static string DefaultCategory =&gt; &quot;General&quot;;
    }
}var product = Product.CreateDefault();

if (Product.IsValidPrice(999.99m))
{
    product.Price = 999.99m;
}

Console.WriteLine(Product.DefaultCategory); //&quot;General&quot;این اکستنشن ها بدون تغییر کلاس اصلی، قابلیت های جدیدی به ما میدهند.و در مورد آخر، داخل بلوک میتوانید با تعریف فیلد private از آن برای کش کردن محاسبات سنگین استفاده کنید:public static class CollectionExtensions
{
    extension&lt;T&gt;(IEnumerable&lt;T&gt; source)
    {
        private List&lt;T&gt;? _materializedList;

        public List&lt;T&gt; MaterializedList =&gt; _materializedList ??= source.ToList();
        public bool IsEmpty =&gt; MaterializedList.Count == 0;
        public T FirstItem =&gt; MaterializedList[0];
    }
}تابع source.ToList صرفا یک بار اجرا میشود و مقدار آن در materializedList_ کش میشود. این کار سبب میشود زمان اجرای توابعی مثل IsEmpty و FirstItem به طرز چشمگیری کاهش پیدا کند.بهبود عملگرهای کنترلی Nullدر نسخه جدید عملگرهای کنترلی Null (?. یا [ ]?) اکنون میتوانند در سمت چپ یک assignment استفاده شوند.این یعنی می‌توانیم به یک property، field یا indexer (اگر شیء null نباشد) مقدار بدهیم ، بدون اینکه نیاز باشد شرط جداگانه برای چک کردن null بنویسیم.در نسخه های پیشین، باید همیشه null بودن شیء را چک می‌کردید:if (user is not null)
{
    user.Profile = LoadProfile();
}در سینتکس نسخه جدید :user?.Profile = LoadProfile();مقدار LoadProfile فقط در صورتی assign میکند که user نال نباشد.اگر user نال باشد هیچ کاری انجام نمیشود.این کار سبب خوانایی بیشتر کد و عدم تکرار کدهای تکراری میشودتغییرات EF Core 10پشتیبانی مستقیم از RightJoin و LeftJoinبا پشتیبانی مستقیم LeftJoin و RightJoin در LINQ، کوئری ها ساده‌تر، تمیزتر و شبیه تر به زبان SQL شده اند.روش قدیمی(برای مثال LeftJoin):var query = students
    .GroupJoin(
        departments, 
        s =&gt; s.DepartmentID, 
        d =&gt; d.ID, 
        (s, dList) =&gt; new { s, dList })
    .SelectMany(
        x =&gt; x.dList.DefaultIfEmpty(), 
        (x, d) =&gt; new 
        { 
            x.s.FirstName, 
            Department = d != null ? d.Name : &quot;[NONE]&quot; 
        });در نسخه جدید، میتوانید مستقیما از LeftJoin استفاده کنید:var query = students.LeftJoin(
    departments,
    student =&gt; student.DepartmentID,
    department =&gt; department.ID,
    (student, department) =&gt; new 
    { 
        student.FirstName,
        student.LastName,
        Department = department?.Name ?? &quot;[NONE]&quot;
    });پشتیبانی کامل از تایپ JSONشاید مهم ترین تغییری که در EF Core 10 ایجاد شد، همین باشد. این ویژگی به توسعه‌دهندگان اجازه می‌دهد تا انواع مدل های پیچیده را مستقیماً به ستون‌های JSON نگاشت کنند، از طریق LINQ به پراپرتی های داخل ستون کوئری بزنند و فیلدهای JSON را به طور کارآمد به‌روزرسانی کنند.اکنون با استفاده از EF Core 10 و SQL Server 2025 میتوانید ستون های تایپ JSON را تعریف کنید. در نسخه های پیشین برای ذخیره دیتاهای JSON باید آن را در ستون هایی با تایپ nvarchar(max) یا بقیه ستون های متنی ذخیره میکردید.public class Blog
{
    public int Id { get; set; }
    public string Title { get; set; }
    public BlogDetails Details { get; set; } // Complex type stored as JSON
}

[Owned]
public class BlogDetails
{
    public int Views { get; set; }
    public string[] Tags { get; set; }
}modelBuilder.Entity&lt;Blog&gt;(b =&gt;
{
    b.OwnsOne(blog =&gt; blog.Details, a =&gt; a.ToJson());
});در نسخه جدید این امکان نیز فراهم شده که به ویژگی های داخل ستون JSON مستقیما کوئری بزنید:var popularBlogs = context.Blogs
    .Where(b =&gt; b.Details.Views &gt; 100)
    .ToList();در مجموع، تغییرات دات نت 10 و سی شارپ 14، کدنویسی را هم ساده‌تر و هم خواناتر کرده است و امکانات جدید EF Core 10 توسعه‌دهندگان را قادر می‌سازد با داده‌های پیچیده راحت‌تر کار کنند. این ویژگی‌ها نه تنها روند توسعه نرم‌افزار را سریع‌تر می‌کنند، بلکه چشم‌انداز روشنی برای آینده برنامه‌نویسی در دنیای دات نت ایجاد می‌کنند.</description>
                <category>احسان پژومان</category>
                <author>احسان پژومان</author>
                <pubDate>Tue, 25 Nov 2025 16:14:47 +0330</pubDate>
            </item>
                    <item>
                <title>برنامه‌نویسی به سبک سامورایی‌: ژاپنی‌ها چگونه پایدارترین نرم‌افزارهای دنیا را می‌سازند؟</title>
                <link>https://virgool.io/codenevis/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%A8%D9%87-%D8%B3%D8%A8%DA%A9-%D8%B3%D8%A7%D9%85%D9%88%D8%B1%D8%A7%DB%8C%DB%8C-%DA%98%D8%A7%D9%BE%D9%86%DB%8C-%D9%87%D8%A7-%DA%86%DA%AF%D9%88%D9%86%D9%87-%D9%BE%D8%A7%DB%8C%D8%AF%D8%A7%D8%B1%D8%AA%D8%B1%DB%8C%D9%86-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1%D9%87%D8%A7%DB%8C-%D8%AF%D9%86%DB%8C%D8%A7-%D8%B1%D8%A7-%D9%85%DB%8C-%D8%B3%D8%A7%D8%B2%D9%86%D8%AF-mgobjfwzzw96</link>
                <description>در دنیای پرسرعت فناوری، جایی که توسعه دهندگان غربی غرق در فریمورک های مختلف و تکنولوژی های جدید شده اند؛ توسعه دهندگان ژاپنی با تکیه بر اصولی ساده و کاربردی توانسته اند برخی از قابل اعتماد ترین و پایدارترین نرم افزارهای دنیا را بسازند.این مقاله نشان میدهد که فلسفه های سنتی ژاپن چگونه به دنیای نرم افزار نیز راه یافته است و نتیجه آن شده: کدهایی که بعد از ۳۰ سال همچنان در حال اجرا هستند.۱ -مونوزوکوری:فلسفه ای که همه چیز را تغییر میدهددر فرهنگ ژاپنی مونوزوکوری «Monozukuri» به معنای هنر ساختن چیزهاست،اما مفهوم آن صرفا به تولید محصولات فیزیکی محدود نمیشود.این فلسفه بر مهارت در کاری خاص،بهبود مستمر و لذت از خلق کردن، متمرکز است.توسعه دهندگان ژاپنی صرفا یک سری کد روی مانیتور تایپ نمیکنند آنها ساخت نرم افزار را به چشم یک هنر نگاه میکنند که با کد میتوانند آن را خلق کنند.هیروشی ناکامورا،از مهندسان ارشد یک شرکت فناوری در ژاپن، در یکی از مصاحبه هایش این طور گفت:«در غرب، هدف برنامه نویسان صرفا ارائه فیچرهای جدید و ارضا کردن نیازهای بازار است اما در ژاپن هدف برنامه نویسان نوشتن کدی است که دهه ها باقی بماند و فیچرها صرفا نقطه شروع پروژه ها هستند.»این طرز تفکر بسیار جالب توجه و عمیق است. آن‌ها به‌جای شعار «سریع حرکت کن و همه‌چیز را بشکن»، رویکرد «آهسته بساز و چیزی برای خراب شدن باقی نگذار» را در پیش گرفته‌اند.۲-کایزن: اصل ۱ % بهتر شدندر زمینه بهبود کسب و کار،کایزن یک فلسفه و روش‌شناسی ژاپنی است که به معنای بهبود مستمر است(کای به معنای تغییر و زن به معنای خوب است).این فلسفه بر ایجاد بهبودهای کوچک، تدریجی و مستمر در فرآیندها، محصولات یا خدمات به منظور افزایش کارایی و کیفیت و بهره وری در طول زمان تأکید دارد.فلسفه ای که برنامه نویسان ژاپنی نیز برای کدنویسی از آن بهره میبرند.به جای تعیین اسپرینت های عظیم برای بازنویسی کامل برنامه، آنها ترجیح میدهند پیشرفت های کوچک و پیوسته ایجاد کنند.یک مثال عملی شاید مفهوم را بهتر برساند:// رویکرد غربی :بیاید برای اسپرینت بعدی کل این ماژول رو بازنویسی کنیم
function processUserData(users) {
  //اضافه کردن 200 خط کد و پیچیده تر کردن منطق ماژول
  return results;
}

//رویکرد ژاپنی:بیاید امروز 1 درصد ماژول فعلی را بهبود دهیم
function processUserData(users) {
  // امروز:اضافه کردن یک تابع کمکی کوچک
  const validUsers = filterValidUsers(users);
  // فردا : اضافه کردن یک تابع کمکی دیگر
  // هفته بعد : بهینه سازی یک مورد خاص
  return processValidUsers(validUsers);
}یک توسعه دهنده ژاپنی برای بهبود کد از کسی اجازه نمیگیرید. برای آنها چیزی به اسم«بدهی فنی» تعریف نشده است.آنها هر روز سعی میکنند از دیروز خود یک پله بالاتر بایستند.۳-توسعه به‌هنگام(Just-In-Time)تیم های نرم افزاری ژاپنی از سیستم تولید تویوتا (از اینجا بیشتر بخوانید) برای تولید نرم افزار بهره زیادی گرفته اند.از مفاهیم اصلی این سیستم توسعه به‌هنگام(Just-In-Time) است.در این سیستم به جای ساخت فیچرهای ساختگی و ذهنی (شاید یه زمانی بعدا بهش نیاز شد)، دقیقا چیزی را که نیاز دارند را پیاده سازی میکنند، نه بیشتر و نه کمتر.// رویکرد غربی:ساخت یک کلاس جنریک با کلی ویژگی از همان ابتدا
class DataProcessor {
  constructor(options = {}) {
    this.enableCaching = options.enableCaching || false;
    this.enableValidation = options.enableValidation || false;
    this.enableLogging = options.enableLogging || false;
    this.maxRetries = options.maxRetries || 3;
    this.timeout = options.timeout || 5000;
    // و 15 خط دیگر برای &quot;در صورت لزوم&quot; شاید بکار آید
  }
}

// رویکرد ژاپنی:دقیقا چیزی رو که برای الان نیاز داری پیاده سازی کن
class DataProcessor {
  process(data) {
    // مسئله امروز را حل میکند
    return this.validateAndTransform(data);
  }
  
  // اضافه کردن کد فقط در صورت نیاز
}۴-جیدوکا : توقف خط تولیددر کارخانه های تویوتا اگر کارگری یک نقص فنی را مشاهده کند میتواند کل خط تولید را متوقف کند. تیم های توسعه دهنده ژاپنی نیز همین اصل را دنبال میکنند: اگر یک چیز اشتباه باشد،باید کل فرایند متوقف شود.خبری از تعویق آن و انتقال باگ از اسپرینت فعلی به اسپرینت بعدی نیست، یا بدون باگ ادامه میدیم یا اصلا ادامه نمیدیم.به عنوان مثال یک تیم توسعه دهنده ژاپنی دو روز از وقت خود را صرف حل کردن یک نقص فنی کرده بود، نقصی که صرفا روی تجربه کاربری ۰.۱ درصد از کاربران اثر گذاشته بود! وقتی از آنها پرسیده شد چرا لاگ ارور را ثبت نمیکنند و به ادامه کار نمیپردازند؟سرپرست تیم گفت:« اگر ما اجازه بدهیم عیبی در سیستم باقی بماند، در واقع نقص ها را عادی سازی کرده ایم و به زودی سیستم پر از نقص میشود.»۵-پذیرش نقصدر فرهنگ ژاپن مفهومی وجود دارد به نام وابی-سابی «Wabi-Sabi»- یعنی یافتن زیبایی در نقص و ناپایداری.توسعه دهندگان ژاپنی به روش های شگفت انگیزی از این مفهوم در کدنویسی استفاده میکنند.آنها به جای تلاش برای نوشتن کد بی نقص سعی میکنند کدی بنویسند که در طول زمان بتواند تکامل پیدا کند.// رویکرد غربی: تلاش برای پوشش تمام نیازهای آینده
class DataValidator {
  validate(data, rules, options, context, metadata) {
    // اضافه کردن کد های بی مورد برای کنترل کردن تمام سناریوهای احتمالی
  }
}

// رویکرد ژاپنی: ساده برای امروز، قابل‌توسعه برای فردا
class DataValidator {
  validate(data) {
    // Handle today&#039;s case well
    if (!data) return false;
    if (!data.email) return false;
    return true;
  }
  
  // با آمدن نیازمندی های جدید،کد توسعه پیدا میکند
}آن‌ها این واقعیت را می‌پذیرند که نیازها به مرور زمان تغییر خواهند کرد، بنابراین به جای تلاش برای پیش‌بینی آینده، برای تغییرات بالقوه برنامه میسازند.نتایج به ما چه میگوید؟نینتندو : کدهای ۳۰ ساله هنوز در حال اجرا هستندنینتندو در سیستم های مدرن خود همچنان از کدهایی که در دهه ۹۰ میلادی نوشته شده اند استفاده میکند.دلیل این کار این نیست که نینتندو نمیخواهد متحمل هزینه های تغییر شود یا برنامه نویسان تنبلی استخدام کرده است.این کدها چنان از ابتدا بادقت بالا و با دوراندیشی نوشته شده اند که نیازی به بازنویسی ندارند.معیارهای کاراییبر اساس یک مطالعه مقایسه‌ای بین تیم‌های نرم‌افزاری ژاپنی و تیم‌های غربی، نتایج زیر به‌دست آمده است:نرم‌افزارهای تولیدشده توسط تیم‌های ژاپنی، ۶۰ درصد خطا (باگ) کمتری در محیط عملیاتی دارند.زمان صرف‌شده برای نگهداری و رفع اشکالات در تیم‌های ژاپنی، به طور میانگین ۴۰ درصد کمتر است.ویژگی‌های جدید (فیچرها) در این تیم‌ها ۲۵ درصد زودتر به کاربران تحویل داده می‌شوند — با اینکه روند کاری آن‌ها از بیرون «آهسته‌تر» به‌نظر می‌رسد.توسعه‌دهندگان ژاپنی، در مقایسه با همتایان غربی خود، ۸۰ درصد رضایت شغلی بالاتری را تجربه می‌کنند.آنچه توسعه‌دهندگان ژاپنی به ما نشان می‌دهند، این است که کیفیت، پایداری و توجه به جزئیات می‌تواند بر سرعت و عجله برتری داشته باشد. شاید وقت آن رسیده که ما هم در فرآیند توسعه نرم‌افزار، از فلسفه‌های شرقی الهام بگیریم.</description>
                <category>احسان پژومان</category>
                <author>احسان پژومان</author>
                <pubDate>Mon, 04 Aug 2025 16:51:25 +0330</pubDate>
            </item>
                    <item>
                <title>لطفا از JWT به جای Token Session استفاده نکنید!</title>
                <link>https://virgool.io/@m_96552081/%D9%84%D8%B7%D9%81%D8%A7-%D8%A7%D8%B2-jwt-%D8%A8%D9%87-%D8%AC%D8%A7%DB%8C-token-session-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D9%86%DA%A9%D9%86%DB%8C%D8%AF-ko2uid4xrme8</link>
                <description>یکی از بخش‌های کلیدی در طراحی هر نرم‌افزاری، نحوه‌ی پیاده‌سازی احراز هویت کاربرانشه.در این مسیر، ابزارهایی مثل JWT و Session Token نقش مهمی دارن و خیلی‌ها ازشون استفاده می‌کنن.اما قبل از اینکه وارد بحث اصلی بشیم، بیاید اول با هم ببینیم اصلاً این دوتا چی هستن و چه تفاوتی با هم دارن؟فرض کنید وارد یک سایت میشید و با نام کاربری و رمز عبور لاگین میکنید.حالا سایت چطور باید توی صفحه های بعدی تشخیص بده که شما همون کاربر لاگین شده هستید؟ اینجاست که پای Token میاد وسط.تعریف Session Token:در این روش، سایت یه توکن تصادفی برای شما تولید میکنه و اون رو روی سرور خودش نگه میداره. توی مرورگر شما هم یه نسخه از اون ذخیره میشه(مثلا توی کوکی). بعد از اون هر بار که درخواستی میفرستید، مرورگر اون توکن رو همراه با درخواست شما ارسال میکنه، و سایت از طریق توکن ارسالی مرورگر تشخیص میده شما کی هستیداما JWT :JWT نوع خاصی از توکن هست که برای انتقال اطلاعات بین مرورگر و سرور به صورت امن استفاده میشه.وقتی کاربر لاگین میکنه سرور یک توکن JWT برای کاربر میسازه که توش اطلاعات شناسایی کاربر هست و اون رو به کاربر میده ،در واقع JWT مثل یک کارت شناسایی دیجیتال هست که تمام مشخصات شما روش نوشته شده و با یک مهر رسمی از طرف سرور تایید شده.کاربر در درخواست های بعدی خود که سمت سرور ارسال میکند JWT به سرور نشان داده میشود و سرور بدون اینکه به آرشیو مراجعه کنه،مطمئن میشه که کاربر شخص مورد نظر هست.تفاوتش با session token چیه:توکن‌های Session معمولاً فقط یه شناسه (ID) هستن و اطلاعات رو سرور نگه می‌داره.JWT خودش شامل اطلاعات کاربر و وضعیت هست و سرور لازم نیست اطلاعاتی ذخیره کنه (به این حالت میگن Stateless).با گذشت زمان JWT وارد جریان اصلی احراز هویت و توسعه وب شدن و کم کم session token ها به دست فراموشی سپرده شدند.اما در ادامه مسیر معلوم شد JWT ها جادویی نیستند و استفاده از اونا به جای session token ها میتونه یه کابوس امنیتی از نرم افزار شما درست کنه.حالا بیایم کمی عمیق تر بشیم:ما زمان احراز هویت دو حالت برایمان رخ میدهد:حالت Stateful Auth(Session Token):سرور اطلاعات توکن را در یک پایگاه داده ذخیره میکندکاربر یک شناسه توکن تصادفی به عنوان کوکی دریافت میکندهردرخواست که کاربر سمت سرور میفرستد، سرور با توجه به کوکی کاربر دنبال شناسه توکن میگردد تا کاربر را پیدا کنداگر کاربر logout کند سرور توکن کاربر را از پایگاه داده حذف میکندبه این حالت stateful میگویند زیرا سرور تا زمان logout اطلاعات session را نگه میدارد.حالت Stateless Auth(JWT):سرور اطلاعات کاربر را در توکن JWT رمزنگاری و امضا میکندهیچ اطلاعاتی راجب session ذخیره نمیشودهر درخواست کاربر توکن JWT را نیز همراه خود دارد سرور فقط امضای توکن را اعتبارسنجی میکند و نیازی به جستجوی اطلاعات در جایی نداردبه این حالت stateless میگویند چون هیچ ذخیره سازی راجب session صورت نمیگیرد.حالا بریم سراغ اصل مطلب،چه مشکلاتی به وجود می آید؟؟؟1-امکان لغو توکن JWT وجود نداردتوکن های JWT مستقله و شامل همه اطلاعات میشه. وقتی یک توکن JWT ساخته میشه تا وقتی تاریخ انقضاش نرسه معتبر باقی میمونه و نمیتونید حذف یا لغوش کنید این یعنی عملی مثل logout که نیاز به لغو توکن داره عملا وجود نداره.حالا فرض کنید توکن شما دزدیده بشه؟! اون شخص می‌تونه تا زمان انقضای توکن داخل سیستم بمونه.شما در Session token به راحتی میتونید با حذف اون توکن از پایگاه داده توکن رو لغو کنید2-JWT ها بسیار پرحجم هستندتوکن های JWT در مقایسه با Session token ها که صرفا شناسه توکن رو ذخیره میکنند بسیار پرحجم تر هستند مخصوصا وقتی بخواهید اطلاعاتی مانند نقش ها ، دسترسی ها ، شناسه سازمان ها و ... را رمزگذاری کنیداگر به هدر authorization امضا رو هم اضافه کنید حجم هردرخواست حدودا 800 بایت خواهد شد.این رو در هزاران درخواست API ضرب کنید میبیند که پهنای باند مصرفی افزایش و نرخ موفقیت حافظه کش(Cache Hit)کاهش پیدا میکند و در نتیجه سرعت کل سیستم افت پیدا میکنه.3- نداشتن گردش توکن (Rotation) و دوره تنفس (Grace Period)وقتی یک توکن دسترسی (Access token) یا توکن رفرش (Refresh token) صادر میشه برای افزایش امنیت بهتره که بعد از مدتی اون توکن رو با یک توکن جدید جایگزین کنیم(مثلا توکن دسترسی هر 15 دقیقه یکبار عوض بشه) به این کار میگن گردش توکن.وقتی توکن رو عوض می‌کنیم، ممکنه چند لحظه طول بکشه تا همه سیستم‌ها متوجه بشن که توکن قبلی دیگه معتبر نیست.دوره تنفس یعنی یک بازه زمانی کوتاه که توکن قدیمی هنوز کمی اعتبار داره تا کاربر یا سیستم مشکلی نداشته باشه و بدون قطعی ادامه بده.توکن‌های JWT وقتی ساخته شدن، دیگه قابل تغییر نیستن.یعنی اگه بخوای توکن رو «عوض» یا «به‌روزرسانی» کنی، باید کلی تنظیمات پیچیده انجام بدی.درسته که توکن‌های رفرش (Refresh Token) برای این کار هستن، اما بیشتر برنامه‌نویس‌ها:درست ازش استفاده نمی‌کنن،هر دو توکن رو توی localStorage ذخیره می‌کنن (که امن نیست)،موارد خاص مثل ورود/خروج همزمان (parallel logout/login) را در نظر نمی‌گیرند.اما توکن‌های session این مشکل رو ندارن:سرور می‌تونه راحت session ID رو عوض کنه،حتی می‌تونه برای مدت کوتاهی هر دو session (قدیم و جدید) رو قبول کنه تا مشکلی پیش نیاد.اما برای JWT باید کلی دردسر بکشی:توکن دسترسی رو مثلاً هر ۱۵ دقیقه عوض کنی،توکن رفرش رو هم هر بار که استفاده می‌کنی دوباره بسازی،یه لیست سیاه درست کنی از توکن‌های باطل‌شده،و بعد هم دعا کنی همه چیز درست کار کنه!گول جذابیت JWT رو نخورید!JWT ابزار قدرتمندیه، اما نه برای هر سناریویی.هیچ تکنولوژی و ابزاری بدون عیب نیست.قبل از استفاده، مزایا و معایبش رو کامل بسنجید و ببینید آیا مناسب پروژه شما هست یا نه.امنیت هیچ‌وقت نباید فدای سادگی بشه.مخصوصاً وقتی صحبت از ورود، خروج و کنترل دسترسی کاربرهاست.پس لطفاً دیگه از JWT به‌جای Session Token استفاده نکنید!</description>
                <category>احسان پژومان</category>
                <author>احسان پژومان</author>
                <pubDate>Fri, 25 Jul 2025 02:18:10 +0330</pubDate>
            </item>
            </channel>
</rss>