نظرات مطالب
خواندنی‌های 25 اردیبهشت
1 - خیر. jQuery یک کتابخانه اسکریپتی است و کاری با محتوای سایت شما ندارد مگر اینکه خودتان بر اساس آن تغییری را اعمال کنید.
2 - بله. همین برچسب‌هایی را که ملاحظه می‌کنید، کلمات کلیدی مورد نظر شما هستند.
3- یک ویجت از نوع فید اضافه کنید. سپس آدرس فید کامنت‌های سایت را به آن بدهید (هر سایت حداقل دو فید دارد، فید مطالب و فید نظرات). اکنون لیست آخرین 5 نظر ارائه شده را خواهید داشت.
4 و 5 - اگر با این دو مورد مشکل دارید توصیه می‌کنم از windows live writer استفاده کنید که با بلاگر هم سازگار است:
http://baghbanbashi.blogspot.com/2009/01/live-writer-2009-features.html
http://baghbanbashi.blogspot.com/2006/12/windows-live-writer.html
پاسخ به بازخورد‌های پروژه‌ها
درخواست راهنمایی سیستم Decision
آقا خیلی ممنون از لینکهایی که دادین .
خلاصه کاری که برای اضافه کردن کلاس جدید مدل لازم بود:
1- کامنت کردن خط زیر
 //Database.SetInitializer<ApplicationDbContext>(null);
و فعال کردن کد زیر بجای بالایی
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, DataLayer.Migrations.Configuration>());
2- فایل کانفیگ بهمان شکل اول باقی می‌ماند یعنی
public Configuration()
        {         
            AutomaticMigrationsEnabled = false;
            AutomaticMigrationDataLossAllowed = false;           
        }   
3- تغییرات لازم روی مدلها و یا اضافه کردن کلاسهای POCO جدید به همراه کانفیگشان انجام شود
4- با فرمان زیر فایل migration جدید برای تغییراتمان ایجاد می‌کنیم
add-migrations firstchange
5- و با فرمان Update-Database -Verbose  تغییرات روی بانک اعمال می‌شود
اشتراک‌ها
15 درس هنگام مهاجرت به .NET Core
1. Using xproj & csproj files together
2. Building for deployment
3. NetStandard vs NetCoreApp1.0
4. IIS is dead, well sort of
5. HttpModules and HttpHandlers are replaced by new “middleware”
6. FileStream moved to System.IO.FileSystem ???
7. StreamReader constructor no longer works with a file path
8. Platform specific code… like Microsoft specific RSA
9. Newtonsoft changed to default to camel case on field names 🙁
10. Log4net doesn’t work and neither do countless other dependencies, unless you target .NET 4.5!
11. System.Drawing doesn’t exist
12. DataSet and DataTable doesn’t exist
13. Visual Studio Tooling
14. HttpWebRequest weird changes
15. Creating a Windows Service in .NET Core 
15 درس هنگام مهاجرت به .NET Core
مطالب
محدود سازی نرخ دسترسی به منابع در برنامه‌های ASP.NET Core - قسمت اول - بررسی مفاهیم
به ASP.NET Core 7، یک میان‌افزار جدید به نام Rate limiter اضافه شده‌است که امکان محدود سازی دسترسی به منابع برنامه‌ی ما را میسر می‌کند. این میان‌افزار، طراحی جامع و مفصلی را دارد. به همین جهت نیاز است در ابتدا با مفاهیم مرتبط با آن آشنا شد و سپس به سراغ پیاده سازی و استفاده‌ی از آن رفت.


چرا باید میزان دسترسی به منابع یک برنامه‌ی وب را محدود کرد؟

