طراحی سایت و برنامه نویسی

آموزش طراحی سایت و برنامه نویسی

طراحی سایت و برنامه نویسی

آموزش طراحی سایت و برنامه نویسی

آموزش Vue.js: آشنایی با مفاهیم مقدماتی Vue — بخش اول

Vue یک فریمورک بسیار محبوب فرانت‌اند برای جاوا اسکریپت است که شاهد رشد بسیار بالایی بوده است. این فریمورک کوچک (حدوداً 24 کیلوبایت) و بسیار کارآمد است. این فریمورک از همه فریمورک‌های فرانت‌اند جاوا اسکریپت و کتابخانه‌های view دیگر متفاوت است. ما قصد داریم در یک سلسله مقالات دنباله‌دار در مجله فرادرس به بررسی همه‌جانبه این فریمورک بپردازیم. در اولین بخش برخی از مفاهیم مقدماتی Vue را بررسی می‌کنیم. اگر قصد دارید به طور کامل با این فریمورک آشنا شوید، پیشنهاد می‌کنیم با ما همراه باشید.

منظور از فریمورک فرانت‌اند جاوا اسکریپت چیست؟

اگر دقیقاً نمی‌دانید فریمورک جاوا اسکریپت به چه معنا است، بهترین فریمورکی که برای شروع می‌توانید انتخاب کنید Vue است.

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

تا اوایل دهه 2000 میلادی، مرورگرها امکاناتی که امروز دارند را نداشتند. آن مرورگرها قدرت کمی داشتند و ساخت اپلیکیشن‌های پیچیده درون آن‌ها از نظر عملکردی امکان‌پذیر نبود. ابزارهای مناسب چندانی نیز وجود نداشت.

همه این‌ها زمانی که گوگل اقدام به معرفی Google Maps و Gmail کرد، دچار تغییر شدند، زیرا این دو اپلیکیشن درون مرورگر اجرا می‌شدند. Ajax نیز امکان ایجاد درخواست‌های شبکه ناهمگام را فراهم ساخت. در طی زمان توسعه‌دهندگان شروع به ساخت اپلیکیشن‌هایی بر بستر وب کردند و در عین حال مهندسان روی خود پلتفرم یعنی مرورگرها، استانداردهای وب، API-های مرورگر و زبان جاوا اسکریپت کار کردند.

کتابخانه‌هایی مانند جی کوئری و Mootools نخستین پروژه‌های بزرگی بودند که بر مبنای جاوا اسکریپت ساخته شدند و برای مدتی بسیار محبوب بودند. این کتابخانه‌ها اساساً یک API-ی زیباتر برای تعامل با مرورگر ارائه می‌کردند و راه‌حل‌هایی برای باگ‌ها و ناهماهنگی‌های بین مرورگرهای مختلف تدارک می‌دیدند.

فریمورک‌هایی مانند Backbone ،Ember ،Knockout و AngularJS نخستین فریمورک‌های مدرن جاوا اسکریپت محسوب می‌شدند.

موج دومی که در حال حاضر شاهد آن هستیم React ،Angular و Vue بازیگران عمده آن هستند.

توجه کنید که jQuery ،Ember و دیگر پروژه‌هایی که اشاره کردیم، همچنان به صورت گسترده مورد استفاده قرار می‌گیرند، فعالانه نگهداری می‌شوند و میلیون‌ها وب‌سایت بر آن‌ها تکیه دارند.

با این حال، تکنیک‌ها و ابزارها تکامل یافته‌اند و شما به عنوان یک توسعه‌دهنده جاوا اسکریپت اکنون به جای آشنایی با فریمورک‌های قدیمی‌تر، نیازمند دانستن React ،Angular یا Vue هستید.

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

استفاده از فریمورک، شبیه به چیزی مانند استفاده از زبان برنامه‌نویسی C به جای استفاده از زبان اسمبلی برای نوشتن برنامه‌های سیستمی است. این فرایند مانند آن است که به جای ماشین تایپ از رایانه برای نوشتن اسناد استفاده کنیم. توصیف دیگر آن مانند استفاده از یک اتومبیل خودران به جای راندن خودروی معمولی است.

البته شاید در تمثیل کمی زیاده‌روی کرده باشیم، اما ایده کلی چنین است. به جای استفاده از API–های سطح پایین که از سوی مرورگر برای دستکاری عناصر ارائه می‌شوند و ساخت سیستم‌های بسیار پیچیده برای نوشتن یک اپلیکیشن، می‌توان از ابزارهای ساخته شده از سوی افراد بسیار باهوش استفاده کرد تا همه کارها آسان‌تر شوند.

محبوبیت Vue

اگر می‌خواهید بدانید فریمورک Vue چقدر محبوبیت دارید، باید اشاره کنیم که این فریمورک:

  • در سال 2016، هفت هزار و ششصد ستاره در گیت‌هاب داشته است.
  • این ستاره‌ها در سال 2017 به تعداد 36.700 رسیده است.
  • این ستاره‌ها در زمان نگارش این مقاله در سال 2019 به عدد 150.000 نزدیک شد‌ه‌اند.
  • تعداد دانلود npm آن در حال حاضر هر هفته در حدود 350.000 است.

با توجه به اعداد و ارقام فوق می‌توان گفت که Vue محبوبیت بالایی دارد. این میزان محبوبیت را می‌توان با ستاره‌های گیت‌هاب React مقایسه کرد که سال‌ها قبل‌تر عرضه شده است.

البته اعداد گویای همه واقعیت‌ها نیستند. Vue واقعاً مورد علاقه توسعه‌دهندگان است.

یک نکته کلیدی در زمان ظهور Vue گسترش استفاده از آن در اکوسیستم لاراول بود. لاراول یک فریمورک وب اپلیکیشن PHP بسیار محبوب است. اما از آن زمان به بعد Vue در میان جوامع توسعه دیگر نیز گسترش یافته است.

چرا Vue محبوب توسعه‌دهندگان است؟

ابتدا باید گفت که Vue یک فریمورک «پیشرونده» (Progressive) است. این بدان معنی است که با نیازهای توسعه‌دهنده تطبیق پیدا می‌کند. فریمورک‌های دیگر نیازمند یک فرایند استفاده کامل از سوی توسعه‌دهنده یا تیم توسعه هستند و در اغلب موارد باید اپلیکیشن موجود را به طور کامل بازنویسی کرد، زیرا نیازمند مجموعه قراردادهای خاصی است. Vue عموماً از طریق یک تگ ساده script درون اپلیکیشن شما قرار می‌گیرند و بسته به نیازهای شما می‌تواند رشد پیدا کند و از 3 خط تا حدی گسترش پیدا کند که کل لایه view شما را مدیریت کند.

برای شروع استفاده از vue نیاز نیست در مورد webpack ،Babel ،npm یا هر چیز دیگری اطلاع داشته باشید. اما در زمان مقتضی Vue امکان استفاده از آن‌ها را به سادگی برای شما فراهم می‌سازد.

این نکته با توجه به اکوسیستم کنونی فریمورک فرانت‌اند و کتابخانه‌های جاوا اسکریپت که می‌خواهند افراد مبتدی و همچنین خبره را که در اقیانوسی از امکانات و گزینه‌ها غرق شده‌اند جذب خود کنند بسیار حیاتی محسوب می‌شود.

