✅ تست های شما باید ایزوله باشند
در حالت ایده آل، یک تست باید "کاملا" از سایر تست ها "ایزوله" باشه.
این امر موجب میشه تست ها هیچ تاثیری (side effect) روی هم نداشته باشند و ترتیب اجراشونم به هم بستگی نداشته باشه در نتیجه میتونیم براحتی اون ها رو به صورت موازی (Parallel) اجرا کنیم
این امر در بر نامه های وب مخصوصا از اهمیت بیشتری برخوردار میشه چرا که به دلیل ماهیت برنامه های وب، که درخواست ها به صورت موازی اجرا میشن، موازی اجرا شدن تست ها باعث میشه اطمینان خاطر بیشتری به عملکرد کد ها پیدا کنیم
مثلا فرض کنید برنامه نویسی اشتباها از روشی توی کدش استفاده کرده باشه که side effect داره (مثلا ذخیره Username کاربر جاری تو یه متغیر "static") در این صورت با موازی اجرا کردن تست ها به خطا میخوریم و متوجه ایراد کار میشیم ولی با اجرای ترتیبی (Sequential) خیر
اینکه چطور توابع side-effect free (بدون تاثیر جانبی) و بالا تر از اون pure functions (توابع خالص) ایجاد کنیم از مباحث Functional Programming (به اختصار FP) هست که اکیدا پیشنهاد میکنم اونها رو مطالعه کنید
در حالت ایده آل هیچ تستی نباید به نتیجه تست قبلیش وابستگی داشته باشه یا تاثیری روی تست بعدی بگذاره
از طرفی یه تست زمان بر، انگیزه برنامه نویس برای اجرا تست رو به شدت کم میکنه
اگه 1000 تا تست داشته باشید که هر کدوم 1ثانیه طول میکشه، ترتیبی بودنش 16 دقیقه زمان میبره در صورتی که موازی بودنش (با فرض اینکه pc شما 8 عدد logical processor یا thread واقعی داره) این زمان به 2 دقیقه کاهش پیدا میکنه
پس توصیه میکنم همیشه سعی تون بر این باشه که تست ها کاملا ایزوله باشن و به صورت Parallel اجرا بشن مگر جایی که واقعا راهی وجود نداشته باشه
▪️در این ویدئو نیز Kent Beck (خالق متدولوژی XP و روش TDD) در مورد اهمیت و چرایی این موضوع صحبت میکنه
Tests Should Be Isolated (from each other)
__________________
@DotNetZoom
در حالت ایده آل، یک تست باید "کاملا" از سایر تست ها "ایزوله" باشه.
این امر موجب میشه تست ها هیچ تاثیری (side effect) روی هم نداشته باشند و ترتیب اجراشونم به هم بستگی نداشته باشه در نتیجه میتونیم براحتی اون ها رو به صورت موازی (Parallel) اجرا کنیم
این امر در بر نامه های وب مخصوصا از اهمیت بیشتری برخوردار میشه چرا که به دلیل ماهیت برنامه های وب، که درخواست ها به صورت موازی اجرا میشن، موازی اجرا شدن تست ها باعث میشه اطمینان خاطر بیشتری به عملکرد کد ها پیدا کنیم
مثلا فرض کنید برنامه نویسی اشتباها از روشی توی کدش استفاده کرده باشه که side effect داره (مثلا ذخیره Username کاربر جاری تو یه متغیر "static") در این صورت با موازی اجرا کردن تست ها به خطا میخوریم و متوجه ایراد کار میشیم ولی با اجرای ترتیبی (Sequential) خیر
اینکه چطور توابع side-effect free (بدون تاثیر جانبی) و بالا تر از اون pure functions (توابع خالص) ایجاد کنیم از مباحث Functional Programming (به اختصار FP) هست که اکیدا پیشنهاد میکنم اونها رو مطالعه کنید
در حالت ایده آل هیچ تستی نباید به نتیجه تست قبلیش وابستگی داشته باشه یا تاثیری روی تست بعدی بگذاره
از طرفی یه تست زمان بر، انگیزه برنامه نویس برای اجرا تست رو به شدت کم میکنه
اگه 1000 تا تست داشته باشید که هر کدوم 1ثانیه طول میکشه، ترتیبی بودنش 16 دقیقه زمان میبره در صورتی که موازی بودنش (با فرض اینکه pc شما 8 عدد logical processor یا thread واقعی داره) این زمان به 2 دقیقه کاهش پیدا میکنه
پس توصیه میکنم همیشه سعی تون بر این باشه که تست ها کاملا ایزوله باشن و به صورت Parallel اجرا بشن مگر جایی که واقعا راهی وجود نداشته باشه
▪️در این ویدئو نیز Kent Beck (خالق متدولوژی XP و روش TDD) در مورد اهمیت و چرایی این موضوع صحبت میکنه
Tests Should Be Isolated (from each other)
__________________
@DotNetZoom
YouTube
Test Desiderata 8/12: Tests Should Be Isolated (from each other)
Whether one test passes or not should have no effect on whether another test passes. You can ensure this by either: 1. Only using locally initialized state ...
🌹تبریکی به وسعت تعداد اعضای کانال🌹
امروز یکم فروردین 1400، که دارم این پست رو میذارم دقیقا 5 سال و 2 ماه و 18 روز از تاریخ تاسیس کانال میگذره و تو این سال ها بیش از 1,100 عدد پست، تولید محتوا و منتشر شده توی کانال
تولید محتوا واقعا کار پر زحمتیه از بررسی و انتخاب موضوع گرفته تا جمع آوری لینک های مناسب و ترجمه یا تولید محتوا برای اون پست و...
اگه بخوام مدت زمانی که برای تولید محتوا توی کانال صرف کردم رو بگم حدودا میشه 6 ماه استخدام فول تایم! مسلما این کار از روی علاقه خودم بوده و هیچ چشم داشت یا منت ایی بر روی هیچ عزیزی ندارم و نخواهم داشت. خیلی از شما دوستان هم لطف داشتید به بنده و با نظرات مثبت و نیز حمایت ها تون باعث دلگرمی و خوشحالی بنده شدین
واقعا بزرگترین دلخوشی من از این فعالیت توی این سالها اینه که ببینم مطالب کانال تونسته برای بعضی افراد مفید باشه و کمکشون کنه.
و تنها کاری که از طرف شما باعث دلگرمی و امیدواری من برای ادامه این فعالیت میشه همین نظرات مثبت و حمایت های شماست که پیشاپیش تشکر میکنم بابتش
و اما در این لحظه بسیار خوشحالم و افتخار میکنم که در کنار شما عزیزان (تا این لحظه 3,477 عضو واقعی که انشالا به زودی 4,000 رو هم رد میکنیم) و به لطف همراهی شما عزیزان تونستیم به عنوان «بزرگترین کانال تخصصی دات نت در کشور» شناخته بشیم که از این بابت بسیار خدا رو شاکر هستم و امیدوارم که این کانال برای شما عزیزان هم مفید واقع شده باشه
در اینجا میخوام 3تا تشکر بکنم
1- میخوام اولا از دوستانی که منو در این زمینه یاری کردند تشکر کنم از جمله: زهرا موحدی، علی عبدالملکی، بابک طارمی و آرمین شعیبی نژاد. (شما دوستان هم اگر علاقمند به تولید محتوای داوطلبانه بودین پی وی بنده پیام بدین)
2- دوما از عزیزان دوست و همکاری که ما رو حمایت کردند تشکر کنم از جمله : کانال فلسفه نرم افزار از مهران داوودی - کانال برنامه نویس از مهدی کرامتی و کانال کدهک از حکیم قدس
3- سوما از همه شما هایی که عضو کانال هستین، به بنده لطف دارین و بنده رو توی این سالها همراهی کردین.
و در آخر سال نو رو به تک تک شما اعضای کانال تبریک میگم و امیدوارم سالی توام با سلامتی، شادکامی و موفقیت داشته باشین 🌹
دوست دار شما #محمدجواد_ابراهیمی
____________________
@DotNetZoom
امروز یکم فروردین 1400، که دارم این پست رو میذارم دقیقا 5 سال و 2 ماه و 18 روز از تاریخ تاسیس کانال میگذره و تو این سال ها بیش از 1,100 عدد پست، تولید محتوا و منتشر شده توی کانال
تولید محتوا واقعا کار پر زحمتیه از بررسی و انتخاب موضوع گرفته تا جمع آوری لینک های مناسب و ترجمه یا تولید محتوا برای اون پست و...
اگه بخوام مدت زمانی که برای تولید محتوا توی کانال صرف کردم رو بگم حدودا میشه 6 ماه استخدام فول تایم! مسلما این کار از روی علاقه خودم بوده و هیچ چشم داشت یا منت ایی بر روی هیچ عزیزی ندارم و نخواهم داشت. خیلی از شما دوستان هم لطف داشتید به بنده و با نظرات مثبت و نیز حمایت ها تون باعث دلگرمی و خوشحالی بنده شدین
واقعا بزرگترین دلخوشی من از این فعالیت توی این سالها اینه که ببینم مطالب کانال تونسته برای بعضی افراد مفید باشه و کمکشون کنه.
و تنها کاری که از طرف شما باعث دلگرمی و امیدواری من برای ادامه این فعالیت میشه همین نظرات مثبت و حمایت های شماست که پیشاپیش تشکر میکنم بابتش
و اما در این لحظه بسیار خوشحالم و افتخار میکنم که در کنار شما عزیزان (تا این لحظه 3,477 عضو واقعی که انشالا به زودی 4,000 رو هم رد میکنیم) و به لطف همراهی شما عزیزان تونستیم به عنوان «بزرگترین کانال تخصصی دات نت در کشور» شناخته بشیم که از این بابت بسیار خدا رو شاکر هستم و امیدوارم که این کانال برای شما عزیزان هم مفید واقع شده باشه
در اینجا میخوام 3تا تشکر بکنم
1- میخوام اولا از دوستانی که منو در این زمینه یاری کردند تشکر کنم از جمله: زهرا موحدی، علی عبدالملکی، بابک طارمی و آرمین شعیبی نژاد. (شما دوستان هم اگر علاقمند به تولید محتوای داوطلبانه بودین پی وی بنده پیام بدین)
2- دوما از عزیزان دوست و همکاری که ما رو حمایت کردند تشکر کنم از جمله : کانال فلسفه نرم افزار از مهران داوودی - کانال برنامه نویس از مهدی کرامتی و کانال کدهک از حکیم قدس
3- سوما از همه شما هایی که عضو کانال هستین، به بنده لطف دارین و بنده رو توی این سالها همراهی کردین.
و در آخر سال نو رو به تک تک شما اعضای کانال تبریک میگم و امیدوارم سالی توام با سلامتی، شادکامی و موفقیت داشته باشین 🌹
دوست دار شما #محمدجواد_ابراهیمی
____________________
@DotNetZoom
✅ آموزش Caching با استفاده از Redis در ASP Net Core
در این مقاله به طور اجمالی با caching در Redis و استفاده از آن در ASP Net Core آشنا میشویم. به طور کلی Distributed Caching می تواند در مقیاس بالا به افزایش پرفرمنس کمک کند و یکی از ابزار های بسیار کاربردی آن Redis می باشد
#بابک_طارمی
https://vrgl.ir/h7wi6
______________
@DotNetZoom
در این مقاله به طور اجمالی با caching در Redis و استفاده از آن در ASP Net Core آشنا میشویم. به طور کلی Distributed Caching می تواند در مقیاس بالا به افزایش پرفرمنس کمک کند و یکی از ابزار های بسیار کاربردی آن Redis می باشد
#بابک_طارمی
https://vrgl.ir/h7wi6
______________
@DotNetZoom
ویرگول
آموزش Caching با استفاده از Redis در ASP Net Core
در این مقاله قصد داریم به بررسی دیتابیس Redis و Cache کردن داده در آن به وسیله ASP Net Core بپردازیم
#سری_معرفی_وسایت_های_برتر
✅ معرفی 10 سایت برتر (سری ششم)
در مورد #C و NET Core. و ASP.NET Core
🔸توی این سری پست ها هربار 10 وبسایت برتر که از نظر سطح علمی و کیفیت محتوا، بروز و متنوع بودن بهترین هستند رو معرفی میکنم
اینا منابعی هستند که معمولا خودم دنبالشون میکنم
1️⃣ https://jimmybogard.com/
2️⃣ https://jonhilton.net/
3️⃣ https://rimdev.io/
4️⃣ http://josephwoodward.co.uk/
5️⃣ https://dotnetkicks.com/
6️⃣ https://www.mikesdotnetting.com/
7️⃣ https://blog.jeremylikness.com/
8️⃣ https://www.davideguida.com/
9️⃣ https://tyrrrz.me/blog
🔟 https://swimburger.net/
_____________
@DotNetZoom
✅ معرفی 10 سایت برتر (سری ششم)
در مورد #C و NET Core. و ASP.NET Core
🔸توی این سری پست ها هربار 10 وبسایت برتر که از نظر سطح علمی و کیفیت محتوا، بروز و متنوع بودن بهترین هستند رو معرفی میکنم
اینا منابعی هستند که معمولا خودم دنبالشون میکنم
1️⃣ https://jimmybogard.com/
2️⃣ https://jonhilton.net/
3️⃣ https://rimdev.io/
4️⃣ http://josephwoodward.co.uk/
5️⃣ https://dotnetkicks.com/
6️⃣ https://www.mikesdotnetting.com/
7️⃣ https://blog.jeremylikness.com/
8️⃣ https://www.davideguida.com/
9️⃣ https://tyrrrz.me/blog
🔟 https://swimburger.net/
_____________
@DotNetZoom
✅ مفهوم Expression Tree در دات نت
میشه گفت یکی از advanced ترین قسمت های دات نت، مفهوم Expression Tree و کلاس Expression هست که یه جورایی قلب IQueryable رو هم تشکیل میده
شاید نهایت استفاده افراد، کار با <<Expression<Func برای شرط های predicate بر روی متد Where و یا selector برای متد Select باشه
ولی Expression خیلی بزرگتر از اینهاست
🔸درواقع مفهوم Expression Tree به مجموعه از از node ها در قالب یک ساختار درختی گفته میشه که هر node اون، خود یک Expression هست. اما خود Expression چیه؟
درواقع هر Expression یک operation (عملیات) برنامه نویسی رو بیان میکنه. توسط کلاس Expression در دات نت میتوان برای هر عملیات برنامه نویسی یک expression ساخت.
🔹به عنوان مثال:
- تعریف یک variable (متغیر)، constant یا parameter (پارامتر ورودی متد)
- انتصاب یک مقدار به یک variable یا parameter
- جمع، تفریق، ضرب، تقسیم و... کردن دو مقدار
- تعریف یک شرط (if/else) یا سویچ (switch) منطقی
- تعریف یک حلقه (for یا while)
- بازگرداندن (return کردن) خروجی متد
- فراخوانی یک متد، پاس دادن پارامتر های ورودی و گرفتن مقدار خروجی
- و... اکثر کار هایی که شما توسط کد نویسی میتونین انجام بدین
🔸فرق expression با کد نویسی معمولی برای operation های برنامه نویسی اینه که توسط Expression میتوان یک ساختار (data structure) قابل توصیف برای کد ها ایجاد کرد.
در نتیجه میتوان از روی این ساختار قابل توصیف، کار های متفاوت و خلاقانه ای انجام داد. مثلا میشه از روی ساختار کد هامون Transpilation انجام بدیم و کوئری (مثلا SQL) معادل اون رو تولید کرد.
🔹در واقع هنگامی که شما یک عبارت lambda رو به یکی از متد های linq که ورودی <Expression<Func داره پاس میدین، پشت صحنه به هنگام Compile یک LambdaExpression از روی عبارت lambda شما ساخته میشه و اون هست که به متد شما پاس داده میشه.
چرا؟ چون که ساختار کد شما رو لازم داره تا بتونه از روی اون Transpilation انجام بده و کوئری (مثلا SQL) معادل اون رو تولید کنه. (این مثال رو ببینید)
🔸یا حتی میتوان به کمک Transpilation، از روی یک expression یک عبارت readable (خوانا) جهت توصیف کاری که قراره انجام بده تولید کرد. همانند کاری که کتابخانه ReadableExpressions کرده و توسط افزونه ویژوال استادیو ReadableExpressions.Visualizers این امکان رو میده که به هنگام دیباگ بتونین یک readable view از روی expression هاتون ببینید
🔹کار دیگه ای که توسط Expression میشه انجام داد. تولید کد IL (مخفف Intermediate Language) از روی اون هست. مثلا شما نمیتونین توسط Reflection حتی، یک متد جدید (شامل مجمومه ای از operation ها) ایجاد کنین ولی توسط Expression میتونین به جای اینکه کد شما به هنگام compile تبدیل به IL بشه، اون رو به هنگام run-time (در زمان اجرای برنامه) از روی همون expression (که یک ساختار قابل توصیف از یک تیکه کد هست) به کد IL تبدیل کنین یا اصطلاحات Emit کنین (بیرون بدین)
در نتیجه میتونین به هنگام run-time کد جدید تولید کنین و این همون تکنیکی هست که کتابخانه های Object Mapper از جمله AutoMapper و Mapster و... از اون استفاده میکنن
🔸گفتم Emit، جا داره از Reflection.Emiit هم یادی بکنیم که پایه ای ترین روش برای تولید کد IL در زمان run-time هست و میشه Expression رو به عنوان یک wrapper روی Reflection.Emit محسوب کرد که کار با اون رو ساده تر میکنه. هرچند کار هایی میشه با Reflection.Emit انجام داد که توسط Expression Tree نمیشه انجام داد (و بلعکس) پس اینجا به هیچ عنوان جایگزین هم نیستند بلکه فقط توی تولید کد IL وجه مشترک دارند.
🔰 جمع بندی
قابلیت Expression Tree یک قابلیت پیشرفته هست و نیاز اکثر افراد نمیشه ولی مزایای غیر قابل چشم پوشی ایی رو به ما میده که حرفه ای ها میتونین کار جالبی باهاش بکنن. توسط این قابلیت که یکی از جذاب ترین امکانات دات نت هست میتونین کار های جالبی انجام بدین از جمله:
1️⃣ گردش روی node ها و فهمیدن ساختار کد (MetaProgramming)
2️⃣ ترجمه کد ها به یک زبان دیگر (Transpilation)
3️⃣ تولید کد IL از روی اون (Code Generation)
💎در آخر یکی از بهترین مقالاتی که این مفهوم رو به خوبی به همراه مثال توضیح داده مقاله زیر هست که پیشنهاد میکنم حتما بخونین
https://tyrrrz.me/blog/expression-trees
____________________
@DotNetZoom
میشه گفت یکی از advanced ترین قسمت های دات نت، مفهوم Expression Tree و کلاس Expression هست که یه جورایی قلب IQueryable رو هم تشکیل میده
شاید نهایت استفاده افراد، کار با <<Expression<Func برای شرط های predicate بر روی متد Where و یا selector برای متد Select باشه
ولی Expression خیلی بزرگتر از اینهاست
🔸درواقع مفهوم Expression Tree به مجموعه از از node ها در قالب یک ساختار درختی گفته میشه که هر node اون، خود یک Expression هست. اما خود Expression چیه؟
درواقع هر Expression یک operation (عملیات) برنامه نویسی رو بیان میکنه. توسط کلاس Expression در دات نت میتوان برای هر عملیات برنامه نویسی یک expression ساخت.
🔹به عنوان مثال:
- تعریف یک variable (متغیر)، constant یا parameter (پارامتر ورودی متد)
- انتصاب یک مقدار به یک variable یا parameter
- جمع، تفریق، ضرب، تقسیم و... کردن دو مقدار
- تعریف یک شرط (if/else) یا سویچ (switch) منطقی
- تعریف یک حلقه (for یا while)
- بازگرداندن (return کردن) خروجی متد
- فراخوانی یک متد، پاس دادن پارامتر های ورودی و گرفتن مقدار خروجی
- و... اکثر کار هایی که شما توسط کد نویسی میتونین انجام بدین
🔸فرق expression با کد نویسی معمولی برای operation های برنامه نویسی اینه که توسط Expression میتوان یک ساختار (data structure) قابل توصیف برای کد ها ایجاد کرد.
در نتیجه میتوان از روی این ساختار قابل توصیف، کار های متفاوت و خلاقانه ای انجام داد. مثلا میشه از روی ساختار کد هامون Transpilation انجام بدیم و کوئری (مثلا SQL) معادل اون رو تولید کرد.
🔹در واقع هنگامی که شما یک عبارت lambda رو به یکی از متد های linq که ورودی <Expression<Func داره پاس میدین، پشت صحنه به هنگام Compile یک LambdaExpression از روی عبارت lambda شما ساخته میشه و اون هست که به متد شما پاس داده میشه.
چرا؟ چون که ساختار کد شما رو لازم داره تا بتونه از روی اون Transpilation انجام بده و کوئری (مثلا SQL) معادل اون رو تولید کنه. (این مثال رو ببینید)
🔸یا حتی میتوان به کمک Transpilation، از روی یک expression یک عبارت readable (خوانا) جهت توصیف کاری که قراره انجام بده تولید کرد. همانند کاری که کتابخانه ReadableExpressions کرده و توسط افزونه ویژوال استادیو ReadableExpressions.Visualizers این امکان رو میده که به هنگام دیباگ بتونین یک readable view از روی expression هاتون ببینید
🔹کار دیگه ای که توسط Expression میشه انجام داد. تولید کد IL (مخفف Intermediate Language) از روی اون هست. مثلا شما نمیتونین توسط Reflection حتی، یک متد جدید (شامل مجمومه ای از operation ها) ایجاد کنین ولی توسط Expression میتونین به جای اینکه کد شما به هنگام compile تبدیل به IL بشه، اون رو به هنگام run-time (در زمان اجرای برنامه) از روی همون expression (که یک ساختار قابل توصیف از یک تیکه کد هست) به کد IL تبدیل کنین یا اصطلاحات Emit کنین (بیرون بدین)
در نتیجه میتونین به هنگام run-time کد جدید تولید کنین و این همون تکنیکی هست که کتابخانه های Object Mapper از جمله AutoMapper و Mapster و... از اون استفاده میکنن
🔸گفتم Emit، جا داره از Reflection.Emiit هم یادی بکنیم که پایه ای ترین روش برای تولید کد IL در زمان run-time هست و میشه Expression رو به عنوان یک wrapper روی Reflection.Emit محسوب کرد که کار با اون رو ساده تر میکنه. هرچند کار هایی میشه با Reflection.Emit انجام داد که توسط Expression Tree نمیشه انجام داد (و بلعکس) پس اینجا به هیچ عنوان جایگزین هم نیستند بلکه فقط توی تولید کد IL وجه مشترک دارند.
🔰 جمع بندی
قابلیت Expression Tree یک قابلیت پیشرفته هست و نیاز اکثر افراد نمیشه ولی مزایای غیر قابل چشم پوشی ایی رو به ما میده که حرفه ای ها میتونین کار جالبی باهاش بکنن. توسط این قابلیت که یکی از جذاب ترین امکانات دات نت هست میتونین کار های جالبی انجام بدین از جمله:
1️⃣ گردش روی node ها و فهمیدن ساختار کد (MetaProgramming)
2️⃣ ترجمه کد ها به یک زبان دیگر (Transpilation)
3️⃣ تولید کد IL از روی اون (Code Generation)
💎در آخر یکی از بهترین مقالاتی که این مفهوم رو به خوبی به همراه مثال توضیح داده مقاله زیر هست که پیشنهاد میکنم حتما بخونین
https://tyrrrz.me/blog/expression-trees
____________________
@DotNetZoom
Oleksii Holub
Working with Expression Trees in C# • Oleksii Holub
Expression trees is an obscure, although very interesting feature in .NET. Most people probably think of it as something synonymous with object-relational mapping frameworks, but despite being its most common use case, it's not the only one. There are a…
❇️ معرفی 20 کتاب برتر برای برنامه نویسان (فارغ از نوع تکنولوژی)
اگه اهل کتابخوندن هستین لیست زیر برترین و محبوبترین کتابهای برنامه نویسی هست که برای هر برنامه نویس فارغ از استک و نوع تکنولوژیش مفید هست
1- Clean Architecture
2- Clean Code
3- The Clean Coder
4- The Pragmatic Programmer
5- Patterns of Enterprise Application Architecture
6- Head First Design Patterns
7- Design Patterns: Elements of Reusable Object-Oriented Software
8- Working Effectively with Legacy Code
9- Refactoring: Improving the Design of Existing Code
10- Domain-Driven Design: Tackling Complexity in the Heart of Software
11- Patterns, Principles, and Practices of Domain-Driven Design
12- Domain-Driven Design Distilled
13- Implementing Domain-Driven Design
14- Test Driven Development
15- Growing Object-Oriented Software, Guided by Tests
16- Working Effectively with Unit Tests
17- The Art of Unit Testing
18- BDD in Action
19- Soft Skills
20- Code Complete
🔰من لینک آمازون کتاب ها رو قرار دادم و بهتره که حامی قانون کپی رایت باشیم هرچند اونایی که میخوان رایگان دانلود کنن به هرحال راهشو بلدن
____________________
@DotNetZoom
اگه اهل کتابخوندن هستین لیست زیر برترین و محبوبترین کتابهای برنامه نویسی هست که برای هر برنامه نویس فارغ از استک و نوع تکنولوژیش مفید هست
1- Clean Architecture
2- Clean Code
3- The Clean Coder
4- The Pragmatic Programmer
5- Patterns of Enterprise Application Architecture
6- Head First Design Patterns
7- Design Patterns: Elements of Reusable Object-Oriented Software
8- Working Effectively with Legacy Code
9- Refactoring: Improving the Design of Existing Code
10- Domain-Driven Design: Tackling Complexity in the Heart of Software
11- Patterns, Principles, and Practices of Domain-Driven Design
12- Domain-Driven Design Distilled
13- Implementing Domain-Driven Design
14- Test Driven Development
15- Growing Object-Oriented Software, Guided by Tests
16- Working Effectively with Unit Tests
17- The Art of Unit Testing
18- BDD in Action
19- Soft Skills
20- Code Complete
🔰من لینک آمازون کتاب ها رو قرار دادم و بهتره که حامی قانون کپی رایت باشیم هرچند اونایی که میخوان رایگان دانلود کنن به هرحال راهشو بلدن
____________________
@DotNetZoom
❇️ فرق Task.Run با Task.Factory.StartNew
در این سری پست های #پرسش_پاسخ قصد دارم بعضی از سوالاتی که دوستان میپرسند رو به همراه جواب هاشون برای شما به اشتراک بگذارم
🔸سوال:
فرق Task.Run با Task.Factory.StartNew چیه؟ از کدومشون باید استفاده کنیم؟
🔹پاسخ:
خود Task.Run پشت پرده از Task.Factory.StartNew استفاده میکنه و در واقع یه Wrapper روی اون هست که استفاده ازش رو ساده تر میکنه.
علتش اینه که Task.Factory.StartNew امضا (overload) های متفاوتی داره که کار با اون رو انعطاف پذیر تر میکنه که همین انعطاف پذیری بیشتر باعث شده کار باهاش پیچیده تر باشه. مثلا وجود آپشن های بیشتری از جمله TaskCreationOptions و TaskScheduler که اجازه میده سفارشی سازی بیشتری انجام بدیم.
همچنین با توجه به اینکه خروجی متد StartNew از نوع <Task<T هست، این نوع جنریک T درواقع خروجی همون delegate ایی که بهش پاس میدین. درنتیجه اگر delegate ورودی شما به متد StartNew، خودش از نوع Task باشه، خروجی نهایی متد StartNew میشه یک <Task<Task که در این حالت بایستی توسط متد Unwarp، اون تسک داخلی (inner task) رو بیرون بکشید و با اون کار بکنید
از این رو تیم دات نت به جهت جلوگیری و مخفی کردن این پیچیدگی ها اومده Task.Run رو برای سناریو های پرکاربرد ایجاد کرده که این پیچیدگی ها رو داخل خودش مخفی میکنه
جمع بندی اینکه همیشه از Task.Run به جای Task.Factory.StartNew استفاده کنید مگر اینکه نیاز به سفارشی سازی یا استفاده از حالت های خاص دارید (اون هم با آگاهی کامل) که توضیحش از حوصله این سوال خارجه
جهت اطلاعات بیشتر مطالعه لینک زیر کمکتون میکنه
▪️Task.Run vs Task.Factory.StartNew
🔸حالا که تا اینجای کار اومدید جا داره یه نکته دیگه هم بگم
علاوه بر روش های بالا 2 روش دیگه برای ساخت یک Task وجود داره.
1- نمونه سازی تسک توسط سازنده کلاس Task
2- استفاده از کلاس TaskCompletionSource
این دو روش کمتر عمومی بوده و معمولا نیاز نمیشه از این ها استفاده کنید. روش اول بسیار کم کاربرد هست و use-case های خاصی داره و باید با احتیاط و آگاهی ازش استفاده کنین.
وقتی شما توسط Task.Run یا Task.Factory.StartNew استفاده میکنید، یک تسک برای شما ساخته میشه و بلافاصله Start میشه. درنتیحه Task ایی که به دست شما میرسه از قبل start شده و فراخوانی مجدد متد Start روی اون، باعث وقوع Exception میشه
ولی وقتی توسط سازنده کلاس Task استفاده میکنید میتونین قبل از Start شدنش به اون نمونه ایجاد شده دسترسی پیدا کنین. و سپس باید به صورت دستی متد Start رو فراخوانی کنین تا Task اجرا بشه. هرچند فراخوانی دستی متد Start بدلیل Synchronization ایی که در پشت صحنه اعمال میشه (به دلیل جلوگیری از Start شدن همزمان توسط چندین Thread) دارای سربار هست
کلاس TaskCompletionSource اما مکانیزمش کلا فرق میکنه. این کلاس وظیفه ساخت "و مدیریت" چرخه حیات یک Task رو به عهده داره.
مثلا توسط متد های SetResult و SetException و SetCanceled (و نیز همین متد ها با پشوند TryXXX به جهت مدیریت همزمانی) این امکان رو به شما میده وضعیت تسک رو به یکی از این حالات تغییر بدید:
"کنسل شده" یا "خطا رخ داده" یا "تکمیل شده با موفقیت (به همراه نتیجه خروجی اون)"
از این روش معمولا برای تبدیل کد های قدیمی APM و EAP به TPL (روش جدید تر و توصیه شده مایکروسافت) استفاده میشه و یه use-case های خاصی که باید با احتیاط و آگاهی از استفاده بشه
اطلاعات بیشتر:
▪️Mechanisms for Creating Tasks
▪️The Nature of TaskCompletionSource
▪️The danger of TaskCompletionSource class
___________________
@DotNetZoom
در این سری پست های #پرسش_پاسخ قصد دارم بعضی از سوالاتی که دوستان میپرسند رو به همراه جواب هاشون برای شما به اشتراک بگذارم
🔸سوال:
فرق Task.Run با Task.Factory.StartNew چیه؟ از کدومشون باید استفاده کنیم؟
🔹پاسخ:
خود Task.Run پشت پرده از Task.Factory.StartNew استفاده میکنه و در واقع یه Wrapper روی اون هست که استفاده ازش رو ساده تر میکنه.
علتش اینه که Task.Factory.StartNew امضا (overload) های متفاوتی داره که کار با اون رو انعطاف پذیر تر میکنه که همین انعطاف پذیری بیشتر باعث شده کار باهاش پیچیده تر باشه. مثلا وجود آپشن های بیشتری از جمله TaskCreationOptions و TaskScheduler که اجازه میده سفارشی سازی بیشتری انجام بدیم.
همچنین با توجه به اینکه خروجی متد StartNew از نوع <Task<T هست، این نوع جنریک T درواقع خروجی همون delegate ایی که بهش پاس میدین. درنتیجه اگر delegate ورودی شما به متد StartNew، خودش از نوع Task باشه، خروجی نهایی متد StartNew میشه یک <Task<Task که در این حالت بایستی توسط متد Unwarp، اون تسک داخلی (inner task) رو بیرون بکشید و با اون کار بکنید
از این رو تیم دات نت به جهت جلوگیری و مخفی کردن این پیچیدگی ها اومده Task.Run رو برای سناریو های پرکاربرد ایجاد کرده که این پیچیدگی ها رو داخل خودش مخفی میکنه
جمع بندی اینکه همیشه از Task.Run به جای Task.Factory.StartNew استفاده کنید مگر اینکه نیاز به سفارشی سازی یا استفاده از حالت های خاص دارید (اون هم با آگاهی کامل) که توضیحش از حوصله این سوال خارجه
جهت اطلاعات بیشتر مطالعه لینک زیر کمکتون میکنه
▪️Task.Run vs Task.Factory.StartNew
🔸حالا که تا اینجای کار اومدید جا داره یه نکته دیگه هم بگم
علاوه بر روش های بالا 2 روش دیگه برای ساخت یک Task وجود داره.
1- نمونه سازی تسک توسط سازنده کلاس Task
2- استفاده از کلاس TaskCompletionSource
این دو روش کمتر عمومی بوده و معمولا نیاز نمیشه از این ها استفاده کنید. روش اول بسیار کم کاربرد هست و use-case های خاصی داره و باید با احتیاط و آگاهی ازش استفاده کنین.
وقتی شما توسط Task.Run یا Task.Factory.StartNew استفاده میکنید، یک تسک برای شما ساخته میشه و بلافاصله Start میشه. درنتیحه Task ایی که به دست شما میرسه از قبل start شده و فراخوانی مجدد متد Start روی اون، باعث وقوع Exception میشه
ولی وقتی توسط سازنده کلاس Task استفاده میکنید میتونین قبل از Start شدنش به اون نمونه ایجاد شده دسترسی پیدا کنین. و سپس باید به صورت دستی متد Start رو فراخوانی کنین تا Task اجرا بشه. هرچند فراخوانی دستی متد Start بدلیل Synchronization ایی که در پشت صحنه اعمال میشه (به دلیل جلوگیری از Start شدن همزمان توسط چندین Thread) دارای سربار هست
کلاس TaskCompletionSource اما مکانیزمش کلا فرق میکنه. این کلاس وظیفه ساخت "و مدیریت" چرخه حیات یک Task رو به عهده داره.
مثلا توسط متد های SetResult و SetException و SetCanceled (و نیز همین متد ها با پشوند TryXXX به جهت مدیریت همزمانی) این امکان رو به شما میده وضعیت تسک رو به یکی از این حالات تغییر بدید:
"کنسل شده" یا "خطا رخ داده" یا "تکمیل شده با موفقیت (به همراه نتیجه خروجی اون)"
از این روش معمولا برای تبدیل کد های قدیمی APM و EAP به TPL (روش جدید تر و توصیه شده مایکروسافت) استفاده میشه و یه use-case های خاصی که باید با احتیاط و آگاهی از استفاده بشه
اطلاعات بیشتر:
▪️Mechanisms for Creating Tasks
▪️The Nature of TaskCompletionSource
▪️The danger of TaskCompletionSource class
___________________
@DotNetZoom
Microsoft News
Task.Run vs Task.Factory.StartNew
In .NET 4, Task.Factory.StartNew was the primary method for scheduling a new task. Many overloads provided for a highly configurable mechanism, enabling setting options, passing in arbitrary state, enabling cancellation, and even controlling scheduling behaviors. …
✅ اشتباهات رایج در استفاده از Async/Await + راه حل
زبان سی شارپ برنامه نویسی async را با کلمات کلیدی async/await و Task Parallel Library بسیار ساده کرده است اما نکاتی در آن وجود دارد که در صورت عدم توجه به آنها ممکن است که باعث ایجاد مشکلاتی شود.در این مقاله قصد داریم که به 7 اشتباه رایج در async programming بپردازیم و برای هر کدام راه حل مناسب را ارائه دهیم.
#بابک_طارمی
https://vrgl.ir/PsCmD
___________________
@DotNetZoom
زبان سی شارپ برنامه نویسی async را با کلمات کلیدی async/await و Task Parallel Library بسیار ساده کرده است اما نکاتی در آن وجود دارد که در صورت عدم توجه به آنها ممکن است که باعث ایجاد مشکلاتی شود.در این مقاله قصد داریم که به 7 اشتباه رایج در async programming بپردازیم و برای هر کدام راه حل مناسب را ارائه دهیم.
#بابک_طارمی
https://vrgl.ir/PsCmD
___________________
@DotNetZoom
ویرگول
اشتباهات رایج در استفاده از Async/Await + راه حل
در این مقاله قصد داریم به اشتباه رایج در استفاده از AsyncAwait بپردازیم و راه حل مناسب را برای آن ارائه دهیم
❇️ دیباگ بهتر در Visual Studio با 3 ترفند
بعضی وقتا پیش میاد که خطا تو کد هاتون رخ میده ولی Exception ایی نشون داده نمیشه. یا جزئیات کاملی از علت خطا در Exception رخ داده نشون داده نمیشه و...
در اینجا میخوایم با اعمال 3 تنظیم در Visual Studio، بتونیم خطا ها رو بهتر Debug کنیم
مراحل زیر رو انجام بدید تا به هنگام وقوع Exception، اجرای کد سر همون خطی که exception اصلی رخ داده متوقف بشه و علت رو پیدا کنید و نیز جزئیات بیشتری از خطا ها براتون نمایش داده بشه
1️⃣ از پنجره Exception Settings توی VisualStudio گزینه زیر رو به صورت کامل تیک بزنید
Common Language Runtime Exceptions
این باعث میشه "هر" نوع خطایی رخ بده Exception اش رو ببینیم
2️⃣ وارد تنظیمات VS بشین و از "غیر فعال" بودن گزینه Enable Just My Code اطمینان پیدا کنید
Tools > Options > Debugging > General
این باعث میشه هر خطایی (نه صرفا در کد های شما) حتی در library های دیگه رخ بده Exception اش رو ببینیم (اطلاعات بیشتر)
3️⃣ وارد تنظیمات VS بشین و از "فعال" بودن گزینه Suppress JIT optimization اطمینان پیدا کنید
Tools > Options > Debugging > General
این باعث میشه JIT Optimization انجام نشه و جزئیات و اطلاعات بیشتری از Exception ها نمایان بشن
در نهایت کدتون رو اجرا کنید در این صورت اگر هر Exception ایی رخ بده نمایش داده میشه و بعد میتونین توسط Call Stack سلسله مراتب متد های فراخوانی کننده رو ببینید و متوجه بشید علت اصلی خطا کجاست
🔰نکته:
وقتی تنظیمات بالا رو انجام میدید بعضی وقتا ممکنه Exception هایی که در کد های داخلی خود Framework و کتابخانه های BCL دات نت رخ میده و حتی Exception های "هندل شده" هم الکی نمایش داده بشه. که میتونید اون ها رو رد کنید و در نظر نگیرید یا توی پنجره Exception Settings (ترفند اول) راست کلیک کنین و گزینه "Restore Defaults" رو بزنین
🔰توی لینک زیر میتونین تکنیک های بیشتری رو هم ببینین
7 Debugging Techniques you should know in C# .NET
____________________
@DotNetZoom
بعضی وقتا پیش میاد که خطا تو کد هاتون رخ میده ولی Exception ایی نشون داده نمیشه. یا جزئیات کاملی از علت خطا در Exception رخ داده نشون داده نمیشه و...
در اینجا میخوایم با اعمال 3 تنظیم در Visual Studio، بتونیم خطا ها رو بهتر Debug کنیم
مراحل زیر رو انجام بدید تا به هنگام وقوع Exception، اجرای کد سر همون خطی که exception اصلی رخ داده متوقف بشه و علت رو پیدا کنید و نیز جزئیات بیشتری از خطا ها براتون نمایش داده بشه
1️⃣ از پنجره Exception Settings توی VisualStudio گزینه زیر رو به صورت کامل تیک بزنید
Common Language Runtime Exceptions
این باعث میشه "هر" نوع خطایی رخ بده Exception اش رو ببینیم
2️⃣ وارد تنظیمات VS بشین و از "غیر فعال" بودن گزینه Enable Just My Code اطمینان پیدا کنید
Tools > Options > Debugging > General
این باعث میشه هر خطایی (نه صرفا در کد های شما) حتی در library های دیگه رخ بده Exception اش رو ببینیم (اطلاعات بیشتر)
3️⃣ وارد تنظیمات VS بشین و از "فعال" بودن گزینه Suppress JIT optimization اطمینان پیدا کنید
Tools > Options > Debugging > General
این باعث میشه JIT Optimization انجام نشه و جزئیات و اطلاعات بیشتری از Exception ها نمایان بشن
در نهایت کدتون رو اجرا کنید در این صورت اگر هر Exception ایی رخ بده نمایش داده میشه و بعد میتونین توسط Call Stack سلسله مراتب متد های فراخوانی کننده رو ببینید و متوجه بشید علت اصلی خطا کجاست
🔰نکته:
وقتی تنظیمات بالا رو انجام میدید بعضی وقتا ممکنه Exception هایی که در کد های داخلی خود Framework و کتابخانه های BCL دات نت رخ میده و حتی Exception های "هندل شده" هم الکی نمایش داده بشه. که میتونید اون ها رو رد کنید و در نظر نگیرید یا توی پنجره Exception Settings (ترفند اول) راست کلیک کنین و گزینه "Restore Defaults" رو بزنین
🔰توی لینک زیر میتونین تکنیک های بیشتری رو هم ببینین
7 Debugging Techniques you should know in C# .NET
____________________
@DotNetZoom
Telegram
Attach Files
❇️ تم های RTL زیبا و متنوع برای Bootstrap به صورت رایگان
🔸مشاهده Demo
https://mrjelveh.github.io/bootswatch-rtl/
🔹ریپازیتوری گیتهاب
https://github.com/mrjelveh/bootswatch-rtl
🔰تم های RTL بالا از روی نسخه های LTR اصلی اون ها که در زیر وجود دارند، برگردان شده اند
http://bootswatch.com/
https://github.com/thomaspark/bootswatch
___________________
@DotNetZoom
🔸مشاهده Demo
https://mrjelveh.github.io/bootswatch-rtl/
🔹ریپازیتوری گیتهاب
https://github.com/mrjelveh/bootswatch-rtl
🔰تم های RTL بالا از روی نسخه های LTR اصلی اون ها که در زیر وجود دارند، برگردان شده اند
http://bootswatch.com/
https://github.com/thomaspark/bootswatch
___________________
@DotNetZoom
Forwarded from کدهک
✅ آموزش Cache در Asp.Net Core (قسمت دوم : EasyCaching)
در دنیای امروز برنامه نویسی ، پکیج ها و فریمورک ها نقش بسیار مهمی را ایفا میکنند بطوری که در بسیاری ازین موارد استفاده از این پکیج ها عمل عاقلانه تری نسبت به دوباره نویسی فیچر های مربوطه است.
برای عمل کشینگ در Asp.Net Core نیز پکیج های فوقالعاده ای وجود دارد که در این مقاله به بررسی و استفاده از پکیج EasyCaching، یک پکیج محبوب و کاربردی برای پیاده سازی کش در Asp.Net Core میپردازیم.
همچنین جهت افزایش Performance از کتابخانه EasyCaching.Extensions.EasyCompressor که یک افزونه بر روی EasyCaching هست، استفاده میکنیم .این پکیج اطلاعات را قبل از کش شدن فشرده سازی میکند و حجم اطلاعات را به طور محسوسی کاهش میدهد که میزان فضای اشغالی Ram را کم کرده و همچنین عمل جابجایی اطلاعات را نیز تسریع میبخشد.
#سجاد_کاردل
https://vrgl.ir/SJlkR
پ.ن:
شخصا پیشنهاد میکنم به جای IMemoryCache و IDistributedCache ماکروسافت برای Caching از کتابخانه EasyCaching و در کنارش از EasyCompressor توی پروژه هاتون استفاده کنین (محمدجواد ابراهیمی)
__________________
@DotNetZoom
در دنیای امروز برنامه نویسی ، پکیج ها و فریمورک ها نقش بسیار مهمی را ایفا میکنند بطوری که در بسیاری ازین موارد استفاده از این پکیج ها عمل عاقلانه تری نسبت به دوباره نویسی فیچر های مربوطه است.
برای عمل کشینگ در Asp.Net Core نیز پکیج های فوقالعاده ای وجود دارد که در این مقاله به بررسی و استفاده از پکیج EasyCaching، یک پکیج محبوب و کاربردی برای پیاده سازی کش در Asp.Net Core میپردازیم.
همچنین جهت افزایش Performance از کتابخانه EasyCaching.Extensions.EasyCompressor که یک افزونه بر روی EasyCaching هست، استفاده میکنیم .این پکیج اطلاعات را قبل از کش شدن فشرده سازی میکند و حجم اطلاعات را به طور محسوسی کاهش میدهد که میزان فضای اشغالی Ram را کم کرده و همچنین عمل جابجایی اطلاعات را نیز تسریع میبخشد.
#سجاد_کاردل
https://vrgl.ir/SJlkR
پ.ن:
شخصا پیشنهاد میکنم به جای IMemoryCache و IDistributedCache ماکروسافت برای Caching از کتابخانه EasyCaching و در کنارش از EasyCompressor توی پروژه هاتون استفاده کنین (محمدجواد ابراهیمی)
__________________
@DotNetZoom
ویرگول
آموزش Cache در Asp.Net Core (قسمت دوم : EasyCaching)
در قسمت اول درمورد سیستم Cache دیفالت موجود در AspNet Core و مزیت ها و معایبش گفتیم اگر قسمت اول رو نخواندید پیشنهاد میکنم در همین پروفای…
✅ گنجینه ای ناب از کتاب های مختصر و مفید برنامه نویسی
به معنای واقعی کلمه یه گنجینه ناب هست! سال هاست ازش استفاده میکنم و خیلی راضی ام. بیش از 170 تا کتاب الکترونیکی رایگان داره تو انواع و اقسام موضوعات برنامه نویسی.
کتاباشم خیلی مختصر و مفید هست و اصلا طولانی و خسته کننده نیست، راست کار یه برنامه نویسایی که سرشون شلوغه. یعنی انتظار خیلی deep شدن رو نداشته باشین ولی اگه میخواین تو مدت زمان کمی به یه موضوع تسلط نسبی و یه دید کلی پیدا کنین بهترین گزینه اس.
https://www.syncfusion.com/ebooks/
____________________
@DotNetZoom
به معنای واقعی کلمه یه گنجینه ناب هست! سال هاست ازش استفاده میکنم و خیلی راضی ام. بیش از 170 تا کتاب الکترونیکی رایگان داره تو انواع و اقسام موضوعات برنامه نویسی.
کتاباشم خیلی مختصر و مفید هست و اصلا طولانی و خسته کننده نیست، راست کار یه برنامه نویسایی که سرشون شلوغه. یعنی انتظار خیلی deep شدن رو نداشته باشین ولی اگه میخواین تو مدت زمان کمی به یه موضوع تسلط نسبی و یه دید کلی پیدا کنین بهترین گزینه اس.
https://www.syncfusion.com/ebooks/
____________________
@DotNetZoom
✅ نمایش تعداد کاربران آنلاین در AspNet Core
برای محاسبه تعداد کاربران آنلاین اساسا دو روش وجود داره
1️⃣ روش اول - با استفاده از Cookie
در ASP.NET قدیم داخل کلاس global.asax متد هایی وجود داشت به نام Session_Start و Session_End که به هنگام شروع و پایان "سشن" کاربری، فراخوانی میشدن (با شی Session اشتباه گرفته نشود)
رخداد Session_Start زمانی raise یا اجرا میشد که یک سشن جدید برای یک کاربر ساخته بشه
و رخداد Session_End نیز زمانی raise میشد که یک سشن expire (منقضی) بشه
🔰مکانیزمی که سشن کاربری رو ایجاد ومنقضی میکرد، مراحلش به این صورت بود که:
▪️اولین بار که شخصی سایت رو باز میکرد، خود ASP.NET یک کوکی به نام "ASP.NET_SessionD" با مقدار یک "کلید تصادفی" به همراه Response برای کاربر میفرستاد و اون در مرورگر کاربر ذخیره میشد و از اون طرف همین "کلید تصادفی" در حافظه مموری سرور (به کمک شی Session) به عنوان شناسه یک کاربر (که شاید هنوز نمیدونیم کیه ولی میدونیم یه کاربره) ذخیره میشد (تا اینجای کار یک سشن برای کاربر جدید ساخته شده، در نتیجه رخداد Session_Start فراخوانی میشد)
▪️از درخواست های بعدی، این کوکی به همراه مقدارش (همون کلید تصادفی)، به Server ارسال میشد سپس ASP.NET این کلید رو میخوند و با مقادیر ذخیره شده در شی Session (در حافظه رم) مطابقت میداد و متوجه میشد که این همون کاربری هست که قبلا درخواست زده بود.
تایم منقضی شدن این سشن ها (session expire) به صورت پیشفرض 20 دقیقه بود و مادامی که درخواست یا بازدید از سمت همون کاربر میومد، این مدت زمان تمدید میشد.
در نتیجه مادامی که آخرین درخواست کاربر کمتر از 20 دقیقه قبل بود، سشن برقرار بود و زمانی که این مدت از 20 بیشتر میشد. اون سشن به صورت خودکار expire/منقضی میشد (در این مرحله رخداد Session_End فراخوانی میشد)
🔸بنابراین مادامی که کاربر ما، فاصله بین هر درخواستش کمتر از 20 دقیقه بود، سشن اون کاربر برقرار بود و یک کاربر "آنلاین" به حساب میومد
و زمانی که از آخرین درخواست کاربر، بیش از 20 دقیقه میگذشت، سشن کاربر منقضی شده و یک کاربر "آفلاین" به حساب میومد
در این حالت با کمی کد نویسی میشد تعداد کاربران آنلاین رو محاسبه کرد، به این صورت که یک متغیر global برای تعداد کاربران آنلاین در نظر میگرفتیم و به هنگام Session_Start اون رو ++ (یکی اضافه) و به هنگام Session_End اون رو -- (یکی کم) میکردیم
نکته: این توضیحات حالت پیشفرض هست، در صورت تنظیم sessionState میتونه محل ذخیره سازی سشن و کوکی در سمت سرور و کلاینت متفاوت باشه (مثلا ذخیره شدن سشن ها درون یک دیتابیس SqlServer به جای Memory یا تنظیم شدن کلید تصادفی درون URL به جای کوکی) - توضیحات بیشتر
🔹در ASP.NET Core اما این مکانیزم و این دو متد دیگه وجود نداره. پس مجبوریم مشابه همین مکانیزم رو خودمون کدنویسی و طراحی کنیم. کد نویسیش کار خاصی نداره، همین مراحل ساخت کوکی با یک "کلید تصادفی" (مثلا guid) و ذخیره اون علاوه بر Response، درون یک InMemory Cache داخل یک Middleware به سادگی انجام میشه
🔸در این روش چون فاصله زمانی 20 دقیقه رو برای session expire هست در نتیجه همیشه ما یک تلورانس و اختلاف 20 دقیقه ای ممکنه داشته باشیم. اگر کاربر جاری همین الان مرورگرش رو میبنده یا برق میره چون session اش تا 20 دقیقه از آخرین بازدیدش معتبر هست، همچنان تا 20 دقیقه آینده "آنلاین" محسوب میشه
2️⃣ روش دوم - با استفاده از ارتباطات Realtime مانند SignalR
🔹این روش خیلی مشابه روش قبل هست با این تفاوت که به محض برقرار شدن اتصال کاربر (رخداد OnConnectedAsync کلاس Hub) اون رو به عنوان کاربر آنلاین و به محض قطع شدن ارتباطش (رخداد OnDisconnectedAsync کلاس Hub) اون کاربر رو آفلاین در نظر میگیریم.
بقیه موارد ساخت کلید تصادفی و تنظیم کوکی جهت تشخیص کاربر از بقیه کاربر ها تقریبا مشابه قبل هست
🔸مزیت این روش اینه که دیگه ما تلورانس و اختلاف 20 دقیقه رو نخواهیم داشت و به صورت آنی و در لحظه تعداد کاربران آنلاین بروزرسانی خواهد شد
معایبش هم اینه که به دلیل استفاده از ارتباطات realtime پردازش بیشتری نسبت به روش اول روی سرور میوفته و یا اینکه امکان استفاده از ارتباطات realtime در برنامه شما به هر دلیل از جمله زیرساخت network یا محدودیت های سرور و application شما وجود نداشته باشه
🔹نکته آخر اینکه در اینجا سعی کردم مکانیزم خیلی ساده توضیح بدم اما پیاده سازی صحیح چنین مکانیزمی با توجه به امکان وقوع همزمانی مستلزم اینه که نکات پیشگیری از مشکلات همزمانی رعایت بشه
🔰در اینجا یک پروژه نمونه آماده کردم که هر دو این روش ها رو پیاده سازی کرده و میتونین با بررسی سورس کدش بیشتر با نحوه عملکرد اون آشنا بشین
https://github.com/dotnetzoom/OnlineUsers-AspNetCore
_________
@DotNetZoom
برای محاسبه تعداد کاربران آنلاین اساسا دو روش وجود داره
1️⃣ روش اول - با استفاده از Cookie
در ASP.NET قدیم داخل کلاس global.asax متد هایی وجود داشت به نام Session_Start و Session_End که به هنگام شروع و پایان "سشن" کاربری، فراخوانی میشدن (با شی Session اشتباه گرفته نشود)
رخداد Session_Start زمانی raise یا اجرا میشد که یک سشن جدید برای یک کاربر ساخته بشه
و رخداد Session_End نیز زمانی raise میشد که یک سشن expire (منقضی) بشه
🔰مکانیزمی که سشن کاربری رو ایجاد ومنقضی میکرد، مراحلش به این صورت بود که:
▪️اولین بار که شخصی سایت رو باز میکرد، خود ASP.NET یک کوکی به نام "ASP.NET_SessionD" با مقدار یک "کلید تصادفی" به همراه Response برای کاربر میفرستاد و اون در مرورگر کاربر ذخیره میشد و از اون طرف همین "کلید تصادفی" در حافظه مموری سرور (به کمک شی Session) به عنوان شناسه یک کاربر (که شاید هنوز نمیدونیم کیه ولی میدونیم یه کاربره) ذخیره میشد (تا اینجای کار یک سشن برای کاربر جدید ساخته شده، در نتیجه رخداد Session_Start فراخوانی میشد)
▪️از درخواست های بعدی، این کوکی به همراه مقدارش (همون کلید تصادفی)، به Server ارسال میشد سپس ASP.NET این کلید رو میخوند و با مقادیر ذخیره شده در شی Session (در حافظه رم) مطابقت میداد و متوجه میشد که این همون کاربری هست که قبلا درخواست زده بود.
تایم منقضی شدن این سشن ها (session expire) به صورت پیشفرض 20 دقیقه بود و مادامی که درخواست یا بازدید از سمت همون کاربر میومد، این مدت زمان تمدید میشد.
در نتیجه مادامی که آخرین درخواست کاربر کمتر از 20 دقیقه قبل بود، سشن برقرار بود و زمانی که این مدت از 20 بیشتر میشد. اون سشن به صورت خودکار expire/منقضی میشد (در این مرحله رخداد Session_End فراخوانی میشد)
🔸بنابراین مادامی که کاربر ما، فاصله بین هر درخواستش کمتر از 20 دقیقه بود، سشن اون کاربر برقرار بود و یک کاربر "آنلاین" به حساب میومد
و زمانی که از آخرین درخواست کاربر، بیش از 20 دقیقه میگذشت، سشن کاربر منقضی شده و یک کاربر "آفلاین" به حساب میومد
در این حالت با کمی کد نویسی میشد تعداد کاربران آنلاین رو محاسبه کرد، به این صورت که یک متغیر global برای تعداد کاربران آنلاین در نظر میگرفتیم و به هنگام Session_Start اون رو ++ (یکی اضافه) و به هنگام Session_End اون رو -- (یکی کم) میکردیم
نکته: این توضیحات حالت پیشفرض هست، در صورت تنظیم sessionState میتونه محل ذخیره سازی سشن و کوکی در سمت سرور و کلاینت متفاوت باشه (مثلا ذخیره شدن سشن ها درون یک دیتابیس SqlServer به جای Memory یا تنظیم شدن کلید تصادفی درون URL به جای کوکی) - توضیحات بیشتر
🔹در ASP.NET Core اما این مکانیزم و این دو متد دیگه وجود نداره. پس مجبوریم مشابه همین مکانیزم رو خودمون کدنویسی و طراحی کنیم. کد نویسیش کار خاصی نداره، همین مراحل ساخت کوکی با یک "کلید تصادفی" (مثلا guid) و ذخیره اون علاوه بر Response، درون یک InMemory Cache داخل یک Middleware به سادگی انجام میشه
🔸در این روش چون فاصله زمانی 20 دقیقه رو برای session expire هست در نتیجه همیشه ما یک تلورانس و اختلاف 20 دقیقه ای ممکنه داشته باشیم. اگر کاربر جاری همین الان مرورگرش رو میبنده یا برق میره چون session اش تا 20 دقیقه از آخرین بازدیدش معتبر هست، همچنان تا 20 دقیقه آینده "آنلاین" محسوب میشه
2️⃣ روش دوم - با استفاده از ارتباطات Realtime مانند SignalR
🔹این روش خیلی مشابه روش قبل هست با این تفاوت که به محض برقرار شدن اتصال کاربر (رخداد OnConnectedAsync کلاس Hub) اون رو به عنوان کاربر آنلاین و به محض قطع شدن ارتباطش (رخداد OnDisconnectedAsync کلاس Hub) اون کاربر رو آفلاین در نظر میگیریم.
بقیه موارد ساخت کلید تصادفی و تنظیم کوکی جهت تشخیص کاربر از بقیه کاربر ها تقریبا مشابه قبل هست
🔸مزیت این روش اینه که دیگه ما تلورانس و اختلاف 20 دقیقه رو نخواهیم داشت و به صورت آنی و در لحظه تعداد کاربران آنلاین بروزرسانی خواهد شد
معایبش هم اینه که به دلیل استفاده از ارتباطات realtime پردازش بیشتری نسبت به روش اول روی سرور میوفته و یا اینکه امکان استفاده از ارتباطات realtime در برنامه شما به هر دلیل از جمله زیرساخت network یا محدودیت های سرور و application شما وجود نداشته باشه
🔹نکته آخر اینکه در اینجا سعی کردم مکانیزم خیلی ساده توضیح بدم اما پیاده سازی صحیح چنین مکانیزمی با توجه به امکان وقوع همزمانی مستلزم اینه که نکات پیشگیری از مشکلات همزمانی رعایت بشه
🔰در اینجا یک پروژه نمونه آماده کردم که هر دو این روش ها رو پیاده سازی کرده و میتونین با بررسی سورس کدش بیشتر با نحوه عملکرد اون آشنا بشین
https://github.com/dotnetzoom/OnlineUsers-AspNetCore
_________
@DotNetZoom
Telegram
Attach Files
Forwarded from Software Philosophy
معرفی System.Threading.Channels
فرض کنید سیستم ایمیل مارکتینگ شما قرار است یک میلیون کاربر را در حافظه لود کند و سپس برای همهی آنها ایمیل ارسال کند. از زمانی که شما این کاربرها را از دیتابیس لود میکنید هزینه بالایی بابت کوئری سنگین متحمل میشوید و همچنین بعد از لود کردن هم نگهداری این تعداد در حافظه باعث اشغال شدن مقدار زیادی از حافظه میشود. (هر چند عملیات با موفقیت انجام میشود ولی بهینه نیست!)
از طرفی هم اگر بخواهید مثلا هزار تا هزار تا این داده ها را لود و ارسال کنید، سرعت عملیات پایین میآید.
بهینه ترین روش ایجاد سیستمی است که همانند چرخه تولید به مصرف عمل کند. یعنی مصرف کننده داده صرفا دادههایی را از یک صف تعریف شده میگیرد و قسمت تولید کننده داده هم با استراتژی خاصی دادهها را تولید (از دیتابیس لود میکند) و داخل صف قرار میدهد و هر موقع کارش به اتمام رسید به مصرف کننده اعلام میکند تا دیگر منتظر صف نماند.
در اینجا چالشهای زیادی مطرح میشود که در System.Threading.Channels این چالشها مد نظر قرار گرفته شده است که برنامه نویس میتواند بر روی چنل (صف) داده قرار دهد (Write) و یا در جای دیگری از دادههای صف استفاده کند (Read).
افزودن داده بر روی چنل
https://virgool.io/@hamedhajiloo96/system-threading-channels-z1kx0mctp7gp
⁉️ برای بحث و تبادل نظر فنی در مورد این پست، برروی دکمه «نظرت را بگو» کلیک کنید.
#حامد_حاجیلو (http://bit.ly/2IVjfYD)
کانال تلگرام:
@SoftwarePhilosophy
________
فرض کنید سیستم ایمیل مارکتینگ شما قرار است یک میلیون کاربر را در حافظه لود کند و سپس برای همهی آنها ایمیل ارسال کند. از زمانی که شما این کاربرها را از دیتابیس لود میکنید هزینه بالایی بابت کوئری سنگین متحمل میشوید و همچنین بعد از لود کردن هم نگهداری این تعداد در حافظه باعث اشغال شدن مقدار زیادی از حافظه میشود. (هر چند عملیات با موفقیت انجام میشود ولی بهینه نیست!)
از طرفی هم اگر بخواهید مثلا هزار تا هزار تا این داده ها را لود و ارسال کنید، سرعت عملیات پایین میآید.
بهینه ترین روش ایجاد سیستمی است که همانند چرخه تولید به مصرف عمل کند. یعنی مصرف کننده داده صرفا دادههایی را از یک صف تعریف شده میگیرد و قسمت تولید کننده داده هم با استراتژی خاصی دادهها را تولید (از دیتابیس لود میکند) و داخل صف قرار میدهد و هر موقع کارش به اتمام رسید به مصرف کننده اعلام میکند تا دیگر منتظر صف نماند.
در اینجا چالشهای زیادی مطرح میشود که در System.Threading.Channels این چالشها مد نظر قرار گرفته شده است که برنامه نویس میتواند بر روی چنل (صف) داده قرار دهد (Write) و یا در جای دیگری از دادههای صف استفاده کند (Read).
افزودن داده بر روی چنل
await channel.Writer.WriteAsync(item);خواندن داده از چنل
channel.Reader.ReadAllAsync()توضیحات تکمیلی را اینجا بخوانید:
https://virgool.io/@hamedhajiloo96/system-threading-channels-z1kx0mctp7gp
⁉️ برای بحث و تبادل نظر فنی در مورد این پست، برروی دکمه «نظرت را بگو» کلیک کنید.
#حامد_حاجیلو (http://bit.ly/2IVjfYD)
کانال تلگرام:
@SoftwarePhilosophy
________
ویرگول
معرفی System.Threading.Channels
معرفی سیستمی جهت پیاده سازی بهینه و ایمن صف Queue در برنامه نویسی
❇️ نمونه معماری پیاده سازی شده با ASP.NET Core و Angular و DDD
مناسب جهت Code Review و ایده برداری
✔️.NET 5
✔️ASP.NET Core 5
✔️Entity Framework Core 5
✔️C# 9
✔️#Angular 11
✔️#UIkit
✔️#Clean_Code
✔️#Clean_Architecture
✔️#SOLID
✔️#DDD
🔰لینک مخزن گیتهاب
https://github.com/rafaelfgx/Architecture
___________________
@DotNetZoom
مناسب جهت Code Review و ایده برداری
Architecture .NET 5, ASP.NET Core 5, Entity Framework Core 5, C# 9, Angular 11, Clean Code, SOLID, DDD.
تکنولوژی ها و تکنیک های استفاده شده: ✔️.NET 5
✔️ASP.NET Core 5
✔️Entity Framework Core 5
✔️C# 9
✔️#Angular 11
✔️#UIkit
✔️#Clean_Code
✔️#Clean_Architecture
✔️#SOLID
✔️#DDD
🔰لینک مخزن گیتهاب
https://github.com/rafaelfgx/Architecture
___________________
@DotNetZoom
GitHub
GitHub - rafaelfgx/Architecture: .NET, Angular, Clean Architecture, Clean Code, SOLID Principles, KISS Principle, DRY Principle…
.NET, Angular, Clean Architecture, Clean Code, SOLID Principles, KISS Principle, DRY Principle, Fail Fast Principle, Common Closure Principle, Common Reuse Principle, Acyclic Dependencies Principle...
✅ لاگ کردن جزئیات Request ها به کمک Serilog و ActionFilter
بعضی وقتا پیش میاد لازم دارید اطلاعات هر درخواست ورودی Action هامون رو به همراه جزئیات کاملشون رو جهت عیب یابی یا بررسی های آتی ثبت و Log کنیم
در اینجا یک نمونه پروژه آماده کردم که این کار رو به راحتی قرار دادن یک اتریبیوت [LogRequest] بر روی اکشن های مورد نظر انجام میده یا میتونین روی Controller یا به صورت Global ثبت اش کنین تا همه اکشن ها رو Log کنه
🔸طرز کارش به این صورته که در درون ActionFilter مذکور (LogRequest)، جزئیات لازم رو قبل و بعد از اجرا شدن Action مورد نظر Log میکنه (بنا بر نیازتون میتونین هر دیتای دلخواه دیگه ای رو هم از request و response بهش اضافه کنین)
و نهایتا برای ذخیره سازی لاگ ها هم از Serilog و از SqlServer به عنوان Sinks استفاده میکنه (در صورت دلخواه میتونین تو هر Storage/Sink دیگه ای ذخیره کنین)
🔹مسلما لاگ کردن همه درخواست ها میتونه سربار داشته باشه و شخصا پیشنهاد نیمکنم همیشه و همه جا ازش استفاده کنین ولی نکته ای که در مورد Sink های Serilog وجود داره اینه که اکثرا از Async و PeriodicBatching استفاده میکنن به این صورت که در بازه های زمانی Log ها رو به صورت Bulk ایی Insert میکنن (اونم به صورت Async که Thread ایی رو بلاک نکنن) در نتیجه از نظر پرفرمنسی در حالت بهینه ای کار میکنن
🔰از جمله جزئیاتی که در هر درخواست Log میکنه:
1- آدرس URL درخواستی به همراه مقادیر QueryString
2- مقادیر Header های Request و Response
3- مقادیر ارسالی از سمت کاربر (آرگومان های Action)
4- وضعیت ModelState به همراه Error Message ها در صورت وجود
5- مقادیر Routing بسته به Route مچ شده
6- مقادیر شی User.Identity از جمله Claim ها، Name و IsAuthenticated
7- مقدار IP Address کاربر
8- مقدار Url Referrer (آدرس هدایت کننده قبلی به این صفحه)
9- مدت زمان پردازش درخواست جاری (Elapsed Time) و زمان ثبت درخواست
10- جزئیات Exception در صورت وقوع خطا
11- وضعیت Http Status Code درخواست
12- و...
https://github.com/dotnetzoom/RequestLogger-AspNetCore
____________________
@DotNetZoom
بعضی وقتا پیش میاد لازم دارید اطلاعات هر درخواست ورودی Action هامون رو به همراه جزئیات کاملشون رو جهت عیب یابی یا بررسی های آتی ثبت و Log کنیم
در اینجا یک نمونه پروژه آماده کردم که این کار رو به راحتی قرار دادن یک اتریبیوت [LogRequest] بر روی اکشن های مورد نظر انجام میده یا میتونین روی Controller یا به صورت Global ثبت اش کنین تا همه اکشن ها رو Log کنه
🔸طرز کارش به این صورته که در درون ActionFilter مذکور (LogRequest)، جزئیات لازم رو قبل و بعد از اجرا شدن Action مورد نظر Log میکنه (بنا بر نیازتون میتونین هر دیتای دلخواه دیگه ای رو هم از request و response بهش اضافه کنین)
و نهایتا برای ذخیره سازی لاگ ها هم از Serilog و از SqlServer به عنوان Sinks استفاده میکنه (در صورت دلخواه میتونین تو هر Storage/Sink دیگه ای ذخیره کنین)
🔹مسلما لاگ کردن همه درخواست ها میتونه سربار داشته باشه و شخصا پیشنهاد نیمکنم همیشه و همه جا ازش استفاده کنین ولی نکته ای که در مورد Sink های Serilog وجود داره اینه که اکثرا از Async و PeriodicBatching استفاده میکنن به این صورت که در بازه های زمانی Log ها رو به صورت Bulk ایی Insert میکنن (اونم به صورت Async که Thread ایی رو بلاک نکنن) در نتیجه از نظر پرفرمنسی در حالت بهینه ای کار میکنن
🔰از جمله جزئیاتی که در هر درخواست Log میکنه:
1- آدرس URL درخواستی به همراه مقادیر QueryString
2- مقادیر Header های Request و Response
3- مقادیر ارسالی از سمت کاربر (آرگومان های Action)
4- وضعیت ModelState به همراه Error Message ها در صورت وجود
5- مقادیر Routing بسته به Route مچ شده
6- مقادیر شی User.Identity از جمله Claim ها، Name و IsAuthenticated
7- مقدار IP Address کاربر
8- مقدار Url Referrer (آدرس هدایت کننده قبلی به این صفحه)
9- مدت زمان پردازش درخواست جاری (Elapsed Time) و زمان ثبت درخواست
10- جزئیات Exception در صورت وقوع خطا
11- وضعیت Http Status Code درخواست
12- و...
https://github.com/dotnetzoom/RequestLogger-AspNetCore
____________________
@DotNetZoom
Forwarded from کدهک
✅ معرفی REST API Guideline شرکت های بزرگ + Best Practice ها
🔸Microsoft REST API Guidelines
🔹Microsoft Best Practices for Web API design
🔸Microsoft Best Practices for Web API implementation
🔹Google API Design Guide
🔸PayPal API Design Guidelines
🔸Stackoverflow Best practices for REST API design
🔸Best Practices for Designing a Pragmatic RESTful API
__________________
@DotNetZoom
🔸Microsoft REST API Guidelines
🔹Microsoft Best Practices for Web API design
🔸Microsoft Best Practices for Web API implementation
🔹Google API Design Guide
🔸PayPal API Design Guidelines
🔸Stackoverflow Best practices for REST API design
🔸Best Practices for Designing a Pragmatic RESTful API
__________________
@DotNetZoom