فرض کنید در حال ساخت یک web API هستید که کارش ذخیره سازی لیست وظایف اشخاص است و برای مثال از یک GET /api/todos برای دریافت لیست ظایف، یک POST /api/todos برای ثبت و یک PUT /api/todos/{id} برای تغییر موارد ثبت شده، تشکیل می‌شود.
سؤال: چه مشکلی ممکن است به همراه این سه endpoint بروز کند؟
پاسخ: به حداقل چهار مورد زیر می‌توان اشاره کرد:
- یک مهاجم سعی می‌کند با برنامه‌ای که تدارک دیده، هزاران وظیفه‌ی جدید را در چند ثانیه به سمت برنامه ارسال کند تا سبب خاتمه‌ی سرویس آن شود.
- برنامه‌ی ما در حین سرویس دهی، به یک سرویس ثالث نیز وابسته‌است و آن سرویس ثالث، اجازه‌ی استفاده‌ی بیش از اندازه‌ی از منابع خود را نمی‌دهد. با رسیدن تعداد زیادی درخواست به برنامه‌ی ما تنها از طرف یک کاربر، به سقف مجاز استفاده‌ی از آن سرویس ثالث رسیده‌ایم و اکنون برنامه، برای تمام کاربران آن قابل استفاده نیست.
- شخصی در حال دریافت اطلاعات تک تک کاربران است. از شماره یک شروع کرده و به همین نحو جلو می‌رود. برای دریافت اطلاعات کاربران، نیاز است شخص به سیستم وارد شده و اعتبارسنجی شود؛ یعنی به ازای هر درخواست، یک کوئری نیز به سمت بانک اطلاعاتی جهت بررسی وضعیت فعلی و آنی کاربر ارسال می‌شود. به همین جهت عدم کنترل میزان دسترسی به لیست اطلاعات کاربران، بار سنگینی را به بانک اطلاعاتی و CPU سیستم وارد می‌کند.
- هم اکنون چندین موتور جستجو و بات‌هایی نظر آن‌ها در حال پیمایش سایت و برنامه‌ی شما هستند که هر کدام از آن‌ها می‌توانند در حد یک مهاجم رفتار کنند.

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


محدود کردن نرخ دسترسی به برنامه چیست؟

Rate limiting و یا نام دیگر آن request throttling، روشی است که توسط آن بتوان از الگوهای پیش بینی نشده‌ی استفاده‌ی از برنامه جلوگیری کرد. عموما برنامه‌های وب، محدود کردن نرخ دسترسی را بر اساس تعداد بار درخواست انجام شده‌ی در یک بازه‌ی زمانی مشخص، انجام می‌دهند و یا اگر کار برنامه‌ی شما ارائه‌ی فیلم‌های ویدیویی است، شاید بخواهید میزان حجم استفاده شده‌ی توسط یک کاربر را کنترل کنید. در کل هدف نهایی از آن، کاهش و به حداقل رساندن روش‌های آسیب زننده‌ی به برنامه و سیستم است؛ صرفنظر از اینکه این نحوه‌ی استفاده‌ی خاص، سهوی و یا عمدی باشد.


محدود کردن نرخ دسترسی را باید به چه منابعی اعمال کرد؟

پاسخ دقیق به این سؤال: «همه چیز» است! بله! همه چیز را کنترل کنید! در اینجا منظور از همه چیز، همان endpointهایی هستند که استفاده‌ی نابجای از آن‌ها می‌توانند سبب کند شدن برنامه یا از دسترس خارج شدن آن شوند. برای مثال هر endpoint‌ای که از CPU، حافظه، دسترسی به دیسک سخت، بانک اطلاعاتی، APIهای ثالث و خارجی و امثال آن استفاده می‌کند، باید کنترل و محدود شود تا استفاده‌ی ناصحیح یک کاربر از آن‌ها، استفاده‌ی از برنامه را برای سایر کاربران غیرممکن نکند. البته باید دقت داشت که هدف از اینکار، عصبی کردن کاربران عادی و معمولی برنامه نیست. هدف اصلی در اینجا، تشویق به استفاده‌ی منصفانه از منابع سیستم است.


الگوریتم‌های محدود کردن نرخ دسترسی

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

الگوریتم‌های بازه‌ی زمانی مشخص

در این روش، یک شمارشگر در یک بازه‌ی زمانی مشخص فعال می‌شود و بر این مبنا است که محدودیت‌ها اعمال خواهند شد. یک مثال آن، مجاز دانستن فقط «100 درخواست در یک دقیقه» است که نام دیگر آن «Quantized buckets / Fixed window limit» نیز هست.
برای مثال «نام هر اکشن + یک بازه‌ی زمانی»، یک کلید دیکشنری نگهدارنده‌ی اطلاعات محدود کردن نرخ دسترسی خواهد بود که به آن کلید، «bucket name» هم می‌گویند؛ مانند مقدار someaction_106062120. سپس به ازای هر درخواست رسیده، شمارشگر مرتبط با این کلید، یک واحد افزایش پیدا می‌کند و محدود کردن دسترسی‌ها بر اساس مقدار این کلید صورت می‌گیرد. در ادامه با شروع هر بازه‌ی زمانی جدید که در اینجا window نام دارد، یک کلید یا همان «bucket name» جدید تولید شده و مقدار متناظر با این کلید، به صفر تنظیم می‌شود.
اگر بجای دیکشنری‌های #C از بانک اطلاعاتی Redis برای نگهداری این key/valueها استفاده شود، می‌توان برای هر کدام از مقادیر آن، طول عمری را نیز مشخص کرد تا خود Redis، کار حذف خودکار اطلاعات غیرضروری را انجام دهد.