Vue.js احتمالاً سهل‌الوصول‌ترین فریمورک فرانت‌اند موجود است. برخی افراد آن را جی‌کوئری جدید می‌نامند، زیرا به سادگی از طریق یک تگ اسکریپت درون اپلیکیشن جای می‌گیرند و به‌تدریج فضای مورد نیاز خود را به دست می‌آورد. این تعریف را می‌توان یک تحسین تلقی کرد، زیرا جی‌کوئری سال‌ها است که در بر پلتفرم وب تسلط یافته و همچنان در بخش وسیعی از وب‌سایت‌ها سرویس‌دهی می‌کند.

Vue با انتخاب بهترین ایده‌های فریمورک‌هایی مانند انگولار، ری‌اکت، Knockout و با گزینش بهترین امکانات آن فریمورک‌ها ساخته شده است. همچنین امکانات کمتر مورد استفاده فریمورک‌های دیگر حذف شده و بدین ترتیب نوعی گلچین فریمورک‌های دیگر ساخته شده است.

جایگاه Vue.js در میان فریمورک‌های فرانت‌اند کجا است؟

زمانی که از توسعه وب صحبت می‌کنیم، دو غول بزرگ وجود دارند که انگولار و ری‌اکت هستند. بدین ترتیب Vue چگونه جایگاه خود را در رابطه با آن دو فریمورک محبوب و بزرگ تعریف می‌کند؟

Vue از سوی Evan You زمانی که در گوگل و بر روی اپلیکیشن‌های AngularJS یا همان Angular 1.0 کار می‌کرد ساخته شده است. در واقع دلیل تولید آن نیاز به ایجاد اپلیکیشن‌هایی با کارایی بالا بوده است. Vue ساختار قالب‌بندی انگولار را برگزیده، اما ساختار سخت‌گیرانه و پیچیده‌ای که انگولار نیاز دارد را حذف کرده و آن را کارآمدتر ساخته است.

انگولار جدید (انگولار 2.0) بسیاری از مشکلات AngularJS را حذف کرده است، اما روش آن کاملاً متفاوت است. انگولار 2 همچنین نیازمند تایپ‌اسکریپت است که استفاده از آن یا دست‌کم یادگیری‌اش مورد علاقه همه توسعه‌دهندگان نیست.

در مورد ری‌اکت نیز می‌توان گفت که Vue ایده‌های خوب زیادی از آن اخذ کرده است که مهم‌ترینشان DOM مجازی است. اما Vue آن را با نوعی مدیریت وابستگی خودکار پیاده‌سازی کرده است. بدین ترتیب کامپوننت‌هایی که از تغییر حالت (State) متأثر می‌شوند، به طور خودکار ردگیری شده و تنها آن کامپوننت‌ها در زمان تغییر یافتن مشخصه حالت مجدداً رندر می‌شوند.

از سوی دیگر در React زمانی که بخشی از حالت که روی کامپوننت تأثیر می‌گذارد تغییر پیدا کند، کامپوننت مجدداً رندر خواهد شد. برای اجتناب از این وضعیت باید از متد shouldComponentUpdate هر کامپوننت استفاده کرد تا مشخص شود که آن کامپوننت نیاز به رندر مجدد دارد یا نه. بدین ترتیب Vue برحسب سهولت استفاده مزیت بیشتری دارد و به طور پیش‌فرض بهبود عملکرد خوبی ارائه می‌کند.

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

قالب‌های Vue بسیار شبیه به Mustache و Handlebars هستند، هر چند برحسب انعطاف‌پذیری تفاوت‌هایی دارند. بدین ترتیب برای توسعه‌دهندگانی که از قبل از فریمورک‌هایی مانند انگولار یا Ember استفاده کرده‌اند، آشناتر هستند.

کتابخانه رسمی مدیریت حالت Vuex از معماری Flux پیروی می‌کند و مفاهیم آن تا حدودی شبیه به Redux است. در این مورد نیز این بخش یکی از مزیت‌های Vue محسوب می‌شود که یکی از الگوهای خوب React را مشاهده کرده و آن را در اکوسیستم خود مورد استفاده قرار داده است. با این که می‌توان از Redux به همراه Vue استفاده کرد، اما Vuex به طور خاص برای Vue و سازوکار درونی آن مناسب‌سازی شده است.

Vue انعطاف‌پذیر است، اما این واقعیت که تیم مرکزی دو پکیج را مدیریت می‌کنند که برای هر وب اپلیکیشن حائز اهمیت هستند (یعنی مسیریابی و مدیریت حالت) موجب شده که یکپارچگی آن بیش از React باشد. برای نمونه vue-router و vuex و کلید موفقیت Vue محسوب می‌شوند.

بدن ترتیب دیگر در زمان انتخاب کتابخانه‌ها جای نگرانی نخواهد بود که آیا این کتابخانه در آینده نیز همچنان نگهداری می‌شود و آیا به‌روزرسانی خواهد شد یا نه. از آنجا که این کتابخانه‌ها رسمی هستند، می‌توانید با خیال راحت از آن‌ها استفاده کنید. البته همچنان امکان استفاده از کتابخانه‌های دیگر نیز وجود دارد.

یکی از نکاتی که موجب می‌شود Vue در قیاس با React و Angular در جایگاه متفاوتی قرار گیرد، این است که یک پروژه indie است، یعنی از سوی شرکت‌های بزرگی مانند فیسبوک یا گوگل پشتیبانی نمی‌شود.

در عوض به طور کامل از سوی جامعه پشتیبانی می‌شود و توسعه‌اش را مدیون اسپانسرها و حمایت‌های مالی مختلف است. بدین ترتیب می‌توان مطمئن بود که Vue برحسب برنامه‌های کاری یک شرکت منفرد توسعه نمی‌یابد.

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

منبع: فرادرس


آموزش Vue.js: آشنایی با مفاهیم مقدماتی Vue — بخش اول

Vue یک فریمورک بسیار محبوب فرانت‌اند برای جاوا اسکریپت است که شاهد رشد بسیار بالایی بوده است. این فریمورک کوچک (حدوداً 24 کیلوبایت) و بسیار کارآمد است. این فریمورک از همه فریمورک‌های فرانت‌اند جاوا اسکریپت و کتابخانه‌های view دیگر متفاوت است. ما قصد داریم در یک سلسله مقالات دنباله‌دار در مجله فرادرس به بررسی همه‌جانبه این فریمورک بپردازیم. در اولین بخش برخی از مفاهیم مقدماتی Vue را بررسی می‌کنیم. اگر قصد دارید به طور کامل با این فریمورک آشنا شوید، پیشنهاد می‌کنیم با ما همراه باشید.

منظور از فریمورک فرانت‌اند جاوا اسکریپت چیست؟

اگر دقیقاً نمی‌دانید فریمورک جاوا اسکریپت به چه معنا است، بهترین فریمورکی که برای شروع می‌توانید انتخاب کنید Vue است.

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

تا اوایل دهه 2000 میلادی، مرورگرها امکاناتی که امروز دارند را نداشتند. آن مرورگرها قدرت کمی داشتند و ساخت اپلیکیشن‌های پیچیده درون آن‌ها از نظر عملکردی امکان‌پذیر نبود. ابزارهای مناسب چندانی نیز وجود نداشت.

