اشتراکها
مطالب
آموزش QUnit #2
فریم ورک تست جاوا اسکریپت QUnit:
انتخاب و استفاده از یک فریم ورک برای تست کدهای جاوا اسکریپت، قطعا نتیجه بهتری را به همراه خواهد داشت. من در این جا از QUnit که یکی از بهترینهای تست واحد است، استفاده میکنم. برای این کار فایلهای qunit.js و qunit.css را دانلود و مانند زیر برای تست واحد آماده کنید:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Refactored date examples</title> <link rel="stylesheet" href="../qunit.css"> <script src="../qunit.js"></script> <script src="prettydate.js"></script> <script> test("prettydate basics", function() { var now = "2013/01/28 22:25:00"; equal(prettyDate(now, "2013/01/28 22:24:30"), "just now"); equal(prettyDate(now, "201308/01/28 22:23:30"), "1 minute ago"); equal(prettyDate(now, "2013/01/28 21:23:30"), "1 hour ago"); equal(prettyDate(now, "2013/01/27 22:23:30"), "Yesterday"); equal(prettyDate(now, "2013/01/26 22:23:30"), "2 days ago"); equal(prettyDate(now, "2012/01/26 22:23:30"), undefined); }); </script> </head> <body> <div id="qunit"></div> </body> </html>
در کد بالا ابتدا فایلهای فریم ورک و فایل prettydate.js را اضافه کردیم. برای نمایش نتیجه تست، یک تگ div با نام qunit در بین تگ body اضافه میکنیم.
تابع test:
این تابع برای تست توابع نوشته شده، استفاده میشود. ورودیهای این تابع، یکی عنوان تست و دومی یک متود دیگر، به عنوان ورودی دریافت میکند که در آن بدنه تست نوشته میشود.
تابع equal:
اولین تابع برای سنجش تست واحد equal است و در آن، تابعی که میخواهیم تست کنیم با مقدار خروجی آن مقایسه میشود.
فایل را با نام test.htm ذخیره و آن را در مرورگر خود باز نمایید. خروجی در شکل آورده شده است:
همین طور که در تصویر بزرگ میبینید اطلاعات مرورگر، زمان تکمیل تست و تعداد تست، تعداد تست پاس شده و تعداد تست شکست خورده، نشان داده شده است.
اگر یکی از تستها با شکست روبرو شود رنگ پس زمینه قرمز و جزئیات شکست نمایش داده میشوند.
بهینه سازی، مرحله اول:
در حال حاضر تست ما کامل نیست زیرا امکان تست n weeks ago یا تعداد هفته پیش میسر نیست. قبل از آنکه این را به آزمون اضافه کنیم، تغییراتی در تست میدهیم
test("prettydate basics", function() { function date(then, expected) { equal(prettyDate("2013/01/28 22:25:00", then), expected); } date("2013/01/28 22:24:30", "just now"); date("2013/01/28 22:23:30", "1 minute ago"); date("2013/01/28 21:23:30", "1 hour ago"); date("2013/01/27 22:23:30", "Yesterday"); date("2013/01/26 22:23:30", "2 days ago"); date("2012/01/26 22:23:30", undefined); });
تابع prettyDate را در تابع دیگری به نام date قرار میدهیم. این تغییر سبب میشود تا امکان مقایسه زمان ورودی تست جاری با تست قبلی فراهم شود.
تست دستکاری عناصر DOM:
تا اینجا با تست توایع آشنا شدید، حالا میخواهیم تغییراتی در prettyDate دهیم تا امکان انتخاب عناصر DOM و به روزرسانی آن نیز وجود داشته باشد. فایل prettyDate2.js در زیر آورده شده است:
var prettyDate = { format: function(now, time){ var date = new Date(time || ""), diff = (((new Date(now)).getTime() - date.getTime()) / 1000), day_diff = Math.floor(diff / 86400); if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) return; return day_diff === 0 && ( diff < 60 && "just now" || diff < 120 && "1 minute ago" || diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" || diff < 7200 && "1 hour ago" || diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") || day_diff === 1 && "Yesterday" || day_diff < 7 && day_diff + " days ago" || day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago"; }, update: function(now) { var links = document.getElementsByTagName("a"); for ( var i = 0; i < links.length; i++ ) { if ( links[i].title ) { var date = prettyDate.format(now, links[i].title); if ( date ) { links[i].innerHTML = date; } } } } };
prettyDate شامل دو تابع، یکی format که weeks ago به آن اضافه گردیده و تابع update که با انتخاب تگها، مقدار title را به تابع فرمت و خروجی آن را در Html هر عنصر قرار میدهد. حال یک تست واحد مینویسیم:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Refactored date examples</title> <link rel="stylesheet" href="../qunit.css"> <script src="../qunit.js"></script> <script src="prettydate2.js"></script> <script> test("prettydate.format", function() { function date(then, expected) { equal(prettyDate.format("2013/01/28 22:25:00", then), expected); } date("2013/01/28 22:24:30", "just now"); date("2013/01/28 22:23:30", "1 minute ago"); date("2013/01/28 21:23:30", "1 hour ago"); date("2013/01/27 22:23:30", "Yesterday"); date("2013/01/26 22:23:30", "2 days ago"); date("2012/01/26 22:23:30", undefined); }); function domtest(name, now, first, second) { test(name, function() { var links = document.getElementById("qunit-fixture") .getElementsByTagName("a"); equal(links[0].innerHTML, "January 28th, 2013"); equal(links[2].innerHTML, "January 27th, 2013"); prettyDate.update(now); equal(links[0].innerHTML, first); equal(links[2].innerHTML, second); }); } domtest("prettyDate.update", "2013-01-28T22:25:00Z", "2 hours ago", "Yesterday"); domtest("prettyDate.update, one day later", "2013/01/29 22:25:00", "Yesterday", "2 days ago"); </script> </head> <body> <div id="qunit"></div> <div id="qunit-fixture"> <ul> <li id="post57"> <p>blah blah blah...</p> <small> Posted <span> <a href="/2013/01/blah/57/" title="2013-01-28T20:24:17Z" >January 28th, 2013</a> </span> by <span><a href=""></a></span> </small> </li> <li id="post57"> <p>blah blah blah...</p> <small> Posted <span> <a href="/2013/01/blah/57/" title="2013-01-27T22:24:17Z" >January 27th, 2013</a> </span> by <span><a href=""></a></span> </small> </li> </ul> </div> </body> </html>
همین طور که مشاهد میکنید در تست واحد اول خود تابع prettyDate.format را تست نموده ایم. در تست بعدی عناصر DOM نیز دستکاری و تست شده است. تابع domtest با جستجوی تگ qunit-fixture و تگهای a درون آن، مقدار نهایی html آن با مقدار داده شده، مقایسه شده است.
در شکل بالا نتیجه تست واحد نشان داده شده است.
چگونه میشه برفرض از تعداد 100 تگ از یک پست به همراه واکشی پست (1)، از فیلترهای Take و Skip استفاده کرد؟
یعنی قبل کد زیر که پست و 100 تگ مرتبط رو واکشی میکند بر روی تگها فیلتر رو اعمال کنیم
آیا امکانش وجود دارد؟
BlogPosts post1 = this.BlogPosts .Include(blogPosts => blogPosts.BlogPostsJoinTags) .ThenInclude(joinTags => joinTags.Tag) .First(blogPosts => blogPosts.Id == 1); IEnumerable<Tags> post1Tags = post1.BlogPostsJoinTags.Select(x => x.Tag);
.First(blogPosts => blogPosts.Id == 1);
آیا امکانش وجود دارد؟
سلام مهیار جان!
کد بسیار خوب و خوانایی گذاشتید، ممنونم!
در نتیجه:
کد بسیار خوب و خوانایی گذاشتید، ممنونم!
در نتیجه:
DECLARE @IntegerNumber NVARCHAR(100), @DecimalNumber NVARCHAR(100), @PointPosition INT =case CHARINDEX('.', @pNumber) WHEN 0 THEN LEN(@pNumber)+1 ELSE CHARINDEX('.', @pNumber) END SET @pNumber=replace(rtrim(replace(@pNumber,'0',' ')),' ','0'); SET @IntegerNumber= LEFT(@pNumber, @PointPosition - 1) SET @DecimalNumber= SUBSTRING(@pNumber, @PointPosition+1 , LEN(@pNumber)) SET @pNumber= @IntegerNumber
اینترفیس، مانند قراردادی است که یک نوع را تعریف میکند. کامپایلر از اینترفیسها جهت بررسی نوعها و اجبار به رعایت قرارداد استفاده میکند. در این حالت اگر متدها یا خواص معرفی شدهی در نوع اینترفیس، توسط استفاده کننده بکار گرفته نشوند، خطایی توسط کامپایلر گزارش خواهد شد.
از آنجائیکه اینترفیسها به معنای نوعهای سفارشی هستند و جاوا اسکریپت از آنها پشتیبانی نمیکند، توسط کامپایلر TypeScript، به هیچ نوع کد معادلی در جاوا اسکریپت، ترجمه و تبدیل نخواهند شد. کامپایلر TypeScript تنها از آنها جهت بررسی نوعها استفاده میکند.
اینترفیسها به صورت مجموعهای از تعاریف خواص و متدها، بدون پیاده سازی آنها تعریف میشوند. پیاده سازی این اینترفیسها، توسط کلاسها و یا سایر اشیاء صورت خواهند گرفت. برای مثال یک قرارداد اجاره، مشخص میکند که آخر هر ماه چه مقداری را باید پرداخت کرد. اما این قرار داد مشخص نمیکند که چگونه باید این پرداخت صورت گیرد و از هر شخصی به شخص دیگری میتواند متفاوت باشد. به این حالت duck typing هم میگویند. به این معنا که قرار داد، شکل یک شیء را مشخص میکند و تا زمانیکه پیاده سازی کنندهی آن بتواند این قرارداد را تامین کند، میتواند بجای نوع اصلی نیز بکار گرفته شود.
Duck typing چیست؟
duck typing به این معنا است که اگر پرندهای بتواند مانند یک اردک راه برود، شنا کند و صدا در بیاورد، یک اردک نامیده میشود. بنابراین همینقدر که یک شیء بتواند قراردادی را پیاده سازی کند، نوع آن با نوع اینترفیس یکی درنظر گرفته میشود. برای نمونه به مثال ذیل دقت کنید:
در این مثال اینترفیس Duck، متدهایی را تعریف کردهاست که یک Duck میتواند انجام دهد.
در ادامه متغیر و شیءایی بدون تعریف نوع آن ایجاد شدهاست که همان متدهای اینترفیس Duck را پیاده سازی میکند و امضای آنها با امضای متدهای اینترفیس Duck یکی هستند.
سپس متد FlyOverWater تعریف شده که در آن، نوع پارامتر ورودی آن به صورت صریحی به نوع اینترفیس Duck مقید شدهاست.
در سطر بعدی، این متد با دریافت شیء probablyADuck فراخوانی شدهاست و چون این شیء تمام اجزای قرارداد Duck را پیاده سازی کردهاست، مشکلی در اجرای آن نخواهد بود. به این حالت duck typing میگویند.
نحوهی تعریف یک اینترفیس در TypeScript
تعریف یک اینترفیس با واژهی کلیدی interface شروع شده و سپس خواص و متدهای مدنظر این قرارداد، به همراه نوع آنها تعریف خواهند شد:
در این مثال خواص id، title و author اجباری هستند و پیاده سازی کننده موظف است آنها را به همراه داشته باشد.
در اینترفیسهای TypeScript میتوان خواص اختیاری و optional را نیز تعریف کرد. نمونهی آن خاصیت pages در این مثال است که با ? مشخص شدهاست و نمونهی آنرا در حین تعریف پارامترهای اختیاری متدها نیز پیشتر ملاحظه کرده بودید.
تعریف متدها در یک اینترفیس، با مشخص سازی نام آن متد و ذکر یک کولن و سپس مشخص سازی امضای پارامترهای دریافتی انجام میشود. نوع خروجی متد، در سمت راست علامت <= قرار خواهد گرفت.
استفاده از اینترفیسها برای تعریف نوع خروجی توابع
در مثال زیر، متد CreateCustomerID دارای دو پارامتر ورودی از نوعهای رشتهای و عددی است و خروجی آن نیز از نوع رشتهای تعریف شدهاست:
در ادامه تعریف متغیری را مشاهده میکنید که نوع آن، متدی است که با امضای متد CreateCustomerID یکسان است:
به این ترتیب امکان انتساب متد CreateCustomerID به متغیر IdGenerator وجود خواهد داشت:
جهت مدیریت بهتر یک چنین تعریفهایی و همچنین امکان استفادهی مجدد از آنها، میتوان از اینترفیسها کمک گرفت:
اینترفیس StringGenerator نام بهتر و با قابلیت استفادهی مجددی را به نوع متدی که قابل انتساب است به متغیر IdGenerator، تعریف میکند. در اینجا syntax تعریف نوع متد، در اینترفیس StringGenerator اندکی با حالتهای قبلی متفاوت است. در اینجا بجای استفاده از <= جهت مشخص کردن نوع خروجی متد، از کولن استفاده شدهاست.
اکنون میتوان نحوهی تعریف متغیر IdGenerator را به صورت زیر Refactor کرد و تغییر داد:
به عنوان نمونه میتوان یک چنین تغییری را در نحوهی تعریف اینترفیس Book ابتدای بحث و تغییر متد markDamaged آن نیز اعمال کرد.
بسط و توسعهی اینترفیسها
بسط و توسعهی اینترفیسها شبیه به مباحث ارث بری هستند. به این ترتیب که با بسط یک اینترفیس از طریق اینترفیسی دیگر، میتوان به نوعی مرکب رسید:
در این مثال، ابتدا دو اینترفیس منابع و کتابهای یک کتابخانه تعریف شدهاند. سپس اینترفیس جدیدی به نام Encyclopedia با بسط این دو اینترفیس توسط واژهی کلیدی extends ایجاد شدهاست.
این نوع مرکب، علاوه بر دارا بودن خاصیت volume مختص به خودش، اکنون حاوی دو خاصیت موجود در سایر اینترفیسهای ذکر شدهی در قسمت extends نیز هست.
حال اگر متغیر جدیدی را از نوع Encyclopedia تعریف کنیم، جهت برآورده شده تمام اجزای قرارداد، لازم است هر سه خاصیت را مقدار دهی نمائیم:
نوع کلاسها
مبحث کلاسها به صورت جداگانهای در این سری بررسی خواهند شد. اما جهت تکمیل بحث جاری نیاز است اشارهی کوتاهی به آنها شود.
همانطور که عنوان شد، اینترفیسها تنها شکل و قرارداد پیاده سازی یک شیء را تعریف میکنند؛ بدون ارائهی پیاده سازی خاصی از آنها. تا اینجا در بحث جاری، اشیاء را توسط object literals داخل {} تعریف کردیم (مانند متغیر refBook مثال قبل). اما کلاسها روش بهتری برای انجام اینکار و تعریف اشیاء هستند.
در ذیل تعریف اینترفیس کتابدار را با تک متد doWork آن ملاحظه میکنید:
متد doWork دارای پارامتری نیست و خروجی نیز ندارد. سپس با استفاده از واژهی کلیدی class، یک کلاس جدید را ایجاد کردهایم که با استفادهی واژهی کلیدی implements، یک پیاده سازی مشخص از اینترفیس Librarian را ارائه میدهد:
اکنون داخل این کلاس، پیاده سازی خاصی از متد doWork مشخص شدهی در قرارداد و اینترفیس Librarian را مشاهده میکنید.
در ادامه برای ایجاد شیءایی از روی این تعریف، به نحو ذیل عمل میکنیم:
در اینجا متغیر kidsLibrarian از نوع اینترفیس کتابدار تعریف شدهاست. به این معنا که شیءایی که به آن انتساب داده میشود باید این اینترفیس را پیاده سازی کند. این شیء نیز توسط واژهی کلیدی new، نمونه سازی/وهله سازی میشود. در ادامه میتوان به متدها و خواص شیء kidsLibrarian دسترسی یافت و آنها را فراخوانی کرد.
از آنجائیکه اینترفیسها به معنای نوعهای سفارشی هستند و جاوا اسکریپت از آنها پشتیبانی نمیکند، توسط کامپایلر TypeScript، به هیچ نوع کد معادلی در جاوا اسکریپت، ترجمه و تبدیل نخواهند شد. کامپایلر TypeScript تنها از آنها جهت بررسی نوعها استفاده میکند.
اینترفیسها به صورت مجموعهای از تعاریف خواص و متدها، بدون پیاده سازی آنها تعریف میشوند. پیاده سازی این اینترفیسها، توسط کلاسها و یا سایر اشیاء صورت خواهند گرفت. برای مثال یک قرارداد اجاره، مشخص میکند که آخر هر ماه چه مقداری را باید پرداخت کرد. اما این قرار داد مشخص نمیکند که چگونه باید این پرداخت صورت گیرد و از هر شخصی به شخص دیگری میتواند متفاوت باشد. به این حالت duck typing هم میگویند. به این معنا که قرار داد، شکل یک شیء را مشخص میکند و تا زمانیکه پیاده سازی کنندهی آن بتواند این قرارداد را تامین کند، میتواند بجای نوع اصلی نیز بکار گرفته شود.
Duck typing چیست؟
duck typing به این معنا است که اگر پرندهای بتواند مانند یک اردک راه برود، شنا کند و صدا در بیاورد، یک اردک نامیده میشود. بنابراین همینقدر که یک شیء بتواند قراردادی را پیاده سازی کند، نوع آن با نوع اینترفیس یکی درنظر گرفته میشود. برای نمونه به مثال ذیل دقت کنید:
interface Duck { walk: () => void; swim: () => void; quack: () => void; } let probablyADuck = { walk: () => console.log('walking like a duck'), swim: () => console.log('swimming like a duck'), quack: () => console.log('quacking like a duck') } function FlyOverWater(bird: Duck) { } FlyOverWater(probablyADuck); // works!
در ادامه متغیر و شیءایی بدون تعریف نوع آن ایجاد شدهاست که همان متدهای اینترفیس Duck را پیاده سازی میکند و امضای آنها با امضای متدهای اینترفیس Duck یکی هستند.
سپس متد FlyOverWater تعریف شده که در آن، نوع پارامتر ورودی آن به صورت صریحی به نوع اینترفیس Duck مقید شدهاست.
در سطر بعدی، این متد با دریافت شیء probablyADuck فراخوانی شدهاست و چون این شیء تمام اجزای قرارداد Duck را پیاده سازی کردهاست، مشکلی در اجرای آن نخواهد بود. به این حالت duck typing میگویند.
نحوهی تعریف یک اینترفیس در TypeScript
تعریف یک اینترفیس با واژهی کلیدی interface شروع شده و سپس خواص و متدهای مدنظر این قرارداد، به همراه نوع آنها تعریف خواهند شد:
interface Book { id: number; title: string; author: string; pages?: number; markDamaged: (reason: string) => void; }
در اینترفیسهای TypeScript میتوان خواص اختیاری و optional را نیز تعریف کرد. نمونهی آن خاصیت pages در این مثال است که با ? مشخص شدهاست و نمونهی آنرا در حین تعریف پارامترهای اختیاری متدها نیز پیشتر ملاحظه کرده بودید.
تعریف متدها در یک اینترفیس، با مشخص سازی نام آن متد و ذکر یک کولن و سپس مشخص سازی امضای پارامترهای دریافتی انجام میشود. نوع خروجی متد، در سمت راست علامت <= قرار خواهد گرفت.
استفاده از اینترفیسها برای تعریف نوع خروجی توابع
در مثال زیر، متد CreateCustomerID دارای دو پارامتر ورودی از نوعهای رشتهای و عددی است و خروجی آن نیز از نوع رشتهای تعریف شدهاست:
function CreateCustomerID(name: string, id: number): string { return name + id; }
let IdGenerator: (chars: string, nums: number) => string;
IdGenerator = CreateCustomerID;
interface StringGenerator { (chars: string, nums: number): string; }
اکنون میتوان نحوهی تعریف متغیر IdGenerator را به صورت زیر Refactor کرد و تغییر داد:
let IdGenerator: StringGenerator;
بسط و توسعهی اینترفیسها
بسط و توسعهی اینترفیسها شبیه به مباحث ارث بری هستند. به این ترتیب که با بسط یک اینترفیس از طریق اینترفیسی دیگر، میتوان به نوعی مرکب رسید:
interface LibraryResource { catalogNumber: number; } interface LibraryBook { title: string; } interface Encyclopedia extends LibraryResource, LibraryBook { volume: number; }
این نوع مرکب، علاوه بر دارا بودن خاصیت volume مختص به خودش، اکنون حاوی دو خاصیت موجود در سایر اینترفیسهای ذکر شدهی در قسمت extends نیز هست.
حال اگر متغیر جدیدی را از نوع Encyclopedia تعریف کنیم، جهت برآورده شده تمام اجزای قرارداد، لازم است هر سه خاصیت را مقدار دهی نمائیم:
let refBook: Encyclopedia = { catalogNumber: 1234, title: 'The Book of Everything', volume: 1 }
نوع کلاسها
مبحث کلاسها به صورت جداگانهای در این سری بررسی خواهند شد. اما جهت تکمیل بحث جاری نیاز است اشارهی کوتاهی به آنها شود.
همانطور که عنوان شد، اینترفیسها تنها شکل و قرارداد پیاده سازی یک شیء را تعریف میکنند؛ بدون ارائهی پیاده سازی خاصی از آنها. تا اینجا در بحث جاری، اشیاء را توسط object literals داخل {} تعریف کردیم (مانند متغیر refBook مثال قبل). اما کلاسها روش بهتری برای انجام اینکار و تعریف اشیاء هستند.
در ذیل تعریف اینترفیس کتابدار را با تک متد doWork آن ملاحظه میکنید:
interface Librarian { doWork: () => void; }
class ElementarySchoolLibrarian implements Librarian { doWork() { console.log('Reading to and teaching children...'); } }
در ادامه برای ایجاد شیءایی از روی این تعریف، به نحو ذیل عمل میکنیم:
let kidsLibrarian: Librarian = new ElementarySchoolLibrarian(); kidsLibrarian.doWork();
WTF is a personal information dashboard for your terminal, developed for those who spend most of their day in the command line.
بله. در قسمت استفاده از tortoisesvn در کتابچه فوق، نحوهی صحیح move کردن فایلها با تصویر توضیح داده شده است.
یا اگر نیاز به توضیحات بیشتری بود به مقاله زیر رجوع کنید (که همان روش فوق را توضیح داده است):
http://www.lostechies.com/blogs/joshua_lockwood/archive/2007/09/12/subversion-tip-of-the-day-moving-files.aspx
یا اگر نیاز به توضیحات بیشتری بود به مقاله زیر رجوع کنید (که همان روش فوق را توضیح داده است):
http://www.lostechies.com/blogs/joshua_lockwood/archive/2007/09/12/subversion-tip-of-the-day-moving-files.aspx
نظرات اشتراکها
چرا از آنگولار به ری اکت + ری داکس سوئیچ کردم!
- فسلفه React مبتنی بر مخلوط کردن جاوا اسکریپت و HTML با هم هست در فایلهای JSX (نوشتن HTML با کدهای جاوا اسکریپت). به این صورت شما مزیتهای ذاتی HTML و CSS را یکجا از دست میدید؛ چون دیگه نمیتونید HTML جدا یا CSS جدای از جاوا اسکریپت را داشته باشین. در حالیکه در Angular این دو یا این سه (TypeScript، HTML و CSS) از هم جدا هستند که مزیت آن دسترسی به انواع ادیتورهایی هست که بدون اینکه برای Angular نوشته شده باشند، در همان بدو معرفی آن، با آن سازگار هستند که سادگی توسعه را به همراه داره. شاید تولید کامپوننتهای ساده React تولید شده با کدهای جاوا اسکریپتی ساده باشه، اما کمی که حجم آن بیشتر شد، کنترل و مدیریت این مخلوط، سختتر و سختتر میشه و به علاوه مخلوط کردن کدهای یک فریم ورک با HTML و CSS خیلی شبیه به PHP کلاسیک و یا ASP کلاسیک هست و این روزها کسی را پیدا نمیکنید که برای پروژههای واقعی حتی از PHP در حالت کلاسیک آن بدون یک فریم ورک جانبی استفاده کنه. در Angular از همان بدو امر مباحث طراحی ماژولها، کامپوننتها و جدا سازی کدها به صورت ذاتی طراحی شدهاند.
- مزیت کار کردن با TypeScript در مقایسه با ES6 خالص در React، امکان دسترسی به کامپایل آفلاین هست و مباحث پیشرفتهی کامپایلر مانند tree-shaking (حذف کدهای مرده) و AOT (a head of time compilation) که سبب میشن هم حجم نهایی کمتری تولید شود و هم پیش از اجرای برنامه در مرورگر و سپس یافتن باگهای احتمالی در زمان اجرا، پیش از موعد و توسط کامپایلر این باگها گزارش شوند. اگر قصد داشته باشید به یک چنین کیفیت و بررسی کدی در React برسید، باید تعداد آزمونهای واحد قابل توجهی را داشته باشین تا بتونید یافتن مشکلاتی را که کامپایلر TypeScript گوشزد میکند، شبیه سازی کنید. همچنین شما در TypeScript میتونید به تمام امکانات پیشرفتهی زبان جاوا اسکریپت (حتی پس از ES6) دسترسی داشته باشید، اما کد نهایی جاوا اسکریپتی تولید شدهی توسط آنرا برای ES5 که تمام مرورگرها از آن پشتیبانی میکنند، تولید کنید که این هم خودش یک مزیت مهم هست. بنابراین TypeScript فقط یک static type checker ساده نیست.
- اینکه Angular یک فریمورک هست به خودی خودش یک مزیت مهم هست نسبت به React که یک کتابخانه است و اجزای آن باید از منابع مختلفی تهیه شوند. فریم ورک یعنی به روز رسانیهای منظم تمام اجزای آن توسط خود تیم Angular و سازگاری کامل و یکدست هر جزء با نگارش فعلی یا همان آخرین نگارش موجود. اگر با دنیای وابستگیهای ثالث در یک پروژهی واقعی کار کرده باشید به خوبی میدونید که هر چقدر تعداد آنها کمتر باشند، نگهداری طولانی مدت آن پروژه آسانتر میشود؛ چون روزی ممکن است آن کتابخانهی ثالث دیگر توسعه پیدا نکند، یا منسوخ شود یا دیرتر از آخرین نگارش ارائه شده به روز رسانی شود. مزیت داشتن یک فریم ورک یکدست، درگیر نشدن با این مسایل است؛ خصوصا اینکه عموما کتابخانههای ثالث کیفیتشون در حد کتابخانهی اصلی نیست و اینکه مثلا خود تیم Angular ماژول روتر، اعتبارسنجی یا فرمهای اون رو توسعه میده، قطعا کیفیتشون از کتابخانههای ثالث دیگه بهتر هست.
- در مورد سرعت و کارآیی و حتی مصرف حافظه، مطابق یک benchmarck خیلی معتبر، وضعیت Angular اندکی بهتر از React است؛ هرچند در کل از این لحاظ به هم نزدیک هستند.
- این مباحث انحصاری شدن و اینها هم در مورد محصولات سورس باز، زیاد مفهومی ندارند و بیشتر یکسری شعار ایدئولوژیک هست توسط کسانیکه حتی تغییر رفتار این شرکتها را هم دنبال نمیکنند و منابع و ماخذی رو که مطالعه کردن مربوط به یک دهه قبل هست.
- مزیت کار کردن با TypeScript در مقایسه با ES6 خالص در React، امکان دسترسی به کامپایل آفلاین هست و مباحث پیشرفتهی کامپایلر مانند tree-shaking (حذف کدهای مرده) و AOT (a head of time compilation) که سبب میشن هم حجم نهایی کمتری تولید شود و هم پیش از اجرای برنامه در مرورگر و سپس یافتن باگهای احتمالی در زمان اجرا، پیش از موعد و توسط کامپایلر این باگها گزارش شوند. اگر قصد داشته باشید به یک چنین کیفیت و بررسی کدی در React برسید، باید تعداد آزمونهای واحد قابل توجهی را داشته باشین تا بتونید یافتن مشکلاتی را که کامپایلر TypeScript گوشزد میکند، شبیه سازی کنید. همچنین شما در TypeScript میتونید به تمام امکانات پیشرفتهی زبان جاوا اسکریپت (حتی پس از ES6) دسترسی داشته باشید، اما کد نهایی جاوا اسکریپتی تولید شدهی توسط آنرا برای ES5 که تمام مرورگرها از آن پشتیبانی میکنند، تولید کنید که این هم خودش یک مزیت مهم هست. بنابراین TypeScript فقط یک static type checker ساده نیست.
- اینکه Angular یک فریمورک هست به خودی خودش یک مزیت مهم هست نسبت به React که یک کتابخانه است و اجزای آن باید از منابع مختلفی تهیه شوند. فریم ورک یعنی به روز رسانیهای منظم تمام اجزای آن توسط خود تیم Angular و سازگاری کامل و یکدست هر جزء با نگارش فعلی یا همان آخرین نگارش موجود. اگر با دنیای وابستگیهای ثالث در یک پروژهی واقعی کار کرده باشید به خوبی میدونید که هر چقدر تعداد آنها کمتر باشند، نگهداری طولانی مدت آن پروژه آسانتر میشود؛ چون روزی ممکن است آن کتابخانهی ثالث دیگر توسعه پیدا نکند، یا منسوخ شود یا دیرتر از آخرین نگارش ارائه شده به روز رسانی شود. مزیت داشتن یک فریم ورک یکدست، درگیر نشدن با این مسایل است؛ خصوصا اینکه عموما کتابخانههای ثالث کیفیتشون در حد کتابخانهی اصلی نیست و اینکه مثلا خود تیم Angular ماژول روتر، اعتبارسنجی یا فرمهای اون رو توسعه میده، قطعا کیفیتشون از کتابخانههای ثالث دیگه بهتر هست.
- در مورد سرعت و کارآیی و حتی مصرف حافظه، مطابق یک benchmarck خیلی معتبر، وضعیت Angular اندکی بهتر از React است؛ هرچند در کل از این لحاظ به هم نزدیک هستند.
- این مباحث انحصاری شدن و اینها هم در مورد محصولات سورس باز، زیاد مفهومی ندارند و بیشتر یکسری شعار ایدئولوژیک هست توسط کسانیکه حتی تغییر رفتار این شرکتها را هم دنبال نمیکنند و منابع و ماخذی رو که مطالعه کردن مربوط به یک دهه قبل هست.
نظرات مطالب
راه اندازی StimulSoft Report در ASP.NET MVC
سلام؛ بنده یک لیست تو در تو دارم؛ مثلا چندتا گروه دارم هر گروه چندتا آیتم داره:
ممنون میشم راهنماییم کنید چطور پیاده سازیش کنم.
[ { "day" : "۱۳۹۸/۱۰/۲۵", "plan" : "موردی", "rId" : 1, "records" : [ { "help" : "بسته غذایی", "rId" : 1 }, { "help" : "کمک مالی", "rId" : 1 } ] }, { "day" : "۱۳۹۸/۱۰/۱۶", "plan" : "مادرانه", "rId" : 1002, "records" : [ { "help" : "بسته غذایی", "rId" : 1002 }, { "help" : "تدریس", "rId" : 1002 } ] } ]