یک مشکل الگوریتم‌های بازه‌ی زمانی مشخص، غیر دقیق بودن آن‌ها است. برای مثال فرض کنید که به ازای هر 10 ثانیه می‌خواهید تنها اجازه‌ی پردازش 4 درخواست رسیده را بدهید. مشکل اینجا است که در این حالت یک کاربر می‌تواند 5 درخواست متوالی را بدون مشکل ارسال کند؛ 3 درخواست را در انتهای بازه‌ی اول و دو درخواست را در ابتدای بازه‌ی دوم:


به یک بازه‌ی زمانی مشخص، fixed window و به انتها و ابتدای دو بازه‌ی زمانی مشخص متوالی، sliding window می‌گویند. همانطور که در تصویر فوق هم مشاهده می‌کنید، در این اگوریتم، امکان محدود سازی دقیقی تنها در یک fixed window میسر است و نه در یک sliding window.

سؤال: آیا این مساله عدم دقت الگوریتم‌های بازه‌ی زمانی مشخص مهم است؟
پاسخ: بستگی دارد! اگر هدف شما، جلوگیری از استفاده‌ی سهوی یا عمدی بیش از حد از منابع سیستم است، این مساله مشکل مهمی را ایجاد نمی‌کند. اما اگر دقت بالایی را انتظار دارید، بله، مهم است! در این حالت از الگوریتم‌های «sliding window limit » بیشتر استفاده می‌شود که در پشت صحنه از همان روش استفاده‌ی از چندین fixed window کوچک، کمک می‌گیرند.


الگوریتم‌های سطل توکن‌ها (Token buckets)

در دنیای مخابرات، از الگوریتم‌های token buckets جهت کنترل میزان مصرف پهنای باند، زیاد استفاده می‌شود. از واژه‌ی سطل در اینجا استفاده شده، چون عموما به همراه آب بکارگرفته می‌شود:
فرض کنید سطل آبی را دارید که در کف آن نشتی دارد. اگر نرخ پر کردن این سطل، با آب، از نرخ نشتی کف آن بیشتر باشد، آب از سطل، سرریز خواهد شد. به این معنا که با سرریز توکن‌ها یا آب در این مثال، هیچ درخواست جدید دیگری پردازش نمی‌شود؛ تا زمانیکه مجددا سطل، به اندازه‌ای خالی شود که بتواند توکن یا آب بیشتری را بپذیرد.

یکی از مزیت‌های این روش، نداشتن مشکل عدم دقت به همراه بازه‌های زمانی مشخص است. در اینجا اگر تعداد درخواست زیادی به یکباره به سمت برنامه ارسال شوند، سطل پردازشی آن‌ها سرریز شده و دیگر پردازش نمی‌شوند.
مزیت دیگر آن‌ها، امکان بروز انفجاری یک ترافیک (bursts in traffic) نیز هست. برای مثال اگر قرار است سطلی با 60 توکن در دقیقه پر شود و این سطل نیز هر ثانیه یکبار تخلیه می‌شود، کلاینت‌ها هنوز می‌توانند 60 درخواست را در طی یک ثانیه ارسال کنند (ترافیک انفجاری) و پس از آن نرخ پردازشی، یک درخواست به ازای هر ثانیه خواهد شد.


آیا باید امکان بروز انفجار در ترافیک را داد؟

عموما در اکثر برنامه‌ها وجود یک محدود کننده‌ی نرخ دسترسی کافی است. برای مثال یک محدود کننده‌ی نرخ دسترسی سراسری 600 درخواست در هر دقیقه، برای هر endpoint ای شاید مناسب باشد. اما گاهی از اوقات نیاز است تا امکان بروز انفجار در ترافیک (bursts) را نیز درنظر گرفت. برای مثال زمانیکه یک برنامه‌ی موبایل شروع به کار می‌کند، در ابتدای راه اندازی آن تعداد زیادی درخواست، به سمت سرور ارسال می‌شوند و پس از آن، این سرعت کاهش پیدا می‌کند. در این حالت بهتر است چندین محدودیت را تعریف کرد: برای مثال امکان ارسال 10 درخواست در هر ثانیه و حداکثر 3600 درخواست در هر ساعت.