همه این‌ها زمانی که گوگل اقدام به معرفی Google Maps و Gmail کرد، دچار تغییر شدند، زیرا این دو اپلیکیشن درون مرورگر اجرا می‌شدند. Ajax نیز امکان ایجاد درخواست‌های شبکه ناهمگام را فراهم ساخت. در طی زمان توسعه‌دهندگان شروع به ساخت اپلیکیشن‌هایی بر بستر وب کردند و در عین حال مهندسان روی خود پلتفرم یعنی مرورگرها، استانداردهای وب، API-های مرورگر و زبان جاوا اسکریپت کار کردند.

کتابخانه‌هایی مانند جی کوئری و Mootools نخستین پروژه‌های بزرگی بودند که بر مبنای جاوا اسکریپت ساخته شدند و برای مدتی بسیار محبوب بودند. این کتابخانه‌ها اساساً یک API-ی زیباتر برای تعامل با مرورگر ارائه می‌کردند و راه‌حل‌هایی برای باگ‌ها و ناهماهنگی‌های بین مرورگرهای مختلف تدارک می‌دیدند.

فریمورک‌هایی مانند Backbone ،Ember ،Knockout و AngularJS نخستین فریمورک‌های مدرن جاوا اسکریپت محسوب می‌شدند.

موج دومی که در حال حاضر شاهد آن هستیم React ،Angular و Vue بازیگران عمده آن هستند.

توجه کنید که jQuery ،Ember و دیگر پروژه‌هایی که اشاره کردیم، همچنان به صورت گسترده مورد استفاده قرار می‌گیرند، فعالانه نگهداری می‌شوند و میلیون‌ها وب‌سایت بر آن‌ها تکیه دارند.

با این حال، تکنیک‌ها و ابزارها تکامل یافته‌اند و شما به عنوان یک توسعه‌دهنده جاوا اسکریپت اکنون به جای آشنایی با فریمورک‌های قدیمی‌تر، نیازمند دانستن React ،Angular یا Vue هستید.

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

استفاده از فریمورک، شبیه به چیزی مانند استفاده از زبان برنامه‌نویسی C به جای استفاده از زبان اسمبلی برای نوشتن برنامه‌های سیستمی است. این فرایند مانند آن است که به جای ماشین تایپ از رایانه برای نوشتن اسناد استفاده کنیم. توصیف دیگر آن مانند استفاده از یک اتومبیل خودران به جای راندن خودروی معمولی است.

البته شاید در تمثیل کمی زیاده‌روی کرده باشیم، اما ایده کلی چنین است. به جای استفاده از API–های سطح پایین که از سوی مرورگر برای دستکاری عناصر ارائه می‌شوند و ساخت سیستم‌های بسیار پیچیده برای نوشتن یک اپلیکیشن، می‌توان از ابزارهای ساخته شده از سوی افراد بسیار باهوش استفاده کرد تا همه کارها آسان‌تر شوند.

محبوبیت Vue

اگر می‌خواهید بدانید فریمورک Vue چقدر محبوبیت دارید، باید اشاره کنیم که این فریمورک:

  • در سال 2016، هفت هزار و ششصد ستاره در گیت‌هاب داشته است.
  • این ستاره‌ها در سال 2017 به تعداد 36.700 رسیده است.
  • این ستاره‌ها در زمان نگارش این مقاله در سال 2019 به عدد 150.000 نزدیک شد‌ه‌اند.
  • تعداد دانلود npm آن در حال حاضر هر هفته در حدود 350.000 است.

با توجه به اعداد و ارقام فوق می‌توان گفت که Vue محبوبیت بالایی دارد. این میزان محبوبیت را می‌توان با ستاره‌های گیت‌هاب React مقایسه کرد که سال‌ها قبل‌تر عرضه شده است.

البته اعداد گویای همه واقعیت‌ها نیستند. Vue واقعاً مورد علاقه توسعه‌دهندگان است.

یک نکته کلیدی در زمان ظهور Vue گسترش استفاده از آن در اکوسیستم لاراول بود. لاراول یک فریمورک وب اپلیکیشن PHP بسیار محبوب است. اما از آن زمان به بعد Vue در میان جوامع توسعه دیگر نیز گسترش یافته است.

چرا Vue محبوب توسعه‌دهندگان است؟

ابتدا باید گفت که Vue یک فریمورک «پیشرونده» (Progressive) است. این بدان معنی است که با نیازهای توسعه‌دهنده تطبیق پیدا می‌کند. فریمورک‌های دیگر نیازمند یک فرایند استفاده کامل از سوی توسعه‌دهنده یا تیم توسعه هستند و در اغلب موارد باید اپلیکیشن موجود را به طور کامل بازنویسی کرد، زیرا نیازمند مجموعه قراردادهای خاصی است. Vue عموماً از طریق یک تگ ساده script درون اپلیکیشن شما قرار می‌گیرند و بسته به نیازهای شما می‌تواند رشد پیدا کند و از 3 خط تا حدی گسترش پیدا کند که کل لایه view شما را مدیریت کند.

برای شروع استفاده از vue نیاز نیست در مورد webpack ،Babel ،npm یا هر چیز دیگری اطلاع داشته باشید. اما در زمان مقتضی Vue امکان استفاده از آن‌ها را به سادگی برای شما فراهم می‌سازد.

این نکته با توجه به اکوسیستم کنونی فریمورک فرانت‌اند و کتابخانه‌های جاوا اسکریپت که می‌خواهند افراد مبتدی و همچنین خبره را که در اقیانوسی از امکانات و گزینه‌ها غرق شده‌اند جذب خود کنند بسیار حیاتی محسوب می‌شود.

Vue.js احتمالاً سهل‌الوصول‌ترین فریمورک فرانت‌اند موجود است. برخی افراد آن را جی‌کوئری جدید می‌نامند، زیرا به سادگی از طریق یک تگ اسکریپت درون اپلیکیشن جای می‌گیرند و به‌تدریج فضای مورد نیاز خود را به دست می‌آورد. این تعریف را می‌توان یک تحسین تلقی کرد، زیرا جی‌کوئری سال‌ها است که در بر پلتفرم وب تسلط یافته و همچنان در بخش وسیعی از وب‌سایت‌ها سرویس‌دهی می‌کند.

Vue با انتخاب بهترین ایده‌های فریمورک‌هایی مانند انگولار، ری‌اکت، Knockout و با گزینش بهترین امکانات آن فریمورک‌ها ساخته شده است. همچنین امکانات کمتر مورد استفاده فریمورک‌های دیگر حذف شده و بدین ترتیب نوعی گلچین فریمورک‌های دیگر ساخته شده است.

جایگاه Vue.js در میان فریمورک‌های فرانت‌اند کجا است؟

زمانی که از توسعه وب صحبت می‌کنیم، دو غول بزرگ وجود دارند که انگولار و ری‌اکت هستند. بدین ترتیب Vue چگونه جایگاه خود را در رابطه با آن دو فریمورک محبوب و بزرگ تعریف می‌کند؟

Vue از سوی Evan You زمانی که در گوگل و بر روی اپلیکیشن‌های AngularJS یا همان Angular 1.0 کار می‌کرد ساخته شده است. در واقع دلیل تولید آن نیاز به ایجاد اپلیکیشن‌هایی با کارایی بالا بوده است. Vue ساختار قالب‌بندی انگولار را برگزیده، اما ساختار سخت‌گیرانه و پیچیده‌ای که انگولار نیاز دارد را حذف کرده و آن را کارآمدتر ساخته است.

