یقینا سرعت کار با بانکهای اطلاعاتی رابطهای و امکانات توکار آنها همیشه بیشتر از کار با XML و هر حالت مشابه دیگری در آنهاست و بنابراین ... بله. حالت دوم بهینهتر نیست، سریعتر نیست و همچنین کمحجمتر هم نیست. اساسا بانکهای اطلاعاتی رابطهای زمانی طراحی شدند که یک هارد دیسک 4 مگابایتی، چندهزار دلار قیمت داشت. به همین جهت در زمینه ذخیره سازی اطلاعات، بسیار بهینه و کمحجم عمل میکنند؛ با حداقل تکرار و سربار و با سرعت بالا. استفاده از XML و JSON امثال اینها زمانی باب شدند که قیمت هارد دیسکهای حجیم کاهش یافته بود و همچنین بیشتر سرعت read مطرح بود و نه سرعت write. اطلاعات بیشتر
واژه XSS مخفف Cross-site scripting، نوعی از آسیب پذیریست که در برنامههای تحت وب نمود پیدا میکند. به طور کلی و خلاصه، این آسیب پذیری به فرد نفوذ کننده اجازه تزریق اسکریپتهایی را به صفحات وب، میدهد که در سمت کاربر اجرا میشوند ( Client Side scripts ) . در نهایت این اسکریپتها توسط سایر افرادی که از صفحات مورد هدف قرار گرفته بازدید میکنند اجرا خواهد شد.
هدف از این نوع حمله :
بدست آوردن اطلاعات کوکیها و سشنهای کاربران ( مرتبط با آدرسی که صفحه آلوده شده در آن قرار دارد ) است. سپس فرد نفوذ کننده متناسب با اطلاعات بدست آمده میتواند به اکانت شخصی کاربران مورد هدف قرار گرفته، نفوذ کرده و از اطلاعات شخصی آنها سوء استفاده کند .
به صورت کلی دو طبقه بندی برای انواع حملات Cross-site scripting وجود دارند.
حملات XSS ذخیره سازی شده ( Stored XSS Attacks ) :
در این نوع ، کدهای مخرب تزریق شده، در سرور سایت قربانی ذخیره میشوند. محل ذخیره سازی میتواند دیتابیس سایت یا هر جای دیگری که دادهها توسط سایت یا برنامه تحت وب بازیابی میشوند و نمایش داده میشوند باشد. اما اینکه چگونه کدهای مخرب در منابع یاد شده ذخیره میشوند؟
فرض کنید در سایت جاری آسیب پذیری مذکور وجود دارد. راههای ارسال دادهها به این سایت چیست؟ نویسندگان میتوانند مطلب ارسال کنند و کاربران میتوانند نظر دهند. حال اگر در یکی از این دو بخش بررسیهای لازم جهت مقابله با این آسیب پذیری وجود نداشته باشد و نوشتههای کاربران که میتواند شامل کدهای مخرب باشد مستقیما در دیتابیس ذخیره شده و بدون هیچ اعتبار سنجی نمایش داده شود چه اتفاقی رخ خواهد داد؟ مسلما با بازدید صفحه آلوده شده، کدهای مخرب بر روی مرورگر شما اجرا و کوکیهای سایت جاری که متعلق به شما هستند برای هکر ارسال میشود و ...
حملات XSS منعکس شده ( Reflected XSS Attacks ) :
در این نوع از حمله، هیچ نوع کد مخربی در منابع ذخیره سازی وبسایت یا اپلیکیشن تحت وب توسط فرد مهاجم ذخیره نمیشود ! بلکه از ضعف امنیتی بخشهایی همچون بخش جستجو وب سایت، بخشهای نمایش پیغام خطا و ... استفاده میشود ... اما به چه صورت؟
در بسیاری از سایتها، انجمنها و سیستمهای سازمانی تحت وب، مشاهده میشود که مثلا در بخش جستجو، یک فیلد برای وارد کردن عبارت جستجو وجود دارد. پس از وارد کردن عبارت جستجو و submit فرم، علاوه بر نمایش نتایج جستجو، عبارت جستجو شده نیز به نمایش گذاشته میشود و بعضا در بسیاری از سیستمها این عبارت قبل از نمایش اعتبار سنجی نمیشود که آیا شامل کدهای مخرب میباشد یا خیر. همین امر سبب میشود تا اگر عبارت جستجو شامل کدهای مخرب باشد، آنها به همراه نتیجهی جستجو اجرا شوند.
اما این موضوع چگونه مورد سوء استفاده قرار خواهد گرفت؟ مگر نه اینکه این عبارت ذخیره نمیشود پس با توضیحات فوق، کد فقط بر روی سیستم مهاجم که کد جستجو را ایجاد میکند اجرا میشود، درست است؟ بله درست است ولی به نقطه ضعف زیر توجه کنید ؟
www.test.com/search?q=PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpOzwvc2NyaXB0Pg==
این آدرس حاصل submit شدن فرم جستجو وبسایت test (نام وبسایت واقعی نیست و برای مثال است ) و ارجاع به صفحه نتایج جستجو میباشد. در واقع این لینک برای جستجوی یک کلمه یا عبارت توسط این وبسایت تولید شده و از هر کجا به این لینک مراجعه کنید عبارت مورد نظر مورد جستجو واقع خواهد شد. در واقع عبارت جستجو به صورت Base64 به عنوان یک query String به وبسایت ارسال میشود؛ علاوه بر نمایش نتایج، عبارت جستجو شده نیز به کاربر نشان داده شده و اگر آسیب پذیری مورد بحث وجود داشته باشد و عبارت شامل کدهای مخرب باشد، کدهای مخرب بر روی مرورگر فردی که این لینک را باز کرده اجرا خواهد شد!
در این صورت کافیست فرد مهاجم لینک مخرب را به هر شکلی به فرد مورد هدف بدهد ( مثلا ایمیل و ... ). حال در صورتیکه فرد لینک را باز کند (با توجه به اینکه لینک مربوط به یک سایت معروف است و عدم آگاهی کاربر از آسیب پذیری موجود در لینک، باعث باز کردن لینک توسط کاربر میشود)، کدها بر روی مرورگرش اجرا شده و کوکیهای سایت مذکور برای مهاجم ارسال خواهد شد ... به این نوع حمله XSS ، نوع انعکاسی میگویند که کاملا از توضیحات فوق الذکر، دلیل این نامگذاری مشخص میباشد.
اهمیت مقابله با این حمله :
برای نمونه این نوع باگ حتی تا سال گذشته در سرویس ایمیل یاهو وجود داشت. به شکلی که یکی از افراد انجمن hackforums به صورت Private این باگ را به عنوان Yahoo 0-Day XSS Exploit در محیط زیر زمینی و بازار سیاه هکرها به مبلغ چند صد هزار دلار به فروش میرساند. کاربران مورد هدف کافی بود تا فقط یک ایمیل دریافتی از هکر را باز کنند تا کوکیهای سایت یاهو برای هکر ارسال شده و دسترسی ایمیلهای فرد قربانی برای هکر فراهم شود ... ( در حال حاظر این باگ در یاهو وجو ندارد ).
چگونگی جلوگیری از این آسیب پذیری
در این سری از مقالات کدهای پیرامون سرفصلها و مثالها با ASP.net تحت فریم ورک MVC و به زبان C# خواهند بود. هر چند کلیات مقابله با آسیب پذیری هایی از این دست در تمامی زبانها و تکنولوژیهای تحت وب یکسان میباشند.
خوشبختانه کتابخانهای قدرتمند برای مقابله با حمله مورد بحث وجود دارد با نام AntiXSS که میتوانید آخرین نسخه آن را با فرمان زیر از طریق nugget به پروژه خود اضافه کنید. البته ذکر این نکته حائز اهمیت است که Asp.net و فریم ورک MVC به صورت توکار تا حدودی از بروز این حملات جلوگیری میکند. برای مثال به این صورت که در View ها شما تا زمانی که از MvcHtmlString استفاده نکنید تمامی محتوای مورد نظر برای نمایش به صورت Encode شده رندر میشوند. این داستان برای Url ها هم که به صورت پیش فرض encode میشوند صدق میکند. ولی گاها وقتی شما برای ورود اطلاعات مثلا از یک ادیتور WYSWYG استفاده میکنید و نیاز دارید دادهها را بدون encoding رندر کنید. آنگاه به ناچار مجاب بر اعمال یک سری سیاستهای خاصتر بر روی داده مورد نظر برای رندر میشوید و نمیتوانید از encoding توکار فوق الذکر استفاده کنید. آنگاه این کتابخانه در اعمال سیاستهای جلوگیری از بروز این آسیب پذیری میتواند برای شما مفید واقع شود.
PM> Install-Package AntiXSS
… var reviewContent = model.UserReview; reviewContent = Microsoft.Security.Application.Encoder.HtmlEncode(review); …
امیدوارم در اولین بخش از این سری مقالات، به صورت خلاصه مطالب مهمی که باعث ایجاد فهم کلی در رابطه با حملات Xss وجود دارد، برای دوستان روشن شده و پیش زمینه فکری برای مقابله با این دست از حملات برایتان به وجود آمده باشد.
Owin چیست ؟ قسمت اول
بانک اطلاعاتی InfluxDB یکی از انواع بانکهای اطلاعات NoSQL و مدل Time Series هست که برای مدیریت دادههای سری زمانی بهینه شده است و هر ورودی با یک مهر زمانی مرتبط است.
محیط مدیریتی برای این بانک اطلاعاتی بعد از نصب از روی یک آدرس وب و با امکانات مفید در دسترس میباشد.
همچنین جهت کانکت شدن به این دیتابیس یک توکن بر اساس نام کاربری و پسوردی
که برای کاربر ساخته میشود تولید میشود که از محیط مدیریتی این بانک
اطلاعاتی بر روی وب قابل دسترس میباشد و برای اتصال از طریق دات نت از
همان توکن استفاده میکند
نمونه کد اتصال به این بانک اطلاعاتی در صفحه اول سایت influxdata.com در دسترس میباشد.
📌 مستندات جهت یادگیری پایگاه اطلاعاتی InfluxDB
همچنین از طریق نصب پکیج InfluxDB.Client امکان کوئری زدن و فیلتر کردن اطلاعات با دستورات Linq روی این پایگاه داده فراهم شده است.
جهت شروع استفاده از این بانک اطلاعاتی در دات نت میتوانید از لینک پیوست شروع به مطالعه فرمایید.
تصویر صفحه داشبورد تحت وب این دیتابیس
تصویر صفحه کار با دادهها و نمایش اطلاعات به صورت گرافهای متنوع در محیط مدیریتی این دیتابیس بر روی وب
نحوه تبدیل تاریخ میلادی به شمسی
using Persia; namespace Iris.Utilities.DateAndTime { public class DateAndTime { public static DateTime GetDateTime() { return DateTime.Now; } public static string ConvertToPersian(DateTime dateTime, string mod = "") { SolarDate solar = Calendar.ConvertToPersian(dateTime); return string.IsNullOrEmpty(mod) ? solar.ToString() : solar.ToString(mod); } } }
using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; namespace GSD.Globalization { /// <summary> /// <Publisher>http://www.Sayan.ir</Publisher> /// <Author>Maziar Rezaie</Author> /// </summary> public class PersianCulture : CultureInfo { private readonly Calendar cal; private readonly Calendar[] optionals; /// <summary> /// کد رو بخوان تا بفهمی /// </summary> /// <param name="cultureName">fa-IR</param> /// <param name="useUserOverride">true</param> /// <remarks>لطفا در هنگام استفاده به سایت سایان اشاره کنید.</remarks> public PersianCulture() : this("fa-IR", true) { } public PersianCulture(string cultureName, bool useUserOverride) : base(cultureName, useUserOverride) { //Temporary Value for cal. cal = base.OptionalCalendars[0]; //populating new list of optional calendars. var optionalCalendars = new List<Calendar>(); optionalCalendars.AddRange(base.OptionalCalendars); optionalCalendars.Insert(0, new PersianCalendar()); Type formatType = typeof(DateTimeFormatInfo); Type calendarType = typeof(Calendar); PropertyInfo idProperty = calendarType.GetProperty("ID", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo optionalCalendarfield = formatType.GetField("optionalCalendars", BindingFlags.Instance | BindingFlags.NonPublic); //populating new list of optional calendar ids var newOptionalCalendarIDs = new Int32[optionalCalendars.Count]; for (int i = 0; i < newOptionalCalendarIDs.Length; i++) newOptionalCalendarIDs[i] = (Int32)idProperty.GetValue(optionalCalendars[i], null); optionalCalendarfield.SetValue(DateTimeFormat, newOptionalCalendarIDs); optionals = optionalCalendars.ToArray(); cal = optionals[0]; DateTimeFormat.Calendar = optionals[0]; DateTimeFormat.MonthNames = new[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" }; DateTimeFormat.MonthGenitiveNames = new[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" }; DateTimeFormat.AbbreviatedMonthNames = new[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" }; DateTimeFormat.AbbreviatedMonthGenitiveNames = new[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" }; DateTimeFormat.AbbreviatedDayNames = new string[] { "ی", "د", "س", "چ", "پ", "ج", "ش" }; DateTimeFormat.ShortestDayNames = new string[] { "ی", "د", "س", "چ", "پ", "ج", "ش" }; DateTimeFormat.DayNames = new string[] { "یکشنبه", "دوشنبه", "ﺳﻪشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" }; DateTimeFormat.AMDesignator = "ق.ظ"; DateTimeFormat.PMDesignator = "ب.ظ"; /* DateTimeFormat.ShortDatePattern = "yyyy/MM/dd"; DateTimeFormat.LongDatePattern = "yyyy/MM/dd"; DateTimeFormat.SetAllDateTimePatterns(new[] {"yyyy/MM/dd"}, 'd'); DateTimeFormat.SetAllDateTimePatterns(new[] {"dddd, dd MMMM yyyy"}, 'D'); DateTimeFormat.SetAllDateTimePatterns(new[] {"yyyy MMMM"}, 'y'); DateTimeFormat.SetAllDateTimePatterns(new[] {"yyyy MMMM"}, 'Y'); */ } public override Calendar Calendar { get { return cal; } } public override Calendar[] OptionalCalendars { get { return optionals; } } } }
using GSD.Globalization; using System.Threading; protected void Application_BeginRequest(object sender, EventArgs e) { var persianCulture = new PersianCulture(); Thread.CurrentThread.CurrentCulture = persianCulture; Thread.CurrentThread.CurrentUICulture = persianCulture; }
Domain Model یا Business Layer
پیاده سازی را از منطق تجاری یا Business Logic آغاز میکنیم. در روش کد نویسی Smart UI، منطق تجاری در Code Behind قرار میگرفت اما در روش لایه بندی، منطق تجاری و روابط بین دادهها در Domain Model طراحی و پیاده سازی میشوند. در مطالب بعدی راجع به Domain Model و الگوهای پیاده سازی آن بیشتر صحبت خواهم کرد اما بصورت خلاصه این لایه یک مدل مفهومی از سیستم میباشد که شامل تمامی موجودیتها و روابط بین آنهاست.
الگوی Domain Model جهت سازماندهی پیچیدگیهای موجود در منطق تجاری و روابط بین موجودیتها طراحی شده است.
شکل زیر مدلی را نشان میدهد که میخواهیم آن را پیاده سازی نماییم. کلاس Product موجودیتی برای ارائه محصولات یک فروشگاه میباشد. کلاس Price جهت تشخیص قیمت محصول، میزان سود و تخفیف محصول و همچنین استراتژیهای تخفیف با توجه به منطق تجاری سیستم میباشد. در این استراتژی همکاران تجاری از مشتریان عادی تفکیک شده اند.
Domain Model را در پروژه SoCPatterns.Layered.Model پیاده سازی میکنیم. بنابراین به این پروژه یک Interface به نام IDiscountStrategy را با کد زیر اضافه نمایید:
public interface IDiscountStrategy { decimal ApplyExtraDiscountsTo(decimal originalSalePrice); }
علت این نوع نامگذاری Interface فوق، انطباق آن با الگوی Strategy Design Pattern میباشد که در مطالب بعدی در مورد این الگو بیشتر صحبت خواهم کرد. استفاده از این الگو نیز به این دلیل بود که این الگو مختص الگوریتم هایی است که در زمان اجرا قابل انتخاب و تغییر خواهند بود.
توجه داشته باشید که معمولا نام Design Pattern انتخاب شده برای پیاده سازی کلاس را بصورت پسوند در انتهای نام کلاس ذکر میکنند تا با یک نگاه، برنامه نویس بتواند الگوی مورد نظر را تشخیص دهد و مجبور به بررسی کد نباشد. البته به دلیل تشابه برخی از الگوها، امکان تشخیص الگو، در پاره ای از موارد وجود ندارد و یا به سختی امکان پذیر است.
الگوی Strategy یک الگوریتم را قادر میسازد تا در داخل یک کلاس کپسوله شود و در زمان اجرا به منظور تغییر رفتار شی، بین رفتارهای مختلف سوئیچ شود.
حال باید دو کلاس به منظور پیاده سازی روال تخفیف ایجاد کنیم. ابتدا کلاسی با نام TradeDiscountStrategy را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public class TradeDiscountStrategy : IDiscountStrategy { public decimal ApplyExtraDiscountsTo(decimal originalSalePrice) { return originalSalePrice * 0.95M; } }
سپس با توجه به الگوی Null Object کلاسی با نام NullDiscountStrategy را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public class NullDiscountStrategy : IDiscountStrategy { public decimal ApplyExtraDiscountsTo(decimal originalSalePrice) { return originalSalePrice; } }
از الگوی Null Object زمانی استفاده میشود که نمیخواهید و یا در برخی مواقع نمیتوانید یک نمونه (Instance) معتبر را برای یک کلاس ایجاد نمایید و همچنین مایل نیستید که مقدار Null را برای یک نمونه از کلاس برگردانید. در مباحث بعدی با جزئیات بیشتری در مورد الگوها صحبت خواهم کرد.
با توجه به استراتژیهای تخفیف کلاس Price را ایجاد کنید. کلاسی با نام Price را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public class Price { private IDiscountStrategy _discountStrategy = new NullDiscountStrategy(); private decimal _rrp; private decimal _sellingPrice; public Price(decimal rrp, decimal sellingPrice) { _rrp = rrp; _sellingPrice = sellingPrice; } public void SetDiscountStrategyTo(IDiscountStrategy discountStrategy) { _discountStrategy = discountStrategy; } public decimal SellingPrice { get { return _discountStrategy.ApplyExtraDiscountsTo(_sellingPrice); } } public decimal Rrp { get { return _rrp; } } public decimal Discount { get { if (Rrp > SellingPrice) return (Rrp - SellingPrice); else return 0; } } public decimal Savings { get{ if (Rrp > SellingPrice) return 1 - (SellingPrice / Rrp); else return 0; } } }
کلاس Price از نوعی Dependency Injection به نام Setter Injection در متد SetDiscountStrategyTo استفاده نموده است که استراتژی تخفیف را برای کالا مشخص مینماید. نوع دیگری از Dependency Injection با نام Constructor Injection وجود دارد که در مباحث بعدی در مورد آن بیشتر صحبت خواهم کرد.
جهت تکمیل لایه Model، کلاس Product را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public class Product { public int Id {get; set;} public string Name { get; set; } public Price Price { get; set; } }
موجودیتهای تجاری ایجاد شدند اما باید روشی اتخاذ نمایید تا لایه Model نسبت به منبع داده ای بصورت مستقل عمل نماید. به سرویسی نیاز دارید که به کلاینتها اجازه بدهد تا با لایه مدل در اتباط باشند و محصولات مورد نظر خود را با توجه به تخفیف اعمال شده برای رابط کاربری برگردانند. برای اینکه کلاینتها قادر باشند تا نوع تخفیف را مشخص نمایند، باید یک نوع شمارشی ایجاد کنید که به عنوان پارامتر ورودی متد سرویس استفاده شود. بنابراین نوع شمارشی CustomerType را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public enum CustomerType { Standard = 0, Trade = 1 }
برای اینکه تشخیص دهیم کدام یک از استراتژیهای تخفیف باید بر روی قیمت محصول اعمال گردد، نیاز داریم کلاسی را ایجاد کنیم تا با توجه به CustomerType تخفیف مورد نظر را اعمال نماید. کلاسی با نام DiscountFactory را با کد زیر ایجاد نمایید:
public static class DiscountFactory { public static IDiscountStrategy GetDiscountStrategyFor (CustomerType customerType) { switch (customerType) { case CustomerType.Trade: return new TradeDiscountStrategy(); default: return new NullDiscountStrategy(); } } }
در طراحی کلاس فوق از الگوی Factory استفاده شده است. این الگو یک کلاس را قادر میسازد تا با توجه به شرایط، یک شی معتبر را از یک کلاس ایجاد نماید. همانند الگوهای قبلی، در مورد این الگو نیز در مباحث بعدی بیشتر صحبت خواهم کرد.
لایهی سرویس با برقراری ارتباط با منبع داده ای، دادههای مورد نیاز خود را بر میگرداند. برای این منظور از الگوی Repository استفاده میکنیم. از آنجایی که لایه Model باید مستقل از منبع داده ای عمل کند و نیازی به شناسایی نوع منبع داده ای ندارد، جهت پیاده سازی الگوی Repository از Interface استفاده میشود. یک Interface به نام IProductRepository را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public interface IProductRepository { IList<Product> FindAll(); }
الگوی Repository به عنوان یک مجموعهی در حافظه (In-Memory Collection) یا انباره ای از موجودیتهای تجاری عمل میکند که نسبت به زیر بنای ساختاری منبع داده ای کاملا مستقل میباشد.
کلاس سرویس باید بتواند استراتژی تخفیف را بر روی مجموعه ای از محصولات اعمال نماید. برای این منظور باید یک Collection سفارشی ایجاد نماییم. اما من ترجیح میدهم از Extension Methods برای اعمال تخفیف بر روی محصولات استفاده کنم. بنابراین کلاسی به نام ProductListExtensionMethods را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public static class ProductListExtensionMethods { public static void Apply(this IList<Product> products, IDiscountStrategy discountStrategy) { foreach (Product p in products) { p.Price.SetDiscountStrategyTo(discountStrategy); } } }
الگوی Separated Interface تضمین میکند که کلاینت از پیاده سازی واقعی کاملا نامطلع میباشد و میتواند برنامه نویس را به سمت Abstraction و Dependency Inversion به جای پیاده سازی واقعی سوق دهد.
حال باید کلاس Service را ایجاد کنیم تا از طریق این کلاس، کلاینت با لایه Model در ارتباط باشد. کلاسی به نام ProductService را با کد زیر به پروژه SoCPatterns.Layered.Model اضافه کنید:
public class ProductService { private IProductRepository _productRepository; public ProductService(IProductRepository productRepository) { _productRepository = productRepository; } public IList<Product> GetAllProductsFor(CustomerType customerType) { IDiscountStrategy discountStrategy = DiscountFactory.GetDiscountStrategyFor(customerType); IList<Product> products = _productRepository.FindAll(); products.Apply(discountStrategy); return products; } }
در اینجا کدنویسی منطق تجاری در Domain Model به پایان رسیده است. همانطور که گفته شد، لایهی Business یا همان Domain Model به هیچ منبع داده ای خاصی وابسته نیست و به جای پیاده سازی کدهای منبع داده ای، از Interfaceها به منظور برقراری ارتباط با پایگاه داده استفاده شده است. پیاده سازی کدهای منبع داده ای را به لایهی Repository واگذار نمودیم که در بخشهای بعدی نحوه پیاده سازی آن را مشاهده خواهید کرد. این امر موجب میشود تا لایه Model درگیر پیچیدگیها و کد نویسیهای منبع داده ای نشود و بتواند به صورت مستقل و فارغ از بخشهای مختلف برنامه تست شود. لایه بعدی که میخواهیم کد نویسی آن را آغاز کنیم، لایهی Service میباشد.
در کد نویسیهای فوق از الگوهای طراحی (Design Patterns) متعددی استفاده شده است که به صورت مختصر در مورد آنها صحبت کردم. اصلا جای نگرانی نیست، چون در مباحث بعدی به صورت مفصل در مورد آنها صحبت خواهم کرد. در ضمن، ممکن است روال یادگیری و آموزش بسیار نامفهوم باشد که برای فهم بیشتر موضوع، باید کدها را بصورت کامل تست نموده و مثالهایی را پیاده سازی نمایید.
SQL Indexing
دلیل استفاده از ایندکس چیست؟
این سوالی است که ممکن است هر توسعه دهندهای به آن در ابتدا پاسخ دهد: «جهت بالابردن سرعت و کارآیی!» حال اگر بپرسیم چگونه؟ توضیحات چندان دقیقی ارائه نمیشود.
ایندکس چیست؟
ایندکس شیءای از دیتابیس است میتواند برروی یک یا چند ستون ایجاد شود (تا 16 ستون). هنگامیکه ایندکسی ایجاد میگردد، ساختار دادهای (BTree) جهت بهینه سازی عملیات مقایسه نیز ایجاد میشود. اس کیو ال سرور بدون داشتن ایندکس، برای دریافت اطلاعات درخواستی مجبور است کل ردیفهای جدول را جستجو نماید. این کار مانند این است که شما بدون اطلاع از شماره صفحه (محل) عنوان درخواستی، به دنبال آن در صفحات یک کتاب باشید. حال اگر به ایندکس (فهرست) کتاب مراجعه کنید به سرعت و حداقل اتلاف وقت میتوانید محل یا شماره صفحهی عنوان مورد نظر را، بدون جستجوی کلیهی صفحات کتاب، پیدا کنید و به آن مراجعه کنید. ایندکس جدول نیز اجازه میدهد بدون جستجوی کلیه رکوردها، رکورد مورد نظر را دریافت نمایید.مثال:
SELECT [computer_id],[nic_device_id],[nic_vendor_id],[nic_desc] FROM [eXpress].[dbo].[nics]
فرض کنید در جدول بالا ایندکس گذاری انجام نشده باشد و قصد داشته باشید رکوردهایی را دریافت نمایید که در آنها computer_id>5100 باشد. اس کیو ال سرور مجبور است کلیه رکوردهای جدول را جهت اعمال شرط بررسی نماید.
حال، برروی ستون computer_id ایندکسی را اعمال مینماییم و شرط computer_id>5100 را مجدد بررسی میکنیم. اس کیو ال از محل رکوردهای با مقادیر بزرگتر از 5100 اطلاع دارد و از جستجوی کل جدول اجتناب میکند. چرا؟ بدلیل اینکه براساس این ستون مرتب شده است.
انواع ایندکس
دو نوع ایندکس اصلی وجود دارد: ایندکس خوشهای و ایندکس غیرخوشهای
ایندکس خوشهای
نحوهی ذخیره سازی فیزیکی رکوردها را تغییر میدهد. هنگامیکه یک ایندکس خوشهای را ایجاد میکنید، بر روی یک ستون (یا ترکیبی از چند ستون)، اس کیو ال سرور رکوردها را براساس ستون/ها بصورت صعودی مرتب شده (مانند یک دیکشنری که کلیه کلمات بصورت الفبایی قرار گرفتهاند) ذخیره مینماید.
بوسیله ایندکس زیر تمام رکوردها براساس ستون computer_id مرتب شده ذخیره میگردند.CREATE CLUSTERED INDEX [IX_CLUSTERED_COMPUTER_ID] ON [dbo].[nics] ([computer_id] ASC)
همانطور که اشاره شد، رکوردها بصورت مرتب شده براساس ستون انتخاب شدهی در
جدول نگهداری میشوند. اما این مرتب سازی توسط ساختار BTree بهشرح زیر انجام
خواهد شد. جدول زیر را در نظر داشته باشید:
فرض کنید بعد ایندکس گذاری ستون StudId جدول فوق، درخت BTree زیر ایجاد میگردد که این ساختار بهصورت جداگانهای بر روی دیسک ذخیره میگردد. در این درخت، مقدار گره سمت چپ ریشه از آن کمتر و مقدار گره سمت راست ریشه از آن بیشتر است (البته عکس این فرض نیز امکان پذیر است).
و سپس کوئریهای زیر را صادر میکنید:
Select * from student where studid = 103; Select * from student where studid = 107;
با ایندکس گذاری، کوئری اول، بعد از اولین عمل مقایسه و کوئری دوم بعد از 3 عمل مقایسه پیدا میشود؛ بهشرح زیر:
- مقایسه 107 با 103 و انتقال به گره سمت راست
- مقایسه 107 با 106 و انتقال به گره سمت راست
- مقایسه 107 با 107 و یافتن مقدار درخواستی و بازگشت رکورد
در صورتیکه تعداد رکوردها کم باشند، تفاوت کارآیی جداول دارای ایندکس و بدون ایندکس قابل لمس نخواهد بود.
ایندکس غیرخوشهای
این نوع ایندکس، تغییری در نحوهی ذخیره سازی رکوردها انجام نمیدهند. ولی شیء دیگری را که شامل ستون/هایی که قرار است ایندکس شوند و اشارهگر به رکورد (RID) هستند، در جدول ایجاد میکند. برای مثالی از ایندکس غیرخوشهای در دنیای واقعی، میتوان به فهرست انتهای کتابها که شامل عناوین و شماره صفحهی مربوطه میباشد، اشاره کرد.
نکته: RID به موقعیت فیزیکی رکورد اشاره خواهد کرد و شامل شناسه، شماره صفحه و تعداد رکوردهای در یک صفحه میباشد.
برای درک بهتر به سناریوی زیر دقت کنید:
کتابی داریم که شامل 1200 صفحه میباشد و فهرست مطالب آن شامل عناوین و
شماره صفحات عناوین میباشد. حال اگر عنوان درخواستی A در صفحات 700، 300،
800 قرار داشته باشد، برای رفتن به این صفحات، مراحل زیر را برای هر یک طی
خواهید کرد:
- یافتن شماره صفحه عنوان درخواستی با مراجعه به فهرست انتهای کتاب.
- در ادامه شما صفحهای را در میانهی کتاب، باز میکنید؛ چون عدد 700 مقداری از نصف 1200 برزگتر است.
- چند صفحه به جلو رفته، شماره صفحه 750 خواهد بود و هنوز به شرط مورد نظر نرسیدهاید.
- پس مجددا چند صفحه به عقب بازگشته تا به صفحهی مورد نظر، 700، برسید.
مراحل فوق برای یافتن عنوان A واقع شدهی در صفحه 700 انجام شد که همین مراحل نیز برای سایر صفحات میتواند انجام شود. در این مثال، صفحه فهرست مطالب کتاب، به ایندکس غیرخوشهای تعبیر خواهد شد.
این نوع ایندکسها جهت ستون هایی مفید هستند که مقادیر آن تکرار خواهد شد؛ مانند جدولی با بیش از چند میلیون رکورد که دارای ستون نوع حساب است، ولی تعداد نوع حساب منحصر بفرد محدودی را خواهد داشت. فرض کنید مقادیر منحصر بفرد، ستون نوع حساب A، B، C باشد. زمانیکه برروی این ستون ایندکس گذاری غیرخوشهای انجام میشود، فهرست ما دارای سه عنوان خواهد بود که هر عنوان به صفحات مربوط به همان عنوان اشاره خواهد کرد. به این ترتیب هنگامیکه برروی نوع حساب عملیات جستجو انجام شود، اس کیو ال میداند رکوردهای نوع حساب مثلا A در کدام صفحات قرار دارد و بهسرعت رکوردهای متناظر را پیدا مینماید.
A: 300, 700, 800 B: 100, 110 C: 600, 1200
ایندکس غیرخوشه ای توسط دستور زیر ایجاد میگردد:
CREATE NONCLUSTERED INDEX [IX_NONCLUSTERED_COMPUTER_ID] ON [dbo].[nics] ([computer_id] ASC)
نکته: یک جدول میتواند بیش از یک ایندکس غیرخوشهای و فقط و
فقط یک ایندکس خوشهای داشته باشد.
ارتباط ایندکس خوشهای و غیر خوشهای
اشارهگر به رکورد (RID) در یک جدول دارای ایندکس خوشهای، کلید ایندکس خوشهای خواهد بود.
مزایا و معایب ایندکس
مزایا:جدولی بدون ایندکس خوشهای، heap table شناخته میشود. یک جدول هیپ، دادهی مرتب شده نخواهد داشت و به منظور دریافت اطلاعات، اس کیو ال سرور مجبور است کل ردیفهای جدول را بررسی نماید که این عملیات Scan نامیده میشود. ولی در صورت استفاده از ایندکس خوشهای برروی یک ستون، اس کیو ال، جهت یافتن اطلاعات مورد جستجو با توجه به BTree عملیات جستجو را از ریشه شروع، از شاخهها عبور کرده و به برگ که همان اطلاعات درخواستی است میرسد که این عملیات Seek نامیده میشود. عملیات Seek طبیعتا از Scan سریعتر است.
ایندکس غیرخوشهای، شامل مجموعهای از ستونها و ارجاعاتی به رکوردها یا کلید ایندکس خوشهای است (ارتباط بین ایندکس غیر خوشهای با خوشهای). بهدلیل حجم کم این نوع ایندکس، میتواند ردیفها یا کلیدهای ایندکس خوشه ای بیشتری در صفحهی ایندکس وجود داشته باشد که باعث افزایش کارآیی I/O میگردد.
معایب:
ایندکس گذاری، در طی عملیات درج، ویرایش و حذف، باعث سربار میگردد. هنگامیکه تغییری بر روی رکوردهای جدول انجام میشود، سبب تغییراتی نیز بر روی ایندکسها میگردد (هنگامیکه برگهای از کتابی جدا شود، نیاز است شماره صفحات و فهرست انتهایی کتاب مجددا بهروز گردد) که این تغییرات باعث ایجاد هزینه میشود. بنابراین خیلی اهمیت دارد که هنگام طراحی ایندکس گذاری به سربارها نیز توجه کنید. بهعنوان مثال هنگامیکه توسط دستور Delete رکوردی را از جدولی حذف نمایید، نیاز است رکوردها مجددا مرتب شوند که این یک سربار است.
ایندکس گذاری ، سرباری بنام bookmark lookup دارد. bookmark lookup فرآیندی جهت یافتن سایر ستونهایی است که در ایندکس گذاری وجود ندارند و براساس RID هستند.
CoffeeScript #13
بخشهای بد
در ادامهی قسمت قبل، به مواردی که توسط CoffeeScript اصلاح شدهاند، میپردازیم.
Reserved words
کلمات کلیدی خاصی در جاوااسکریپت وجود دارد مانند class، enum و const که برای نسخههای بعدی جاوااسکریپت در آینده رزرو شدهاند. استفاده از این کلمات در برنامههای جاوااسکریپت میتواند نتایج غیرقابل پیش بینی داشته باشد. برخی از مرورگرهای به خوبی از عهدهی این کار برمیآیند و بعضی دیگر به طور کامل جلوی استفاده از اینها را گرفتهاند. CoffeeScript بعد از تشخیص استفاده از یک کلمهی کلیدی، با یک راه کار خاص، از این موضوع میگریزد.
به عنوان مثال، فرض کنید میخواهیم از کلمه کلیدی class به عنوان یک خصوصیت در یک شیء استفاده کنیم:
myObj = { delete: "I am a keyword!" } myObj.class = ->
var myObj; myObj = { "delete": "I am a keyword!" }; myObj["class"] = function() {};
Equality comparisons
مقایسه برابری ضعف دیگری است که در جاوااسکریپت باعث ایجاد رفتاری گیج کننده و اغلب باعث ایجاد اشکالاتی در کد نوشته شده میشود. به مثال زیر توجه کنید:
"" == "0"// false 0 == ""// true 0 == "0"// true false == "false"// false false == "0"// true false == undefined// false false == null// false null == undefined// true " \t\r\n" == 0// true
راه حل این کار استفاده از عملگر برابری سختگیرانه است، که از 3 مساوی تشکیل شده است: === عملگر برابر سخت گیرانه دقیقا مانند عملگر برابری عادی عمل میکند و تنها نوع دادهها را بررسی میکند که با هم برابر باشند.
توصیه میشود که همیشه از عملگر برابری سختگیرانه استفاده کنید و هرجا لازم بود قبل مقایسه عمل تبدیل نوع دادهها را انجام دهید.
CoffeeScript این مشکل را به صورت کامل حل کرده است؛ یعنی هر جایی که عمل مقایسه == انجام شود به === تبدیل میشود. شما باید به صورت صریح نوع دادهها را قبل از مقایسه تبدیل کرده باشید.
نکته: در مقایسهها رشته خالی ""، null ،undefined و عدد 0 همگی false برمی گردانند.
alert "Empty Array" unless [].length alert "Empty String" unless "" alert "Number 0" unless 0
if (![].length) { alert("Empty Array"); } if (!"") { alert("Empty String"); } if (!0) { alert("Number 0"); }
alert "This is not called" unless ""?
if ("" == null) { alert("This is not called"); }
Function definition
خیلی جالب است که در جاوااسکریپت میتوانید تابعی را بعد از اینکه فراخوانی کردید، تعریف کنید. به عنوان مثال، کد زیر به صورت کامل اجرا میشود:
wem(); function wem() {alert("hi");}
if (true) { function declaration() { return "first"; } } else { function declaration() { return "second"; } } declaration();
، تابع ()declaration مقدار "first" را برگشت خواهد داد و در دیگر مرورگرها مانند Chrome، مقدار "second" برگشت داده خواهد شد. در حالیکه به نظر میرسد که قسمت else هیچگاه اجرا نخواهد شد.در صورتیکه علاقمند به کسب اطلاعات بیشتری دربارهی نحوه تعریف توابع، هستید باید راهنمای آقای Juriy Zaytsev را مطالعه کنید. به صورت خلاصه، رفتار نسبتا مبهم مرورگرها میتواند منجر به ایجاد مشکلاتی در مسیر نوشتن یک پروژه شوند.
همه چیز در CoffeeScript در نظر گرفته شده است و بهترین روش برای حل این مشکل، حذف کلمه function و به جای آن استفاده از عبارت (expression) تابع است.
Number property lookups
نقصی که در پارسر جاوااسکریپت در مواجه با نماد نقطه (dot notation) بر روی اعداد وجود دارد، تفسیر آن به ممیز شناور، بجای مراجعه به ویژگیهای آن است. برای مثال کد جاوااسکریپت زیر باعث ایجاد خطای نحوی میشود:5.toString();
(5).toString(); 5..toString();
یادگیری مدل در داده کاوی
مقدمه
هدف اصلی داده کاوی کشف دانش است، که این دانش نظمی که در دادهها وجود دارد را نمایان میسازد. پس از کشف دانش ممکن است با دو وضعیت مواجه شویم:- حالت اول هنگامی است که افراد خبره در دامنه داده مورد کاوش، آگاه به دانش استخراج شده باشند که در این صورت آن دانش به عنوان یک قانون صحیح تلقی خواهد شد.
- در حالت دوم ممکن است دانش کشف شده، یک دانش جدید بوده و در بین افراد خبره در آن حوزه شناخته شده نباشد، در این صورت این دانش بررسی شده و در صورت منطقی بودن تبدیل به فرضیه شده و در نهایت درست یا غلط بودن این فرضیه با آزمایشات و بررسیهای متعدد اثبات میشود و در صورت درست بودن فرضیه تبدیل به قانون خواهد شد.
روشهای یادگیری مدل در داده کاوی
پیشتر به معرفی مراحل کاری در داده کاوی که مشتمل بر سه مرحله اساسی: آماده سازی داده، یادگیری مدل و در نهایت ارزیابی و تفسیر مدل میباشد، پرداختیم.در مرحله یادگیری مدل با استفاده از الگوریتمهای متنوع و با در نظر گرفتن ماهیت داده، نظمهای مختلف موجود در دادهها شناسائی میشود. بطور کلی روشهای مختلف کاوش داده را به دو گروه روشهای پیش بینی و روشهای توصیفی طبقه بندی میکنند.
در روشهای پیش بینی از مقادیر بعضی ویژگیها برای پیش بینی کردن مقدار یک ویژگی مشخص استفاده میکنند. این روشها در متون علمی با نام روشهای با ناظر (Supervised Methods ) نیز شناخته میشوند. الگوریتمهای با ناظر از دو مرحله با عنوان مرحله آموزش (یادگیری) و مرحله ارزیابی تشکیل شده اند.
در مرحله آموزش؛ با استفاده از مجموعه دادههای آموزشی مدل ساخته میشود. شکل مدل ساخته شده به نوع الگوریتم یادگیرنده بستگی دارد.
در مرحله ارزیابی؛ از مجموعه دادههای آزمایشی برای اعتبارسنجی و محاسبه دقت مدل ساخته شده استفاده میشود، در واقع از داده هایی که در مرحله آموزش و ساخت مدل؛ الگوریتم این مجموعه دادهها را ندیده است (Previously Unseen Data) استفاده میشود.
برای نمونه روشهای دسته بندی (Classification)، رگرسیون (Regression) و تشخیص انحراف (Anomaly Detection) سه روش یادگیری مدل در داده کاوی با ماهیت پیش بینی هستند.
در روشهای توصیفی همانطور که انتظار داریم الگوهای قابل توصیف از روابط حاکم بر دادهها بدون در نظر گرفتن هر گونه برچسب و یا متغیر خروجی بدست میآید. این روشها در متون علمی با نام روشهای بدون ناظر (Unsupervised Methods) نیز شناخته میشوند. برای نمونه روشهای خوشه بندی (Clustering)، کاوش قوانین انجمنی (Association Rules Mining) و کشف الگوهای ترتیبی (Sequential Pattern Discovery) سه روش یادگیری مدل در داده کاوی با ماهیت توصیفی هستند.
در ادامه به معرفی هر کدام از این روشها میپردازیم:
دسته بندی:
در الگوریتمهای دسته بندی مجموعه داده اولیه به دو مجموعه داده با عنوان مجموعه دادههای آموزشی (Train Dataset) و مجموعه دادههای آزمایشی (Test Dataset) تقسیم میشود. میدانیم هر Case شامل مجموعه ای از Attribute هاست، که یکی از این ویژگیها ویژگی دسته نامیده میشود.در مرحله آموزش؛ مجموعه دادههای آموزشی به یکی از الگوریتمهای دسته بندی داده میشود تا بر اساس سایر ویژگیها برای مقادیر ویژگی دسته، مدل ساخته شود.
پس از ساخت مدل، در مرحله ارزیابی؛ دقت مدل ساخته شده به کمک مجموعه دادههای آزمایشی ارزیابی خواهد شد. در الگوریتمهای دسته بندی از آنجا که ویژگی دسته مربوط به هر Case مشخص است به صورت الگوریتمهای با ناظر محسوب میشوند. بدیهی است که تشخیص بر اساس دسته هایی است که مدل در مرحله آموزش با آنها روبرو شده است؛ بنابراین امکان تشخیص دسته جدید در کاربرد دسته بندی وجود نخواهد داشت.
رگرسیون:
رگرسیون در علوم آمار و شبکههای عصبی بطور وسیعی مورد بررسی و مطالعه قرار میگیرد. پیش بینی مقدار یک متغیر پیوسته بر اساس مقادیر سایر متغیرها بر مبنای یک مدل وابستگی خطی یا غیر خطی رگرسیون نامیده میشود. یک نوع خاصی از رگرسیون، پیش بینی سریهای زمانی (Time Series Prediction) است؛ برای مثال تغییرات قیمت سهام شرکتی را به صورت نمودار داریم؛ میخواهیم ادامه روند این نمودار را برای مدتی مشخص پیش بینی کنیم. در مسائل سریهای زمانی یکی از متغیرهای اصلی زمان میباشد. بدیهی است که رگرسیون لزوماً سری زمانی نیست و همانند دسته بندی کاربرد رگرسیون نیز از نوع پیش بینی با ناظر است و بطور مشابه در رگرسیون هم دو مرحله آموزش و ارزیابی نیز وجود دارد. مثال هایی از رگرسیون میتواند شامل موارد زیر باشد: پیش بینی میزان فروش یک محصول جدید، براساس میزان فروش محصولات گذشته و یا براساس میزان تبلیغات انجام شده و ... همچنین مسائل مربوط به پیش بینی سریهای زمانی از قبیل بورس و ... .تشخیص انحراف:
از کاربردهای متداول تشخیص انحراف، میتوان به کشف کلاهبرداری کارتهای اعتباری (Credit Card Fraud Detection) اشاره کرد. در مواقعی از این کاربرد استفاده میشود که تنها نمونه هایی با یک برچسب یکسان که معمولاً وضعیت نرمال را نشان میدهند در دسترس میباشند و امکان مالکیت بر دادهها با تمامی برچسبهای موجود به دلایل مختلف وجود ندارد. بنابراین چون فقط نمونههای دسته نرمال در اختیار است، الگوریتم برای وضعیت نرمال و با توجه به یک آستانه (Threshold) مشخص مدل را میسازد و هر گونه تخطی از آن آستانه را؛ بعنوان وضعیت غیرنرمال در نظر میگیرد. توجه شود روشهای دسته بندی تنها قادر به شناسائی دسته هایی هستند که در مرحله آموزش، نمونه ای از آنها به الگوریتم ارائه شده است، بنابراین امکان تشخیص هیچ گونه کلاهبرداری توسط روشهای دسته بندی وجود ندارد.خوشه بندی:
در این مسائل از آنجا که بر خلاف دسته بندی هیچ گونه دسته خاصی وجود ندارد، بنابراین براساس معیار شباهت دادهها گروه بندی و خوشه بندی صورت میگیرد. بدین ترتیب Case هایی که بیشترین شباهت را به یکدیگر دارند در یک خوشه قرار میگیرند، به بیان دیگر Caseهای موجود در خوشههای متفاوت کمترین شباهت را به یکدیگر خواهند داشت. بدیهی است که خوشه بندی براساس ویژگی ورودی نمونهها انجام میگیرد و از آنجائی که برای این الگوریتمها ویژگی دسته تعریف نمیشود و Caseها برچسب خاصی ندارند، جزء الگوریتمهای بدون ناظر محسوب میشوند. در واقع هدف در تمامی الگوریتمهای خوشه بندی کمینه کردن فاصله درون خوشه ای (Intra-Cluster Density) و بیشینه نمودن فاصله بین خوشه ای (Inter-Cluster Density) است و عملکرد خوب یک الگوریتم خوشه بندی زمانی محرز میشود که تا حد امکان خوشهها را از یکدیگر دورتر کند و در ضمن Caseهای موجود در یک خوشه بیشترین شباهت را به یکدیگر داشته باشند.کشف قوانین انجمنی:
قوانین وابستگی (انجمنی) اتفاق و وقوع یک شیء را براساس وقوع سایر اشیاء توصیف میکنند، برای مثال در یک سوپر مارکت هدف در کاوش قوانین انجمنی؛ یافتن نظم حاکم بر سبد خرید میباشد، در این کاربرد به ازای هر سبد؛ یک قانون پیدا میشود و بررسی خواهد شد که این قانون در چه تعداد از سبدها صدق میکند و در نهایت یک مجموعه قوانین که در بیشترین تعداد از سبدها صدق میکند به عنوان مجموعه قوانین انجمنی خروجی ارائه میشود. به بیان دیگر در این کاربرد به دنبال پیدا کردن یک مجموعه از قوانین وابستگی هستیم تا براساس آن قوانین بتوانیم نتیجه گیری کنیم وجود کدامیک از مجموعه اشیاء (Item Set) بر وجود چه مجموعه اشیاء دیگری تاثیر گذار است.کشف الگوهای ترتیبی:
در این کاربرد به دنبال کشف الگوهایی هستیم که وابستگیهای ترتیبی محکمی را در میان وقایع مختلف نشان میدهند. این کاربرد مشابه کاوش قوانین انجمنی میباشد با این تفاوت که در کاوش قوانین انجمنی زمان و ترتیب زمانی مطرح نیست، اما در کشف الگوهای ترتیبی زمان و ترتیب اهمیت ویژه ای دارند برای مثال میتوان به دنبالههای تراکنشهای فروش اشاره نمود.منبع: با اندکی تغییر و تلخیص "داده کاوی کاربردی در RapidMiner، انتشارات نیاز دانش"