روش تشخیص کلاینت‌ها چگونه باشد؟

تا اینجا در مورد bucket name یا کلید دیکشنری اطلاعات محدود کردن دسترسی به منابع، از روش «نام هر اکشن + یک بازه‌ی زمانی» استفاده کردیم. به این کار «پارتیشن بندی درخواست‌ها» هم گفته می‌شود. روش‌های دیگری نیز برای انجام اینکار وجود دارند:
پارتیشن بندی به ازای هر
- endpoint
- آدرس IP. البته باید دقت داشت که کاربرانی که در پشت یک پروکسی قرار دارند، از یک IP آدرس اشتراکی استفاده می‌کنند.
- شماره کاربری. البته باید در اینجا بحث کاربران اعتبارسنجی نشده و anonymous را نیز مدنظر قرار داد.
- شمار سشن کاربر. در این حالت باید بحث ایجاد سشن‌های جدید به ازای دستگاه‌های مختلف مورد استفاده‌ی توسط کاربر را هم مدنظر قرار داد.
- نوع مروگر.
- هدر ویژه رسیده مانند X-Api-Token

بسته به نوع برنامه عموما از ترکیبی از موارد فوق برای پارتیشن بندی درخواست‌های رسیده استفاده می‌شود.


درنظر گرفتن حالت‌های استثنائی

هرچند همانطور که عنوان شد تمام قسمت‌های برنامه باید از لحاظ میزان دسترسی محدود شوند، اما استثناءهای زیر را نیز باید درنظر گرفت:
- عموما تیم مدیریتی یا فروش برنامه، بیش از سایر کاربران، با برنامه کار می‌کنند.
- بیش از اندازه محدود کردن Web crawlers می‌تواند سبب کاهش امتیاز SEO سایت شما شود.
- گروه‌های خاصی از کاربران برنامه نیز می‌توانند دسترسی‌های بیشتری را خریداری کنند.


نحوه‌ی خاتمه‌ی اتصال و درخواست

اگر کاربری به حد نهایی استفاده‌ی از منابع خود رسید، چه باید کرد؟ آیا باید صرفا درخواست او را برگشت زد یا اطلاعات بهتری را به او نمایش داد؟
برای مثال GitHub یک چنین خروجی را به همراه هدرهای ویژه‌ای جهت مشخص سازی وضعیت محدود سازی دسترسی به منابع و علت آن‌، ارائه می‌دهد:
> HTTP/2 403
> Date: Tue, 20 Aug 2013 14:50:41 GMT
> x-ratelimit-limit: 60
> x-ratelimit-remaining: 0
> x-ratelimit-used: 60
> x-ratelimit-reset: 1377013266
> {
> "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
> "documentation_url": "https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"
> }
بنابراین بسته به نوع خروجی برنامه که اگر خروجی آن یک API از نوع JSON است و یا یک صفحه‌ی HTML، می‌توان از ترکیبی از هدرها و اطلاعات متنی و HTML استفاده کرد.
حتی یکسری از APIها از status codeهای ویژه‌ای مانند 403 (دسترسی ممنوع)، 503 (سرویس در دسترس نیست) و یا 429 (تعداد درخواست‌های زیاد) برای پاسخ دهی استفاده می‌کنند.



محل ذخیره سازی اطلاعات محدود سازی دسترسی به منابع کجا باشد؟

اگر محدودسازی دسترسی به منابع، جزئی از مدل تجاری برنامه‌ی شما است، نیاز است حتما از یک بانک اطلاعاتی توزیع شده مانند Redis استفاده کرد تا بتواند اطلاعات تمام نمونه‌های در حال اجرای برنامه را پوشش دهد. اما اگر هدف از این محدود سازی تنها میسر ساختن دسترسی منصفانه‌ی به منابع آن است، ذخیره سازی آن‌ها در حافظه‌ی همان نمونه‌ی در حال اجرای برنامه هم کافی است.
اشتراک‌ها
معرفی فریم‌ورک FAST مایکروسافت

What is FAST?

FAST is a collection of technologies built on Web Components and modern Web Standards, designed to help you efficiently tackle some of the most common challenges in website and application design and development.


What are Web Components?