انگولار جدید (انگولار 2.0) بسیاری از مشکلات AngularJS را حذف کرده است، اما روش آن کاملاً متفاوت است. انگولار 2 همچنین نیازمند تایپ‌اسکریپت است که استفاده از آن یا دست‌کم یادگیری‌اش مورد علاقه همه توسعه‌دهندگان نیست.

در مورد ری‌اکت نیز می‌توان گفت که Vue ایده‌های خوب زیادی از آن اخذ کرده است که مهم‌ترینشان DOM مجازی است. اما Vue آن را با نوعی مدیریت وابستگی خودکار پیاده‌سازی کرده است. بدین ترتیب کامپوننت‌هایی که از تغییر حالت (State) متأثر می‌شوند، به طور خودکار ردگیری شده و تنها آن کامپوننت‌ها در زمان تغییر یافتن مشخصه حالت مجدداً رندر می‌شوند.

از سوی دیگر در React زمانی که بخشی از حالت که روی کامپوننت تأثیر می‌گذارد تغییر پیدا کند، کامپوننت مجدداً رندر خواهد شد. برای اجتناب از این وضعیت باید از متد shouldComponentUpdate هر کامپوننت استفاده کرد تا مشخص شود که آن کامپوننت نیاز به رندر مجدد دارد یا نه. بدین ترتیب Vue برحسب سهولت استفاده مزیت بیشتری دارد و به طور پیش‌فرض بهبود عملکرد خوبی ارائه می‌کند.

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

قالب‌های Vue بسیار شبیه به Mustache و Handlebars هستند، هر چند برحسب انعطاف‌پذیری تفاوت‌هایی دارند. بدین ترتیب برای توسعه‌دهندگانی که از قبل از فریمورک‌هایی مانند انگولار یا Ember استفاده کرده‌اند، آشناتر هستند.

کتابخانه رسمی مدیریت حالت Vuex از معماری Flux پیروی می‌کند و مفاهیم آن تا حدودی شبیه به Redux است. در این مورد نیز این بخش یکی از مزیت‌های Vue محسوب می‌شود که یکی از الگوهای خوب React را مشاهده کرده و آن را در اکوسیستم خود مورد استفاده قرار داده است. با این که می‌توان از Redux به همراه Vue استفاده کرد، اما Vuex به طور خاص برای Vue و سازوکار درونی آن مناسب‌سازی شده است.

Vue انعطاف‌پذیر است، اما این واقعیت که تیم مرکزی دو پکیج را مدیریت می‌کنند که برای هر وب اپلیکیشن حائز اهمیت هستند (یعنی مسیریابی و مدیریت حالت) موجب شده که یکپارچگی آن بیش از React باشد. برای نمونه vue-router و vuex و کلید موفقیت Vue محسوب می‌شوند.

بدن ترتیب دیگر در زمان انتخاب کتابخانه‌ها جای نگرانی نخواهد بود که آیا این کتابخانه در آینده نیز همچنان نگهداری می‌شود و آیا به‌روزرسانی خواهد شد یا نه. از آنجا که این کتابخانه‌ها رسمی هستند، می‌توانید با خیال راحت از آن‌ها استفاده کنید. البته همچنان امکان استفاده از کتابخانه‌های دیگر نیز وجود دارد.

یکی از نکاتی که موجب می‌شود Vue در قیاس با React و Angular در جایگاه متفاوتی قرار گیرد، این است که یک پروژه indie است، یعنی از سوی شرکت‌های بزرگی مانند فیسبوک یا گوگل پشتیبانی نمی‌شود.

در عوض به طور کامل از سوی جامعه پشتیبانی می‌شود و توسعه‌اش را مدیون اسپانسرها و حمایت‌های مالی مختلف است. بدین ترتیب می‌توان مطمئن بود که Vue برحسب برنامه‌های کاری یک شرکت منفرد توسعه نمی‌یابد.

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

منبع: فرادرس


پروتکل های اپلیکیشن در شبکه های کامپیوتری — راهنمای جامع

چند پروتکل برای کاربران در لایه اپلیکیشن شبکه‌های کامپیوتری وجود دارند. پروتکل های اپلیکیشن را می‌توان به طور عمده به دو دسته تقسیم کرد:

  • پروتکل‌هایی که از سوی کاربران استفاده می‌شوند. برای نمونه برای ایمیل از پروتکل eMail استفاده می‌شود.
  • پروتکل‌هایی مانند DNS که به پروتکل‌های استفاده شده از سوی کاربران کمک و پشتیبانی می‌کند.

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

سیستم نام دامنه

سیستم نام دامنه (DNS) روی مدل کلاینت سرور عمل می‌کند. این پروتکل از پروتکل UDP برای ارتباط‌های لایه انتقال بهره می‌گیرد. DNS از طرح نام‌گذاری مبتنی بر دامنه سلسله‌مراتبی استفاده می‌کند. سرور DNS با نام‌های دامنه جامع‌الشرایط (FQDN) و نشانی‌های ایمیل پیکربندی می‌شود که به نشانی‌های پروتکل اینترنتی متناظر نگاشت شده‌اند.

از سرور DNS تقاضای FQDN می‌شود و این سرور نشانی IP نگاشت شده به آن را بازگشت می‌دهد. DNS از پورت 53 UDP استفاده می‌کند.

پروتکل ساده انتقال نامه

«پروتکل ساده انتقال نامه» (Simple Mail Transfer Protocol) یا به اختصار SMTP برای انتقال نامه‌های الکترونیکی از یک کاربر به کاربر دیگر مورد استفاده قرار می‌گیرند. این وظیفه به وسیله نرم‌افزار کلاینت ایمیل که کاربر مورد استفاده قرار می‌دهد اجرا می‌شود. این نرم‌افزارها به کاربر کمک می‌کنند که ایمیل خود را تایپ و قالب‌بندی کند و آن را تا زمانی که به اینترنت دسترسی پیدا می‌کند ذخیره سازد. زمانی که یک ایمیل آماده ارسال می‌شود، فرایند ارسال به وسیله «عامل انتقال پیام» (Message Transfer Agent) مدیریت می‌شود که به طور معمول در نرم‌افزار کلاینت ایمیل جاسازی شده است.

عامل انتقال پیام از پروتکل STMP برای ارسال ایمیل به عامل انتقال پیام دیگر (سمت سرور) استفاده می‌کند. با این که SMTP از سوی کاربر نهایی صرفاً برای ارسال ایمیل استفاده می‌شود، سرورها به طور معمول از STMP برای ارسال و همچنین دریافت ایمیل‌ها استفاده می‌کنند. STMP از پورت TCP شماره‌های 25 و 587 استفاده می‌کند.

نرم‌افزار کلاینت از «پروتکل دسترسی پیام اینترنتی» (Internet Message Access Protocol) یا به اختصار IMAP یا پروتکل‌های POP برای دریافت ایمیل‌ها استفاده می‌کند.

پروتکل انتقال فایل

«پروتکل انتقال فایل» (The File Transfer Protocol) یا به اختصار FTP به طور گسترده برای انتقال فایل روی شبکه استفاده می‌شود. FTP از ارتباط TCP/IP استفاده و روی پورت 21 TCP کار می‌کند.

کلاینت از سرور یک فایل تقاضا می‌کند. زمانی که سرور یک درخواست برای فایل دریافت می‌کند، یک اتصال TCP برای کلاینت باز می‌کند و فایل را انتقال می‌دهد. پس از این که انتقال فایل پایان یافت، سرور اتصال را می‌بندد. کلاینت برای فایل دوم دوباره تقاضا می‌فرستد و سرور یک اتصال جدید TCP باز می‌کند.

