Response Caching در ASP.NET Core 1.1
With the ASP.NET Core 1.1 release, many new features were introduced. One of them was enabling gZip compression and today we will take a look at another new feature which is Response Caching Middleware.
دانای اطلاعات ( Information Expert )
بر طبق این اصل میتوان برای واگذاری هر مسئولیت، کلاسی را انتخاب کرد که بیشترین اطلاعات را در مورد انجام آن در اختیار دارد و لذا نیاز کمتری به ایجاد ارتباط با دیگر مولفهها خواهد داشت.
در مثال زیر مشاهده میکنید که کلاس User، اطلاعات کاملی را از عملیات اضافه کردن آیتمی را به لیست خرید و تسویه حساب، ندارد و پیاده سازی این عملیات در این کلاس، نیاز به ایجاد وابستگیهای پیچیدهای دارد.
public class User { public ShoppingCart ShoppingCart { get; set; } public void AddItem(string name) { // User class must know how to create OrderItem var item = new OrderItem() { Name = name }; // User class must know how to add item to shopping cart ShoppingCart.Items.Add(item); } public void CheckOut() { // User class must know logic behind cost and discount calculations: // check for discount // check shipping method // check promotions // calculate total cost of items } } public class OrderItem { public int Id { get; set; } public string Name { get; set; } } public class ShoppingCart { public int Id { get; set; } public List<OrderItem> Items { get; set; } }
بنابراین به جای این طراحی، مسئولیتها را به ShoppingCart منتقل میکنیم:
public class User { public ShoppingCart ShoppingCart { get; set; } } public class OrderItem { public int Id { get; set; } public string Name { get; set; } } public class ShoppingCart { public int Id { get; set; } public List<OrderItem> Items { get; set; } public void AddItem(string name) { // ShoppingCart class know how to create OrderItem var item = new OrderItem() { Name = name }; // ShoppingCart class already know how to add item Items.Add(item); } public void CheckOut() { // ShoppingCart class know logic behind cost and discount calculations: // check for discount // check shipping method // check promotions // calculate total cost of items } }
اتصال ضعیف ( Low Coupling )
با اتصال ضعیف نیز که از ویژگیهای یک طراحی خوب است آشنا هستیم. هر چه تعداد و نوع اتصال بین مولفهها کمتر و ضعیفتر باشد، اعمال تغییرات راحتتر صورت خواهد گرفت. طراحی با اتصال مناسب سه ویژگی را دارد:
- وابستگی بین کلاسها کم است.
- تغییرات در یک کلاس، اثر کمی بر دیگر کلاسها دارد.
- پتانسیل استفادهی مجدد از مؤلفهها بالا است.
چنانچه قبلا هم اشاره کردم، نوشتن نرم افزاری بدون اتصال، ممکن نیست و باید مؤلفهها با هم همکاری کرده و وظایف را انجام دهند. با این حال میتوان نوع اتصالات و تعداد آنرا بهبود بخشید.
چند ریختی ( Polymorphism )
چند ریختی که از ویژگیهای اساسی برنامه نویسی و زبانهای شیء گراست، به منظور بالا بردن قابلیت استفادهی مجدد، استفاده میشود. بر طبق این اصل، مسئولیت تعریف رفتارهای وابسته به نوع کلاس (زیرنوعها در روابط ارث بری) باید به کلاسی واگذار شود که تغییر رفتار در آن اتفاق میافتد. به عبارت دیگر باید به صورت خودکار رفتار را بر اساس نوع کلاس تصحیح کنیم. این روش در مقابل بررسی نوع دادهای برای انجام رفتار مناسب میباشد.
به عنوان مثال اگر کلاسهای چهار ضلعی، مربع، مستطیل و ذوزنقه را داشته باشیم، برای پیاده سازی مساحت در کلاس چهار ضلعی، طول را در عرض ضرب میکنیم. با این حال نوع رفتار مساحت ذوزنقه متفاوت از دیگران است. طبق این اصل، برای اعمال کردن این تغییر، فقط خود کلاس ذوزنقه باید رفتار مربوطه را پیاده سازی کند و هیچ منطق و کدی نباید برای چک کردن نوع کلاس استفاده گردد.
public class ShapeWithoutPolymorphism { public double X { get; set; } public double Y { get; set; } public double Z { get; set; } public double Area(string shapeType) { switch (shapeType) { case "square": return X * Y; case "rectangle": return X * Y; case "trapze": return (X + Z) * Y / 2; default: return 0; } } }
با استفاده از چندریختی، طراحی به این صورت در خواهد آمد:
public abstract class Shape { public double X { get; set; } public double Y { get; set; } public virtual double Area() { return X * Y; } } public class Rectangle : Shape { // No need to override } public class Square : Shape { // No need to override } public class Trapze : Shape { public double Z { get; set; } public override double Area() { return (X + Z) * Y / 2; } }
مصنوع خالص ( Pure Fabrication )
مصنوع خالص کلاسی است که در دامنه مساله وجود ندارد و به منظور کاهش اتصال، افزایش انسجام و افزایش امکان استفاده مجدد کد ایجاد میشود. سرویسها را میتوان از این دسته نامید. کلاسهایی که دقیقا برای کاهش اتصال، افزایش انسجام و افزایش امکان استفاده مجدد کد استفاده میگردند. سرویسها عملیاتی تکراری هستند که توسط مولفههای دیگر استفاده میشوند. اگر سرویسها وجود نداشتند هر مولفهای میبایست عملیات را در درون خود پیاده سازی میکرد که این هم باعث افزایش حجم کد و هم باعث کابوس شدن اعمال تغییرات میشد.
برای تشخیص زمان استفاده از این اصل میتوان گفت زمانیکه رفتاری را نمیدانیم به کدام کلاس واگذار کنیم، کلاس جدیدی را ایجاد میکنیم. در اینجا بجای آنکه به زور مسئولیتی را به کلاس نامربوطی بچسبانیم، آنرا به کلاس جدیدی که فقط رفتاری را دارد، منتقل میکنیم. با اینکار انسجام کلاسها را حفظ کردهایم و هیچ اشکالی ندارد که کلاسی بدون داده بوده و فقط متد داشته باشد. اگر به یاد داشته باشید، در اصل واسطه گری (Indirection ) کلاس جدیدی برای ایجاد ارتباط ساختیم. در حقیقت مسئولیت برقراری ارتباط بین مؤلفهها را به کلاس دیگری واگذار کردیم که چنانچه میبینید، بدون آنکه بدانیم، برای حل مشکل از اصل مصنوع خالص استفاده کردیم.
در مثال زیر این مساله مشهود است:
public class User { public int Id { get; set; } public string UserName { get; set; } public string Password { get; set; } } public class LibraryManagement { public User CurrentUser { get; set; } public void AddBookToLibrary(int bookId) { // check for CurrentUser authority: // not user's responsibility nor LibraryManagement } public void RearrangeBook(int bookId, int shelfId) { // check for CurrentUser authority // not user's responsibility nor LibraryManagement } } public class UserManagement { public User CurrentUser { get; set; } public void AddUser(string name) { // check for CurrentUser authority: // not user's responsibility nor UserManagement } public void ChangeUserRole(int userId, int roleId) { // check for CurrentUser authority // not user's responsibility nor UserManagement } } public class AuthorizationService { public bool IsAuthorized(int userId, int roleId) { // get user roles from data base // return true if user has the authority } }
عملیات بررسی مجوزها باید در کلاس جدیدی به نام AuthorizationService ارائه شود. بدین صورت تمام قسمتها، از این کد بدون وابستگی اضافی میتوانند استفاده کنند.
حفاظت از تاثیر تغییرات ( Protected Variations )
این اصل میگوید که کلاسها باید از تغییرات یکدیگر مصون بمانند. در واقع این اصل غایت یک طراحی خوب است. تمام اصولی را که تا به حال بررسی کردهایم، به منظور دستیابی به چنین رفتاری از طراحی بودهاست. بدین منظور باید از اصول Open/Closed برای واسطها، چند ریختی در توارث و ... استفاده کرد تا از تاثیرات زنجیرهای تغییرات در امان بمانیم.
اجرای دات نت در مروگر توسط Ooui
Earlier this year, Microsoft announced their support for Blazor, and now Frank A. Krueger has developed the Ooui library which allows C# or F# to be used to write applications that run in the browser. Ooui can target WASM, enabling Xamarin.Forms app to be deployed in web assembly and the result runs entirely in-browser without the need for an application server.
ReSharper 2021.1 منتشر شد
UrlRewriter توسط Intelligencia.UrlRewriter
Could not find schema information for the element 'rewrite' Could not find schema information for the attribute 'url' Could not find schema information for the attribute 'to' Could not find schema information for the attribute 'processing'
We developers spend lot of our time reading code. We read code so that we know how to change it to implement a new feature, fix a bug, etc. It is much better to work in a code base where code is easy to read and understand.
One thing that can make code readable is good naming. Giving variables, classes, and methods good names makes code easier to read.
در واقع Sequence روشی برای تولید اعداد ترتیبی با قابلیت افزایش یا کاهش عددهای دلخواه میباشد که توسط کاربر یا برنامه نویس ایجاد میشود. بنابراین Sequenceها User-Defined میباشند.
در اینجا ممکن است سئوالی پیش بیاید که اینکار توسط Identity هم قابل انجام است، اما چرا استفاده از Sequence توسط مایکروسافت پیشنهاد میشود.
بدلایل زیر استفاده از Sequence بهتر میباشد:
- ممکن است Application شما قبل از درج رکورد، درون یک جدول نیاز به عدد منحصربفردی داشته باشد.
- عدد تولید شده بوسیله Sequence را میتوانید بین جداول یا ستونهای مختلف یک جدول به اشتراک بگذارید.
- میتوانید روند تولید اعداد ترتیبی را Restart نمایید. به عبارت دیگر قابلیت Restart نمودن Sequence وجود دارد.
- میتوانید Sequence خود را براساس Sort یک یا چند فیلد، تنظیم نمایید.
Syntax آن به شرح ذیل میباشد:
CREATE SEQUENCE [schema_name . ] sequence_name [ AS [ built_in_integer_type | user-defined_integer_type ] ] [ START WITH <constant> ] [ INCREMENT BY <constant> ] [ { MINVALUE [ <constant> ] } | { NO MINVALUE } ] [ { MAXVALUE [ <constant> ] } | { NO MAXVALUE } ] [ CYCLE | { NO CYCLE } ] [ { CACHE [ <constant> ] } | { NO CACHE } ] [ ; ]
شرح Syntax :
- در زمان ایجاد Sequence، نوع آن میبایست عددی باشد، چنانچه ،Type آن را مشخص ننمایید، SQL Server، نوع آن را bigint در نظر میگیرد.
- Start With: بدین مفهوم میباشد، که Sequence ایجاد شده از چه عددی آغاز شود.
- INCREMENT BY: مفهومش این است که Sequence به چه مقداری افزایش یا کاهش یابد. به عبارت دیگری عدد تولید شده براساس مقدار Increment by تولید میشود.
- Minvalue: کمترین مقداری که Sequence میتواند ایجاد نماید.
- Maxvalue :بیشترین مقداری که Sequence میتواند ایجاد نماید.
- Cycle :مقداری را که برای Cycle تعیین مینماییم، بدین مفهوم است که Sequence پس از چه عددی میبایست Restart شود.
- Cache :عددی که برای Cache در نظر میگیریم، مفهومش این است که چه تعداد از اعداد تولید شده توسط Sequence، قبل از استفاده، میتواند در Cache قرار گیرد.
در ادامه با یک مثال ساده، یک Sequence ایجاد مینماییم:
CREATE SEQUENCE [dbo].[SequenceTest] AS [int] START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 30 CYCLE CACHE GO
برای اینکه بتوانیم مقدار Sequence را بدست آوریم، کافیست از Syntax زیر استفاده نمایید:
NEXT VALUE FOR [ database_name . ] [ schema_name . ] sequence_name [ OVER (<over_order_by_clause>) ]
اگر Select بالا را تا 30 بار انجام دهید، برای دفعه 31 مقدار آن یک میشود، چون در زمان تعریف Cycle ،Sequence را انتخاب کرده بودیم. در غیر اینصورت برای دفعه 31 با خطا زیر مواجه میشوید.
Msg 11728, Level 16, State 1, Line 1 The sequence object 'SequenceTest' has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.
در ابتدا مطابق Script زیر جدولی را ایجاد و مقادیری را درون آن درج مینماییم:
create table Kids ( ID int, Name varchar(50) ); Go insert Kids values (1,'Emma') , (1,'Tabitha') , (2,'Kendall') , (3,'Delaney') , (4,'Kyle') , (5,'Jessica') , (6,'Josh') , (7,'Kirsten') , (8,'Amanda') , (9,'Jimmy') ;
CREATE SCHEMA Samples ; GO
CREATE SEQUENCE Samples.Test AS tinyint START WITH 1 INCREMENT BY 1 ; GO
SELECT NEXT VALUE FOR Samples.Test OVER (ORDER BY Name) AS NutID, ID, Name FROM test1.Kids WHERE Name LIKE '%e%' ;
امیدوارم مطلب فوق مفید واقع شده باشد.