"Web Components" is an umbrella term that refers to a collection of web standards focused on enabling the creation of custom HTML elements. Some of the standards that are under the umbrella include the ability to define new HTML tags, plug into a standard component lifecycle, encapsulate HTML rendering and CSS, parameterize CSS, skin components, and more. Each of these platform features is defined by the W3C and has shipped in every major browser today. 


ASP.NET Community Standup - July 7, 2020 - FAST Framework  

معرفی فریم‌ورک FAST مایکروسافت
اشتراک‌ها
خاصیت background-clip و نحوه استفاده از آن

background-clip is one of those properties I've known about for years, but rarely used. Maybe just a couple of times as part of a solution to a Stack Overflow question. Until last year, when I started creating my huge collection of sliders. Some of the designs I chose to reproduce were a bit more complex and I only had one element available per slider, which happened to be an input element, meaning that I couldn't even use pseudo-elements on it. Even though that does work in certain browsers, the fact that it works is actually a bug and I didn't want to rely on that. All this meant I ended up using backgrounds, borders, and shadows a lot. I also learned a lot from doing that and this article shares some of those lessons.  

خاصیت background-clip و نحوه استفاده از آن
اشتراک‌ها
Rider EAP 20 منتشر شد.

Rider EAP 20 fixes a number of bugs, improves .NET Core support, has better NuGet performance, supports Xamarin Android applications, comes with Node.js tooling from WebStorm (including SpyJS), can generate ResX files, executes T4 templates (needs Windows and Visual Studio SDK), adds support for scratch files, … Too much for one sentence, as you can see from the full list of fixes. We’ll highlight a few, read on! 

Rider EAP 20 منتشر شد.
مطالب
اصول طراحی شیء گرا: OO Design Principles

قصد دارم مجموعه ای کامل از اصول طراحی شیء گرا، الگوهای طراحی و best practice ‌های مربوطه را ارائه دهم. از این رو ابتدا با اصول طراحی شروع می‌کنم. سپس در مقالات آتی به الگوهای مختلف خواهم پرداخت و تا جایی که معلومات اجازه دهد مشخص خواهم کرد که هر الگو متمرکز بر رعایت کدام یک از اصول است و اینکه آیا مناسب است از الگوی مورد نظر استفاده کنیم.

این مطالب نیز چکیده ای از آموزش‌های Lynda, Pluralsight , SkillFeed  و کتاب های Gang of four, Headfirst Design patterns  و ... میباشد


اصل اول: Encapsulate what varies

"آنچه را که تغییر می‌کند مشخص و جدا کن یا به عبارتی آنرا کپسوله کن"

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


اصل دوم: Program to an interface not implementation

" برنامه نویسی را متمرکز بر واسط کن، نه نحوه‌ی پیاده سازی "

برای این اصل تعابیر مختلفی ارائه شده است:

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

برای رعایت این اصل باید:

  • سعی بر تعریف واسط برای اکثر کلاس‌ها کنیم
  • اشیا را از نوع واسط تعریف کنیم، نه کلاس‌های پیاده ساز آن

در کد زیر نحوه‌ی تعریف واسط را برای کلاس و تعریف اشیاء از نوع واسط را میبینیم: 

    public interface IMyInterface
    {
        void DoWork();
    }

    public class MyImplementation1 : IMyInterface
    {
        public void DoWork()
        {
            var implementationName = this.GetType().ToString();
            Console.WriteLine("DoWork from " + implementationName);
        }
    }
    public class MyImplementation2 : IMyInterface
    {
        public void DoWork()
        {
            var implementationName = this.GetType().ToString();
            Console.WriteLine("DoWork from " + implementationName);
        }
    }

    public class Context
    {
        IMyInterface myInterface;

        public void Print() 
        {
            myInterface = new MyImplementation1();
            myInterface.DoWork();

            myInterface = new MyImplementation2();
            myInterface.DoWork();
        }
    }


اصل سوم: Favor composition over inheritance

"ترکیب را بر توارث ترجیح بده"