پروتکل پست آفیس (POP)

پروتکل پست آفیس نسخه 3 یا POP3 یک پروتکل ساده بازیابی ایمیل است که از سوی عوامل کاربر (نرم‌افزار ایمیل کلاینت) برای بازیابی ایمیل‌ها از سرور ایمیل مورد استفاده قرار می‌گیرند.

زمانی که کلاینت به بازیابی ایمیل‌ها از سرور نیاز پیدا می‌کند، یک اتصال با سرور روی پورت 100 TCP باز می‌کند. سپس کاربر می‌تواند به ایمیل‌های خود دسترسی یافته و آن‌ها را روی رایانه لوکال خود دانلود کند. POP3 در دو حالت کار می‌کند. رایج‌ترین حالت، «حالت حذف» (delete mode) است که برای حذف ایمیل‌ها از سرور ریموت پس از دانلود شدن روی ماشین محلی استفاده می‌شود. حالت دوم «حالت حفظ» (Keep Mode) است که در آن ایمیل‌ها از سرور حذف نمی‌شوند و گزینه‌ای در اختیار کاربر قرار می‌گیرد که می‌تواند در ادامه به ایمیل‌ها روی سرور ایمیل دسترسی پیدا کند.

پروتکل انتقال ابرمتن

«پروتکل انتقال ابرمتن» (Hyper Text Transfer Protocol) یا به اختصار HTTP مبنای وب جهان‌گستر را تشکیل داده است. ابرمتن یا هایپرتکست یک سیستم مستندسازی کاملاً سازمان‌یافته است که از هایپرلینک‌ها برای اتصال صفحه‌های مختلف در اسناد متنی استفاده می‌کند. HTTP در مدل کلاینت/سرور عمل می‌کند. زمانی که کاربری درخواست دسترسی به یک صفحه HTTP را روی اینترنت می‌کند، ماشین کلاینت در سمت کاربر یک اتصال TCP روی پورت 80 با سرور باز می‌کند. زمانی که سرور درخواست کلاینت را بپذیرد، کلاینت اجازه دسترسی به صفحه‌های وب را پیدا می‌کند.

کلاینت برای دسترسی به صفحه‌های وب به طور معمول از مرورگرهای وب استفاده می‌کند که مسئول آغاز، نگهداری و بستن اتصال‌های TCP هستند. HTTP یک پروتکل بی‌حالت (Stateless) است، یعنی سرور هیچ اطلاعاتی در مورد درخواست‌های قبلی کلاینت‌ها نگهداری نمی‌کند.

نسخه‌های مختلف HTTP به صورت زیر هستند:

  • HTTP 1.0 از HTTP غیردائمی استفاده می‌کند. بدین ترتیب حداکثر یک شیء می‌تواند روی یک اتصال TCP منفرد ارسال شود.
  • HTTP 1.1 از HTTP دائمی استفاده می‌کند. در این نسخه اشیای چندگانه را می‌توان روی یک اتصال TCP منفرد ارسال کرد.
  • HTTP 2 موجب بهبود قابل توجهی در سرعت و امنیت اتصال‌های TCP شده است.

منبع: فرادرس


۱۰ اشتباه رایج در پروژه های Go — راهنمای کاربردی

 برنامه نویسی  2 بازدید

در این مقاله به بررسی فهرستی از 10 اشتباه رایج در پروژه های Go پرداخته‌ایم. توجه داشته باشید که ترتیب بیان اشتباه‌ها لزوماً نشان‌دهنده اهمیت آن‌ها نیست.

مقدار Enum ناشناس

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

در این مثال ما یک enum با استفاده از iota ساختیم که حالت زیر را ایجاد می‌کند:

StatusOpen = 0
StatusClosed = 1
StatusUnknown = 2

اکنون تصور کنید این نوع Status بخشی از یک درخواست JSON باشد و قرار است marshalled/unmarshalled شود. می‌توان ساختار زیر را طراحی کرد:

سپس درخواست‌هایی مانند زیر می‌گیریم:

در کد فوق هیچ چیز خاصی وجود ندارد، وضعیت به صورت unmarshalled و StatusOpen است. اینک درخواست دیگری در نظر می‌گیریم که به هر دلیلی مقدار حالت تعیین نشده است:

در این حالت، فیلد Status مربوط به ساختار Request مقدار اولیه‌ای برابر با مقدار صفر می‌گیرند. از این رو به جای StatusUnknown حالت StatusOpen دارد. بهترین رویه این است که مقدار ناشناس را به صورت یک enum با مقدار صفر تعیین کنیم:

در این صورت اگر وضعیت، بخشی از درخواست JSON نباشد، مقدار اولیه آن برابر انتظار ما به صورت StatusUnknown خواهد بود.

بنچمارک کردن

بنچمارک کردن صحیح کار دشواری است. عوامل زیادی وجود دارند که می‌توانند بر نتیجه مفروض تأثیر بگذارند. یکی از رایج‌ترین اشتباه‌ها این است که گول برخی بهینه‌سازی‌های کامپایلر را بخوریم. مثال دقیق زیر را از کتابخانه teivah/bitvector در نظر بگیرید:

این تابع بیت‌های درون یک بازه مفروض را پاک می‌کند. برای تهیه بنچمارک از آن می‌توان به صورت زیر عمل کرد:

در این بنچمارک، کامپایلر متوجه خواهد شد که clear یک «تابع برگ» (leaf function) است، یعنی هیچ تابع دیگری را فراخوانی نمی‌کند و از این رو آن را inline خواهد کرد. زمانی که inline شد، متوجه خواهد شد که برخی عوارض جانبی دارد. بنابراین فراخوانی clear به سادگی پاک می‌شود و نتایج نادقیقی تولید می‌کند.

یک گزینه می‌تواند این باشد که نتیجه را به یک متغیر سراسری به صورت زیر تعیین کنیم:

در کد فوق کامپایلر، نمی‌داند که فراخوانی عارضه جانبی تولید می‌کند یا نه. از این رو بنچمارک کردن درست خواهد بود.

اشاره‌گرها اینجا، اشاره‌گرها آنجا

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

اگر شما نیز بر این باور هستید، نگاهی به مثال زیر بیندازید:

کد فوق یک بنچمارک روی یک ساختار داده 0.3 کیلوبایتی است که ابتدا به وسیله اشاره‌گر و سپس با مقدار ارسال و دریافت می‌شود. 0.3 کیلوبایت مقدار زیادی نیست و از نوع ساختار داده‌هایی که به طور روزمره می‌بینیم نیز فاصله چندانی ندارد.

زمانی که این بنچمارک را روی محیط محلی اجرا کنید، می‌بینید که ارسال با مقدار، بیش از 4 بار سریع‌تر از ارسال با اشاره‌گر است. این موضوع تا حدود خلاف درک شهودی ما است.

توضیح این نتیجه به شیوه مدیریت حافظه در Go ارتباط دارد. توضیح کامل آن خارج از حوصله این مقاله است، اما تلاش می‌کنیم به صورت فشرده به دلیل این مسئله اشاره کنیم.

یک متغیر می‌تواند روی هیپ یا پشته تخصیص یابد. بنابراین به صورت خلاصه:

  • پشته شامل متغیرهای مداوم برای یک goroutine مفروض است. زمانی که تابع بازگشت می‌یابد، متغیرها از پشته برداشته (pop) می‌شوند.
  • هیپ شامل متغیرهای مشترک یعنی متغیرهای سراسری و امثال آن است.

