با تشکر از توجه شما.
در این پروژه نمونه و با همین تنظیمات، شرایط بدین گونه است:
کاربر سایت را به صورت ناشناس مشاهده میکند. سپس با اطلاعات خود وارد سایت میشود. پس از تعییت هویت، مثلا به بخش Product هم دسترسی پیدا میکند. تا این مرحله همه چیز خوب است و خیر. سپس از حساب خود خارج میشود و دقایقی بعد، مجددا وارد حساب خود میشود. از این لحظه به بعد، رفتار برنامه متفاوت میشود. چرا که با وجود اینکه کاربر تایید هویت شده، اما اگر بخواهد مثلا دوباره به همان بخش Product مراجعه کند، سیستم ابتدا او را به صفحهی ورود هدایت کرده و با کاربر، به عنوان یک کاربر ناشناخته برخورد میکند. همین گونه است برای سایر قسمتهایی که صفت Authorize برای آنها لحاظ شده. پرسش من این است که آیا این رفتار طبیعی ست؟
قبلا گفتم که با تغییر مقدار validateInterval ظاهرا این مشکل بر طرف میشود. لااقل این رفتار تغییر میکند. شما فرمودید که در نظرگرفتن هر عددی جز صفر، موجب میشود تا کوکی بلافاصله به روز نشود. این صحبت شما کاملا صحیح و منطقی. اما آیا ورودهای مکرر به نظر شما منطقی ست؟
به کدهای این پروژه هم دقت کردم. مقدار validateInterval برابر با 30 لحاظ شده که ظاهرا نباید اینگونه باشد. برای اینکه هم به رویکردی که شما به آن اشاره کردید برسیم و هم کاربر مجبور نباشد مدام Login کند، لطفا بفرمایید که چه تغییراتی لازم است؟ در صورتیکه من اشتباه کرده ام و یا چیزی را ندیده و یا از قلم انداخته ام، لطف میکنید اگر راهنمایی بفرمایید.
بررسی سورس کد این پرژه، ایدههای بسیار جالبی به شما میدهد. پیشنهاد میکنم حتما کد هاشو بررسی کنید. نکات آموزشی زیادی داخل هست.
چند پروژه منتخب :
- Mvc.GenericControllers : ساخت کنترولر برای Entityها بدون کدنویسی!
- Mvc.CustomRoutingConvention : مسیریابی بر اساس namespace کنترولرها
- Localization.EntityFramework : مدیریت منابع چند زبانگی توسط EntityFramework
اشتراکها
بررسی تازههای Blazor در NET 6.
اشتراکها
ReSharper Ultimate 2016.3 منتشر شد
کارهای سورس باز قابل توجهی از برنامه نویسهای ایرانی یافت نمیشوند؛ عموما کارهای ارائه شده در حد یک سری مثال یا کتابخانههای کوچک است و در همین حد. یا گاهی هم انگشت شمار پروژههایی کامل. مثل یک وب سایت یا یک برنامه نصفه نیمه دبیرخانه و امثال آن. اینها هم خوب است از دیدگاه به اشتراک گذاری اطلاعات، ایدهها و هم ... یک مزیت دیگر را هم دارد و آن این است که بتوان کیفیت عمومی کد نویسی را حدس زد.
اگر کیفیت کدها رو بررسی کنید به یک نتیجهی کلی خواهید رسید: "عموم برنامه نویسهای ایرانی (حداقل اینهایی که چند عدد کار سورس باز به اشتراک گذاشتهاند) با مفهومی به نام Refactoring هیچگونه آشنایی ندارند". مثلا یک برنامهی WinForm تهیه کردهاند و کل سورس برنامه همان چند عدد فرم برنامه است و هر فرم بالای 3000 سطر کد دارد. دوستان عزیز! به این میگویند «فاجعهای به نام کدنویسی!» صاحب اول و آخر این نوع کدها خودتان هستید! شاید به همین جهت باشد که عمدهی پروژههای سورس باز پس از اینکه برنامه نویس اصلی از توسعهی آن دست میکشد، «میمیرند». چون کسی جرات نمیکند به این کدها دست بزند. مشخص نیست الان این قسمت را که تغییر دادم، کجای برنامه به هم ریخت. تستی ندارند. ساختاری را نمیتوان از آنها دریافت. منطق قسمتهای مختلف برنامه از هم جدا نشده است. برنامه یک فرم است با چند هزار سطر کد در یک فایل! کار شما شبیه به کد اسمبلی چند هزار سطری حاصل از decompile یک برنامه که نباید باشد!
به همین جهت قصد دارم یک سری «ساده» Refactoring را در این سایت ارائه دهم. روی سادگی هم تاکید کردم، چون اگر عموم برنامه نویسها با همین موارد به ظاهر ساده آشنایی داشتند، کیفیت کد نویسی بهتری را میشد در نتایج عمومی شده، شاهد بود.
این مورد در راستای نظر سنجی انجام شده هم هست؛ درخواست مقالات خالص سی شارپ در صدر آمار فعلی قرار دارد.
Refactoring چیست؟
Refactoring به معنای بهبود پیوسته کیفیت کدهای نوشته شده در طی زمان است؛ بدون ایجاد تغییری در عملکرد اصلی برنامه. به این ترتیب به کدهایی دست خواهیم یافت که قابلیت آزمون پذیری بهتری داشته، در مقابل تغییرات مقاوم و شکننده نیستند و همچنین امکان به اشتراک گذاری قسمتهایی از آنها در پروژههای دیگر نیز میسر میشود.
قسمت اول - مجموعهها را کپسوله کنید
برای مثال کلاسهای ساده زیر را در نظر بگیرید:
namespace Refactoring.Day1.EncapsulateCollection
{
public class OrderItem
{
public int Id { set; get; }
public string Name { set; get; }
public int Amount { set; get; }
}
}
using System.Collections.Generic;
namespace Refactoring.Day1.EncapsulateCollection
{
public class Orders
{
public List<OrderItem> OrderItems { set; get; }
}
}
نکته اول: هر کلاس باید در داخل یک فایل جدا قرار گیرد. «لطفا» یک فایل درست نکنید با 50 کلاس داخل آن. البته اگر باز هم یک فایل باشد که بتوان 50 کلاس را داخل آن مشاهده کرد که چقدر هم عالی! نه اینکه یک فایل باشد تا بعدا 50 کلاس را با Refactoring از داخل آن بیرون کشید!
قطعه کد فوق، یکی از روشهای مرسوم کد نویسی است. مجموعهای به صورت یک List عمومی در اختیار مصرف کننده قرار گرفته است. حال اجازه دهید تا با استفاده از برنامه FxCop برنامه فوق را آنالیز کنیم. یکی از خطاهایی را که نمایش خواهد داد عبارت زیر است:
Error, Certainty 95, for Do Not Expose Generic Lists
بله. لیستهای جنریک را نباید به همین شکل در اختیار مصرف کننده قرار داد؛ چون به این صورت هر کاری را میتوانند با آن انجام دهند، مثلا کل آن را تعویض کنند، بدون اینکه کلاس تعریف کننده آن از این تغییرات مطلع شود.
پیشنهاد FxCop این است که بجای List از Collection یا IList و موارد مشابه استفاده شود. اگر اینکار را انجام دهیم اینبار به خطای زیر خواهیم رسید:
Warning, Certainty 75, for Collection Properties Should Be ReadOnly
FxCop پیشنهاد میدهد که مجموعه تعریف شده باید فقط خواندنی باشد.
چکار باید کرد؟
بجای استفاده از List جهت ارائه مجموعهها، از IEnumerable استفاده کنید و اینبار متدهای Add و Remove اشیاء به آنرا به صورت دستی تعریف نمائید تا بتوان از تغییرات انجام شده بر روی مجموعه ارائه شده، در کلاس اصلی آن مطلع شد و امکان تعویض کلی آنرا از مصرف کننده گرفت. برای مثال:
using System.Linq;
using System.Collections.Generic;
namespace Refactoring.Day1.EncapsulateCollection
{
public class Orders
{
private int _orderTotal;
private List<OrderItem> _orderItems;
public IEnumerable<OrderItem> OrderItems
{
get { return _orderItems; }
}
public void AddOrderItem(OrderItem orderItem)
{
_orderTotal += orderItem.Amount;
_orderItems.Add(orderItem);
}
public void RemoveOrderItem(OrderItem orderItem)
{
var order = _orderItems.Find(o => o == orderItem);
if (order == null) return;
_orderTotal -= orderItem.Amount;
_orderItems.Remove(orderItem);
}
}
}
اکنون اگر برنامه را مجددا با fxCop آنالیز کنیم، دو خطای ذکر شده دیگر وجود نخواهند داشت. اگر این تغییرات صورت نمیگرفت، امکان داشتن فیلد _orderTotal غیر معتبری در کلاس Orders به شدت بالا میرفت. زیرا مصرف کننده مجموعه OrderItems میتوانست به سادگی آیتمی را به آن اضافه یا از آن حذف کند، بدون اینکه کلاس Orders از آن مطلع شود یا اینکه بتواند عکس العمل خاصی را بروز دهد.
بازخوردهای دوره
آشنایی با AOP Interceptors
- سؤال شما این بود که در کلاس اصلی من، در متدی داخل آن، با چند صدهزار رکورد کار انجام میشود. پاسخ این است که اصلا این پروکسی ایجاد شده ربطی به داخل متد شما ندارد. کاری به وهله سازیهای انجام شده داخل آن نیز ندارد. invocation.Proceed یعنی این متد رو اجرا کن؛ نه اینکه هر وهلهای که داخل آن متد قرار میگیرد را نیز با پروکسی مزین کن.
- تمام ORMها برای پیاده سازی مباحث Lazy loading یک شیء پروکسی را از شیء اصلی شما ایجاد میکنند. نمونهاش را شاید با EF Code first با نامهای خودکاری مانند ClassName_00394CF1F92740F13E3 دیده باشید؛ NHibernate هم یک زمانی از همین Castle.Core برای تدارک پروکسیهای اشیاء استفاده میکرد. سربار آن در حین ایجاد چندین هزار وهله از یک شیء، در حد همان کار با ORMهایی است که هر روزه از آنها استفاده میکنید (اگر میخواهید یک حسی از این قضیه داشته باشید).
- تمام ORMها برای پیاده سازی مباحث Lazy loading یک شیء پروکسی را از شیء اصلی شما ایجاد میکنند. نمونهاش را شاید با EF Code first با نامهای خودکاری مانند ClassName_00394CF1F92740F13E3 دیده باشید؛ NHibernate هم یک زمانی از همین Castle.Core برای تدارک پروکسیهای اشیاء استفاده میکرد. سربار آن در حین ایجاد چندین هزار وهله از یک شیء، در حد همان کار با ORMهایی است که هر روزه از آنها استفاده میکنید (اگر میخواهید یک حسی از این قضیه داشته باشید).
اشتراکها
من عاشق Entity Framework هستم !
There is quite a bit of Entity Framework and NHibernate comparisons on
the web already but all of them cover mostly the technical side of the
question. In this post, I’ll compare these two technologies from
a Domain Driven Design perspective. I’ll step through several code
examples and show you how both of these ORMs let you deal with problems.
نظرات مطالب
معرفی DNTProfiler
با سلام و تشکر به خاطر این نرم افزار مفید.
نرم افزار و پکتهای اون برای EntityFramework در دو حالت وب و ویندوز درست عمل میکند ولی برای NHibernate فقط در حالت ویندوزی درست عمل میکند و در حالت وبی، موقع فراخوانی BuildSessionFactory به اکسپشن زیر برخورد میکنم:
نرم افزار و پکتهای اون برای EntityFramework در دو حالت وب و ویندوز درست عمل میکند ولی برای NHibernate فقط در حالت ویندوزی درست عمل میکند و در حالت وبی، موقع فراخوانی BuildSessionFactory به اکسپشن زیر برخورد میکنم:
Could not create the driver from DNTProfiler.NHibernate.Core.Drivers.ProfiledSql2008ClientDriver,DNTProfiler.NHibernate.Core
و بعد از لود صفحهی وب اکسپشن زیر نمایش داده میشود:
exePath must be specified when not running inside a stand alone exe
با سرچی که انجام دادم به نظر میرسد به پکت نیوگت NHibenate این نرم افزار و نحوهی کار با Configuration manager در کانتکست وبی و ویندوزی مربوط باشد.
با سرچی که انجام دادم به نظر میرسد به پکت نیوگت NHibenate این نرم افزار و نحوهی کار با Configuration manager در کانتکست وبی و ویندوزی مربوط باشد.
نظرات مطالب
نرمال سازی (قسمت اول: First Normal Form)
با تشکر از مطلب خوبتان.
این نوع مباحث رو با ormها و کلاسهای دات نتی بهتر میشه توضیح داد. مثلا یک مشتری داریم با چندتا تلفن. یک دانشجو داریم با چندتا ترم و درس و نمره. این چندتا رو میشه به صورت یک icollection تعریف کرد در یک کلاس بجای اینکه پشت سر هم خاصیت اضافه کنیم. یا حتی زمانیکه مشتری سه تا تلفن داره مشکلی نداره تمامش در همان جدول اصلی قرار بگیره. در ef به این نوعها، complextype گفته میشه (یک خاصیت تو در تو در کلاس، حالتیکه خاصیت کلاس خودش از نوع یک کلاس هست اما این کلاس تبدیل به یک جدول جدا نمیشه) یا مثلا در nhibernate به اون component mapping هم میگن.