رابطه "دارد" (has a ) انعطاف بیشتری نسبت به ارث بری یا "از نوع ... هست" ( is a ) دارد. برای مثال فرض کنید کلاس Enemy رفتار Movable را دارد و این رفتار در طول بازی بر حسب موقعیتی تغییر میکند. اگر این رفتار را با توارث مدل کنیم، یعنی Enemy از نوع Movable باشد، آنگاه برای هر نوع رفتار Movable (هر نوع پیاده سازی) باید یک نوع Enemy داشته باشیم و تصور کنید بعضی از این پیاده سازی‌ها در کلاس Player یکسان باشد. آنگاه کد باید دوباره تکرار شود. حال تصور کنید این موقعیت را با ترکیب مدل کنیم. آنگاه کلاس Enemy یک شیء از جنس Movable خواهد داشت و در زمان نیاز میتواند نوع این رفتار را با نمونه گیری از کلاس‌های پیاده ساز آن، تغییر دهد. در واقع با اینکار اصل اول را رعایت کرده ایم و بخش ثابت را از بخش متغیر جدا نموده ایم.

در زیر مدلسازی با توارث را میبینیم: 

public interface Movable
    {
        void Move();
    }
    public class EnemyBase : Movable
    {
        // Enemy properties goes here
        protected int x, y;
        public virtual void Move()
        {
            x += 2;
            y += 2;
        }
    }
    public class EnemyWithMoveType2 : EnemyBase
    {
        // override the move method
        public override void Move()
        {
            x += 4;
            y += 4;
        }
    }
    public class EnemyWithMoveType3 : EnemyBase
    {
        // override the move method
        public override void Move()
        {
            x += 6;
            y += 6;
        }
    }
    public class PlayerBase : Movable
    {
        // Player properties goes here
        protected int x, y;
        public  virtual void Move()
        {
            // same code as EnemyBase move method
            x += 2;
            y += 2;
        }
    }
    public class PlayerWithMoveType2 : PlayerBase
    {
        // override the move method
        public override void Move()
        {
            // same code as EnemyWithMoveType2 move method
            x += 4;
            y += 4;
        }
    }
    public class PlayerWithMoveType3 : PlayerBase
    {
        // override the move method
        public override void Move()
        {
            // same code as EnemyWithMoveType3 move method
            x += 6;
            y += 6;
        }
    }  

در ادامه نیز مدلسازی با ترکیب را میبینیم: 

     public interface IMovable
    {
        void Move(ref int x, ref int y);
    }
    public class EnemyBase
    {
        // Enemy properties goes here
        protected int x, y;
        IMovable moveBehavior;
        public void SetMoveBehavior(IMovable _moveBehavior) { moveBehavior = _moveBehavior; }
        public void Move()
        {
            moveBehavior.Move(ref x,ref y);
        }
    }
    public class PlayerBase
    {
        // Player properties goes here
        protected int x, y;
        IMovable moveBehavior;
        public void SetMoveBehavior(IMovable _moveBehavior) { moveBehavior = _moveBehavior; }
        public void Move()
        {
            moveBehavior.Move(ref x, ref y);
        }
    }
    public class MoveBehavior1
    {
        public void Move(ref int x, ref int y)
        {
            x += 2;
            y += 2;
        }
    }
    public class MoveBehavior2 : IMovable
    {
        public void Move(ref int x, ref int y)
        {
            x += 4;
            y += 4;
        }
    }
    public class MoveBehavior3 : IMovable
    {
        public void Move(ref int x, ref int y)
        { 
            x += 6;
            y += 6;
        }
    }  

همانطور که میبینید، با فراخوانی تابع SetMoveBehavior میتوان رفتار را در زمان اجرا تغییر داد.

در مقاله‌ی بعدی به ادامه‌ی اصول خواهم پرداخت. از شنیدن نظرات و سوالات شما خرسند خواهم شد.

اشتراک‌ها
بررسی (CLI) جدید دات نت

Command Line Interface 

I've never much like the whole "dnvm" and "dnu" and "dnx" command line stuff in the new ASP.NET 5 beta bits. There's reasons for each to exist and they were and they have been important steps, both organizationally and as aids to the learning process. 

بررسی (CLI) جدید دات نت
اشتراک‌ها
مصاحبه‌ای با Linus Torvalds در مورد استفاده از Rust در هسته‌ی لینوکس

Linus Torvalds talks AI, Rust adoption, and why the Linux kernel is 'the only thing that matters'

Switching to a more modern topic, the introduction of the Rust language into Linux, Torvalds is disappointed that its adoption isn't going faster. "I was expecting updates to be faster, but part of the problem is that old-time kernel developers are used to C and don't know Rust. They're not exactly excited about having to learn a new language that is, in some respects, very different. So there's been some pushback on Rust."

مصاحبه‌ای با Linus Torvalds در مورد استفاده از Rust در هسته‌ی لینوکس