مثال ساده زیر را که یک مقدار بازگشت می‌دهد، در نظر بگیرید:

در کد فوق، متغیر result از سوی goroutine جاری ایجاد شده است. این متغیر به پشته جاری push می‌شود. زمانی که تابع بازگشت یابد، کلاینت یک کپی از این متغیر دریافت خواهد کرد. متغیر خودش از پشته pop می‌شود. این متغیر همچنان در حافظه وجود دارد تا این که از سوی متغیر دیگری پاک شود، اما دیگر نمی‌توان به آن دسترسی یافت.

اینک همان مثال را با اشاره‌گر در نظر بگیرید:

متغیر result همچنان از سوی goroutine جاری ایجاد شده است، اما کلاینت یک اشاره‌گر یعنی یک آدرس متغیر دریافت خواهد کرد. اگر متغیر result از پشته برداشته شود، کلاینت‌های تابع دیگر نمی‌تواند به آن دسترسی پیدا کند.

در این سناریو کامپایلر Go متغیر result را به مکانی منتقل می‌کند که بتواند به اشتراک گذارده شود و اینجا مکانی نیست به جز هیپ.

با این حال ارسال اشاره‌گر نیز یک سناریوی دیگر است. برای مثال:

از آنجا که f را درون همان goroutine فراخوانی می‌کنیم، متغیر p نیازی به انتقال ندارد. این متغیر به سادگی به پشته پوش می‌شود و تابع فرعی می‌تواند به آن دسترسی داشته باشد.

برای نمونه این یک نتیجه مستقیم دریافت یک slice در متد Read مربوط به io.Reader به جای بازگشت دادن یکی از آن‌ها است. بازگشت دادن یک io.Reader (که یک اشاره‌گر است) باعث می‌شود به هیپ انتقال پیدا کند.

اینک سؤال این است که چرا پشته چنین سریع است؟ دو دلیل عمده برای آن وجود دارد:

  • نیازی به garbage collector برای پشته وجود ندارد. چنان که گفتیم متغیر یک بار در زمان ایجاد شدن به پشته ارسال می‌شود و سپس یک بار در زمان بازگشت تابع از آن برداشته می‌شود. بنابراین هیچ نیازی به فرایند پیچیده تملک مجدد متغیرهای استفاده نشده و کارهایی از این دست وجود ندارد.
  • هر پشته به یک goroutine تعلق دارد و از این رو لازم نیست متغیر همانند روش ذخیره‌سازی در هیپ همگام‌سازی شود. این وضعیت موجب بهبود عملکرد نیز می‌شود.

در نتیجه زمانی که یک تابع ایجاد می‌کنیم، رفتار پیش‌فرض ما باید استفاده از مقدار به جای اشاره‌گر باشد. یک اشاره‌گر تنها باید در مواردی استفاده شود که می‌خواهیم متغیری را به اشتراک بگذاریم.

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

در نهایت یک بار دیگر یادآوری می‌کنیم که برای اغلب ما در کاربردهای روزمره، استفاده از ارسال با مقدار، بهترین گزینه محسوب می‌شود.

Break کردن یک for/switch یا یک for/select

در مثال زیر وقتی f مقدار true بازگشت دهد چه رخ می‌دهد؟

ما در این حالت گزاره break را فراخوانی می‌کنیم. اما بدین ترتیب گزاره switch به صورت break درخواهد آمد و نه حلقه for. همین مشکل در مورد مثال زیر نیز وجود دارد:

چنان که می‌بینید Break به گزاره select مربوط است و نه حلقه for. یک راه‌حل ممکن برای break کردن گزاره for/switch یا یک گزاره for/select استفاده از labeled break مانند زیر است:

مدیریت خطا

Go در مسیر مدیریت خطای خود همچنان تا حدودی ناپخته به نظرمی رسد. دقیقاً به همین دلیل است که یکی از بزرگ‌ترین انتظارات ما از نسخه 2 زبان Go حل این مشکل است.

کتابخانه استاندارد کنونی (پیش از Go 1.13) تنها تابع‌هایی برای ساخت خطاها ارائه می‌کرد، بنابراین شاید بهتر باشد نگاهی به pkg/errors (+) داشته باشید.

این کتابخانه روش مناسبی برای رعایت این قاعده ساده است که البته در اغلب موارد نادیده گرفته می‌شود:

یک خطا باید تنها یک بار مدیریت شود. لاگ کردن یک خطا به معنی مدیریت خطا است. بنابراین یک خطا یا باید لاگ شود و یا انتشار یابد.

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

در ادامه مثالی از مشاهده می‌کنید. در این مثال یک فراخوانی REST منجر به ایجاد مشکل در پایگاه داده می‌شود:

اگر از کتابخانه pkg/errors استفاده کنیم، می‌توانیم به صورت زیر عمل کنیم:

خطای اولیه (اگر از سوی یک کتابخانه اکسترنال بازگشت نیافته باشد) می‌تواند با استفاده از errors.New ایجاد شده باشد. لایه میانی insert این خطا را به وسیله افزودن چارچوب بیشتر به آن پوشش می‌دهد. سپس والد با لاگ کردن خطا آن را مدیریت می‌کند. بدن ترتیب در هر سطح یا مقداری بازگشت می‌یابد و یا خطا مدیریت می‌شود.

همچنین می‌توانیم منشأ خطا را نیز بررسی کنیم تا بدانیم آیا به یک تلاش مجدد نیاز داریم یا نه. فرض کنید یک پکیج db از یک کتابخانه بیرونی با دسترسی‌های پایگاه داده سر و کار دارد. این کتابخانه می‌تواند یک خطای گذرا (موقت) به نام db.DBError ایجاد کند. برای تعیین این که آیا به تلاش مجدد نیاز داریم یا نه، باید منشأ خطا را بررسی کنیم:

این کار با استفاده از errors.Cause انجام می‌یابد که آن نیز از پکیج pkg/errors می‌آید:

یک اشتباه رایج، استفاده ناقص از پکیج pkg/errors است. برای نمونه بررسی خطا به صورت زیر اجرا می‌شود:

در این مثال اگر db.DBError پوشش پیدا کند، هرگز موجب تلاش مجدد نمی‌شود.

مقداردهی اولیه Slice

برخی اوقات ما می‌دانیم که طول نهایی یک Slice چه قدر خواهد بود. برای نمونه تصور کنید باید یک Slice به نام Foo را به یک Slice به نام Bar تبدیل کنیم، یعنی دو Slice طولی یکسان دارند. ما غالباً می‌بینیم که Slice-ها به صورت زیر مقداردهی اولیه می‌شوند:

توجه کنید که Slice ساختاری جادویی محسوب نمی‌شود. این ساختار در صورت نبود فضای بیشتر، در پس‌زمینه یک راهبرد رشد را پیاده‌سازی می‌کند. در این حالت یک آرایه جدید به صورت خودکار ایجاد می‌شود که ظرفیت بالاتری دارد و همه آیتم‌ها روی آن کپی می‌شوند.

اینک تصور کنید نیاز داریم این عملیات رشد را چند بار تکرار کنیم، زیرا []Foo ما شامل هزاران آیتم است. پیچیدگی زمانی عملیات درج همچنان (O(1 خواهد بود، اما در عمل با مشکل عملکردی مواجه می‌شویم.

از این رو اگر طول نهایی را بدانیم می‌توانیم به یکی از روش‌های زیر عمل کنیم:

مقداردهی با طول از قبل تعریف‌شده:

یا مقداردهی با طول 0 و ظرفیت از پیش تعریف‌شده:

بهترین گزینه کدام است؟ گزینه اول کمی سریع‌تر است. با این حال ممکن است گزینه دون را بیشتر ترجیح بدهید زیرا موجب می‌شود همه چیز منسجم‌تر بماند. صرف‌نظر از این که اندازه اولیه را می‌دانیم یا نه، افزودن یک عنصر به انتهای یک slice با استفاده از append انجام می‌یابد.

مدیریت چارچوب (Context)

context.Contex غالباً از سوی توسعه‌دهندگان به اشتباه فهمیده می‌شود. بر اساس مستندات رسمی:

یک چارچوب حامل یک ضرب‌الاجل، یک سیگنال لغو و دیگر مقادیر روی API است.

این توصیف کلی است، اما باعث می‌شود که برخی افراد در مورد چرایی و چگونگی استفاده از آن دچار سردرگمی شوند.

در ادامه آن را بیشتر باز می‌کنیم. یک چارچوب می‌تواند شامل موارد زیر باشد:

  • یک ضرب‌الاجل یا deadline. این ضرب‌الاجل یا شامل یک مدت زمان (برای مثال 250 میلی‌ثانیه) یا یک تاریخ-زمان (مثلاً 2019-01-08 01:00:00) است که در زمان فرا رسیدن این زمان، باید فعالیت جاری یعنی درخواست I/O، انتظار برای ورودی کانال و غیره را لغو کنیم.
  • سیگنال لغو (cancelation signal) نیز رفتار مشابهی دارد. زمانی که یک سیگنال دریافت شود باید فعالیت جاری متوقف شود. برای نمونه تصور کنید که ما مشغول دریافت دو درخواست هستیم. فرض کنید یکی برای درج برخی داده‌ها و دیگری برای لغو درخواست اول (چون دیگر موضوعیت ندارد یا هر دلیل دیگر) است. این وضعیت از طریق استفاده از چارچوب قالب لغو در فراخوانی اول میسر است تا به محض دریافت درخواست دوم بتوانیم اولی را لغو کنیم.
  • یک لیست از کلید/مقدار که هر دو از نوع {}interface هستند.

دو نکته وجود دارد که باید اضافه کنیم. ابتدا این که یک چارچوب composable است. بنابراین می‌توانیم یک چارچوب داشته باشیم که شامل یک ضرب‌الاجل باشد و یک لیست از کلید/مقدار نیز برای نمونه داشته باشد. به علاوه goroutine-های چندگانه می‌توانند چارچوب واحدی را به اشتراک بگذارند، بدین ترتیب سیگنال لغو می‌تواند به صورت بالقوه چند فعالیت را متوقف کند.

اگر به موضوع اصلی خود بازگردیم، در اینجا یک اشتباه مهم دیده می‌شود.

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

در چنین حالتی دقیقاً همین چارچوب مستقیماً در زمان فراخوانی نقطه انتهایی gRPC ارسال می‌شود. ولی این آن چیزی نیست که ما می‌خواهیم. به جای آن ما می‌خواهیم به کتابخانه gRPC اعلام کنیم که درخواست را زمانی که اپلیکیشن متوقف شده است و یا پس از مثلاً 100 میلی‌ثانیه لغو کند.

برای نیل به این مقصود می‌توانیم یک «چارچوب ترکیبی» (composed context) ایجاد کنیم. اگر parent نام چارچوب اپلیکیشن باشد، در این حالت به صورت زیر عمل می‌کنیم:

درک چارچوب‌ها کار چندان پیچیده‌ای نیست و یکی از بهترین ویژگی‌های زبان برنامه‌نویسی Go محسوب می‌شوند.

عدم استفاده از گزینه race-

خطایی که غالباً در زمان تست کردن اپلیکیشن‌های Go مشاهده می‌شود، عدم استفاده از گزینه race- است. با این که Go طوری طراحی شده است که برنامه‌نویسی concurrent راحت‌تر و مستعد خطای کمتری است، اما همچنان از مشکلات همزمانی زیادی رنج می‌برد.

بدیهی است که تشخیص‌دهنده race در Go برای همه مشکلات همزمانی چاره‌ساز نیست. در هر حال این ابزار ارزشمندی است و باید همواره در زمان تست اپلیکیشن‌ها مورد استفاده قرار گیرد.

استفاده از نام فایل به عنوان ورودی

اشتباه رایج دیگر در زمان برنامه‌نویسی Go ارسال نام فایل به یک تابع است. فرض کنید ما می‌خواهیم تابعی را برای شمارش خطوط خالی یک فایل پیاده‌سازی کنیم. طبیعی‌ترین پیاده‌سازی چیزی مانند زیر خواهد بود:

Filename به عنوان یک ورودی عرضه می‌شود و از این رو آن را باز می‌کنیم و سپس منطق خود را پیاده‌سازی می‌کنیم.

اینک فرض کنید می‌خواهیم تست‌های unit را روی این تابع اجرا کنیم تا با یک فایل نرمال، یک فایل خالی، یک فایل با نوع انکودینگ متفاوت و غیره آن را تست کنیم. چنان که حدس می‌زنید مدیریت این کار به سرعت دشوار خواهد شد.

ضمناً اگر بخواهیم همین منطق را پیاده‌سازی کنیم، اما از بدنه HTTP استفاده کنیم، باید تابع دیگری برای آن ایجاد کنیم.

Go دو لایه تجرید عالی به این منظور دارد که یکی io.Reader و دیگری io.Writer است. به جای ارسال یک نام فایل می‌توانیم به سادگی یک io.Reader ارسال کنیم و منبع داده را تجرید نماییم.

شاید بپرسید io.Reader یک فایل است؟ یک بدنه HTTP یک بافر بایت و یا شاید چیز دیگری است؟ این مسئله اهمیتی ندارد زیرا ما همچنان همان متد Read را داریم.

در این مورد می‌توانیم حتی ورودی را به بافر کنیم تا آن را خط به خط بخوانیم. بنابراین می‌توانیم از bufio.Reader و از متد ReadLine آن استفاده کنیم:

مسئولیت باز کردن خود فایل اکنون به کلاینت count واگذار شده است:

در پیاده‌سازی دوم تابع می‌تواند صرف‌نظر از این که منبع داده واقعی چیست فراخوانی شود. در عین حال، تست‌های واحد تسهیل می‌شوند، زیرا می‌توان bufio.Reader از یک string ساخت:

Goroutine-ها و متغیرهای حلقه

آخرین اشتباه رایجی که در این مقاله بررسی می‌کنیم به استفاده از متغیرهای حلقه در Goroutine ها مربوط است. خروجی مثال زیر چیست؟

اگر فکر می‌کنید خروجی مثال فوق 1 2 3 با هر نوع ترتیبی است اشتباه می‌کنید. در این مثال هر goroutine وهله یکسانی از متغیر را به اشتراک می‌گذارد و از این رو خروجی آن 3 3 3 است.

دو راه‌حل برای این مشکل وجود دارد. راه‌حل نخست این است که مقدار متغیر i را به بستار (تابع درونی) ارسال کنیم:

و راه‌حل دوم این است که متغیر دیگری درون دامنه حلقه for ایجاد کنیم:

با این که فراخوانی i:= i ممکن است کمی عجیب به نظر برسد، اما کاملاً معتبر است. درون یک حلقه بودن یعنی درون یک دامنه دیگر قرار داریم. بنابراین i:= i یک وهله متغیر دیگری به نام i می‌سازد. البته می‌توانیم آن را به نام دیگری نام‌گذاری کنیم تا خوانایی کد افزایش یابد.

سخن پایانی

در این مقاله به بررسی برخی اشتباه‌های رایج در زبان برنامه‌نویسی Go پرداختیم. شما نیز می‌توانید مواردی که به ذهنتان می‌رسد را در بخش نظرات این نوشته با ما و دیگر خوانندگان مجله فرادرس در میان بگذارید.

منبع: فرادرس


راهنمای ساخت نوع های فرعی مبتنی بر شرط در تایپ اسکریپت — به زبان ساده

در این مقاله قصد داریم نوع های فرعی مبتنی بر شرط در تایپ اسکریپت و همچنین انواع «نگاشت» (Mapping) را مورد بررسی قرار دهیم. هدف ما این است که نوعی ایجاد کنیم که همه کلیدهایی را که با شرط خاصی مطابقت ندارند را از اینترفیس فیلتر کند.

به این منظور نیازی به آشنایی با جزییات نوع‌های نگاشتی وجود ندارد. کافی است بدانید که تایپ‌اسکریپت امکان انتخاب یک نوع موجود و ایجاد تغییر اندک در آن برای ایجاد نوع جدید را به ما می‌دهد. این بخشی از «کامل بودن تورینگ» (Turing Completeness) آن است.

نوع را می‌توان به صورت تابع در نظر گرفت. هر نوع یک نوع دیگر را به عنوان ورودی می‌گیرد، روی آن نوعی محاسبات اجرا می‌کند و نوع جدیدی به عنوان خروجی تولید می‌کند. اگر با Partial<Type> یا Pick<Type, Keys> آشنا هستید، این فرایند نیز کاملاً شبیه آن است.

بیان مسئله

فرض کنید یک شیء پیکربندی دارید. این شیء شامل گروه‌های مختلفی از کلیدها مانند Ids، Dates و functions است. این شیء می‌تواند ناشی از یک API باشد و یا از سوی افراد مختلف سال‌ها نگهداری شود تا این که کاملاً بزرگ شده باشد.

ما می‌خواهیم تنها کلیدهایی را از نوع خاص استخراج کنیم. این فرایند شبیه به این است که تنها تابع‌هایی که Promise بازگشت می‌دهند را انتخاب کنیم یا چیزی ساده‌تر مانند کلید از نوع number داشته باشیم.

ما به یک نام و تعریف نیاز داریم و از این رو از <SubType<Base, Condition استفاده می‌کنیم.

بدین ترتیب دو ژنریک تعریف کرده‌ایم که به وسیله آن SubType را پیکربندی خواهیم کرد:

  • Base – اینترفیسی است که قرار است آن را تغییر دهیم.
  • Condition – نوع دیگری است که به ما اعلام می‌کند کدام مشخصه‌ها باید در شیء جدید حفظ شوند.

ورودی

به منظور تست کردن یک شیء Person داریم که از نوع‌های متفاوتی به صورت string، number، Function تشکیل یافته است. این همان «شیء عظیم» ما است که می‌خواهیم فیلتر کنیم.

خروجی مورد انتظار

برای مثال SubType به نام Person بر اساس نوع رشته می‌تواند تنها کلیدهایی از نوع رشته را بازگشت دهد:

گام به گام به سوی راه‌حل

در این بخش برای مسئله‌ای که در بخش قبل مطرح شد، یک راه‌حل را به صورت گام به گام مطرح می‌کنیم.

گام 1 – Baseline

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

برای هر کلید یک شرط استفاده شده است. بسته به نتیجه نام را به صورت نوع تعیین می‌کنیم یا از مقدار never استفاده می‌کنیم که فلگی برای کلیدهایی است که نمی‌خواهیم در نوع جدید ظاهر شوند. این یک نوع خاص و متضاد any است. به این نوع هیچ چیز نمی‌توان انتساب داد.

در ادامه به روش ارزیابی کد می‌پردازیم:

توجه کنید که ‘id’ یک مقدار نیست، اما نسخه دقیق‌تری از نوع string محسوب می‌شود. ما قصد داریم از آن در ادامه استفاده کنیم. تفاوت بین نوع string و ‘id’ به صورت زیر است:

گام 2 – فهرست‌بندی کلیدهایی که با شرط نوع مطابقت دارند

در این مرحله کار اصلی انجام یافته است. اکنون هدف جدیدی داریم و آن گردآوری نام‌های کلیدهایی است که از اعتبارسنجی ما عبور کرده‌اند. در مورد SubType<Person، string> این مقدار برابر با ‘name’ | ‘lastName’ خواهد بود:

ما از کد مرحله قبلی استفاده کرده و تنها یک بخش دیگر به نام [keyof Base] به آن اضافه می‌کنیم.

کار این بخش آن است که رایج‌ترین انواع مشخصه‌های مفروض را گردآوری کرده و never را نادیده بگیرد چون هیچ راهی برای استفاده از آن‌ها وجود ندارد.

در کد فوق مثالی از بازگشت string | number داریم. چنان که می‌بینید در نخستین گام نوع کلید را با نام آن عوض کرده‌ایم.

اینک به راه‌حل نهایی نزدیک شده‌ایم.

ما اکنون آماده ساخت شیء نهایی خود هستیم. صرفاً از Pick استفاده می‌کنیم که روی نام‌های کلید ارائه شده می‌چرخد و نوع متناظر با شیء جدید را استخراج می‌کند.

در کد فوق Pick یک نوع نگاشت درونی است که از تایپ‌اسکریپت 2.1 به بعد ارائه شده است:

راه‌حل نهایی

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

نکته: این صرفاً یک سیستم نوع‌بندی است. می‌توان در آن از حلقه و حتی اعمال گزاره‌های شرطی نیز استفاده کرد. برخی افراد ترجیح می‌دهند که درون یک عبارت نوع‌هایی داشته باشند:

کاربرد

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

  1. استخراج صرف انواع کلید primitive از JSON:

2. فیلتر کردن همه چیز به جز تابع‌ها:

شما می‌توانید به کاربردهای دیگر این امکان نیز فکر کنید.

این راه‌حل چه مسائلی را حل نمی‌کند؟

  1. یک سناریوی جالب این است که یک زیرنوع Nullable بسازیم

اما از آنجا که string | null نمی‌تواند به null انتساب پیدا کند کار نخواهد کرد. البته ممکن است شما ایده‌ای برای حل این مشکل داشته باشید!

2. فیلترینگ زمان اجرا

چنان که می‌دانید نوع‌ها در زمان کامپایل پاک می‌شوند. بدین ترتیب هیچ نقشی در شیء واقعی ندارند. اگر بخواهید یک شیء را به نوعی فیلتر کنید، باید کد جاوا اسکریپت برای آن بنویسید.

ضمناً استفاده از ()Object.keys روی چنین ساختارهایی توصیه نمی‌شود، زیرا نتیجه «زمان اجرا» ممکن است از نوع مفروض متفاوت باشد.

جمع‌بندی

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

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

منبعک فرادرس