رویه های مناسب GraphQL | راهنمای کاربردی


GraphQL یک زبان کوئری برای API-ها و یک محیط «زمان اجرا» (runtime) برای تأمین آن کوئریها با دادههای موجود است. runtime یک توصیف کامل و قابل درک از دادهها در API ارائه میکند و همچنین به کلاینتها این امکان را میدهد که دقیقاً آنچه را که نیاز دارند و نه بیشتر از آن را تقاضا کنند. GraphQL از سوی فیسبوک به عنوان یک راهکار داخلی برای اپلیکیشنهای موبایل توسعه یافته است و در ادامه به صورت متن-باز در اختیار جامعه توسعهدهندگان قرار گرفته است. در این مقاله با رویه های مناسب GraphQL آشنا خواهیم شد.
رویه های مناسب GraphQL
اگر به صفحه رویههای مناسب GraphQL در مستندات رسمی آن (+) مراجعه کنید، متوجه خواهید شد که صرفاً توضیح مختصری در مورد برخی از رایجترین رویههای مناسب ارائه شده است. این توضیحها صرفاً یک سری راهنماییهای کلی هستند که هیچ جزییات پیادهسازی ندارند. ما در این مقاله برخی جزییات پیادهسازی را برای یک اپلیکیشن بکاند با استفاده از گرافکیوال ارائه میکنیم. البته این راهنما به هیچ وجه یک مرجع کامل محسوب نمیشود و صرفاً فهرستی از برخی رویههای مناسب و دستورالعملها برای جلوگیری از مشکلات رایج که به طور مکرر رخ میدهند ارائه میکند.
از مدلهای دادهای انعطافپذیر برای کوئریهای ساده و موتاسیونها استفاده کنید
زمانی که دست به کار ایجاد اسکیما میشوید، ممکن است طراحی مدلهای دادهای را دشوار بیابید. چندین روش برای انجام این کار وجود دارد و اغلب پیادهسازیها به خوبی کار میکنند. مشکلات مختلف تنها زمانی رخ مینمایند که وارد بحث پیادهسازی شوید.
به طور کلی همواره خوب است که پلتفرمهایی که هماینک از گرافکیوال استفاده میکنند را بررسی کنیم. Mutations یک مورد مناسب برای درک شیوه مدلسازی اشیای ورودی و خروجی و چگونگی افشای کوئریها و موتاسیونها محسوب میشود.
به عنوان یک قاعده کلی باید موتاسیونها را تا حد ممکن کوچک نگه دارید. ورودیها نیز باید همراه با نامگذاری گویا، انعطافپذیر باشند.
موتاسیون به نام addComment ساده منسجم و روشن است. این جهش یا موتاسیون یک ورودی به نام میگیرد و یک مقدار به نام Comment بازگشت میدهد. ما یک مادیفایر غیر تهی (!) به کار میگیریم تا مطمئن شویم که payload ورودی نمیتواند تهی باشد. نکتهای که در اینجا باید مطمئن باشیم این است که شیوه ایجادشدن/ بهروز شدن را بازگشت میدهیم. به این ترتیب کلاینت میتواند حالت را بهروزرسانی کند تا کاربر بداند که آیا چیزی بهروزرسانی شده یا نه.
از اشیای تودرتو برای کاهش فراخوانیهای شبکه بهره بگیرید
نوع Comment در مثال قبلی یک نوع ساده بود که تنها یک فیلد داشت. فرض کنید میخواهیم userId را به عنوان بخشی از Comment بازگشت دهیم. یک رویکرد ممکن میتواند به صورت زیر باشد:
با این که این مثال میتواند شبیه یک رویکرد سریع و آسان به نظر برسد، اما یک مشکل کوچک وجود دارد. userId خودش نمیتواند برای فرانتاند مفید باشد و در نهایت باید یک فراخوانی انجام دهد تا کاربر با userId واکشی کند. این وضعیت کاملاً نامناسب است و امکان بهرهبرداری از همه توان گرافکیوال را فراهم نمیسازد. در GraphQL بسیار بهتر است که انواع خروجی را به صورت تودرتو دربیاوریم. به این ترتیب میتوانیم همه چیز را با یک درخواست منفرد فراخوانی کنیم و همچنین عملیات کشکردن و دستهسازی را با data loader اجرا کنیم. این رویکرد شامل ارسال User در Comment است و به صورت زیر اجرا میشود:
کوئری مربوطه به صورت زیر است:
استفاده از مدیریت خطای مناسب
این یکی از نکاتی است که تقریباً همه افراد در آغاز استفاده از گرافکیوال فراموش میکنند و زمانی که اپلیکیشن بسیار بزرگ میشود، امکان پوشش دادن همه خطاها دشوار میشود. شاید بحث مدیریت خطا در GraphQl کمی پیچیده باشد، چون پاسخ همواره دارای یک حالت HTTP به صورت 200 OK است. اگر درخواستی ناموفق باشد، پاسخ JSON payload شامل فیلد روت به نام errors خواهد بود که جزییاتی در مورد علت شکست ارائه میکند. بدون مدیریت مناسب خطاها، پاسخ میتواند به صورت زیر باشد:
این پاسخ به هیچ وجه مفید نیست، چون پاسخ اعلام نمیکند که دقیقاً چه چیزی اشتباه بوده است. به همین جهت است که اغلب اپلیکیشنها بدون ارائه پاسخ مناسب به کاربر یا گزینه fallback شکست میخورند. مدیریت خطاها خود یک موضوع مهم است و نیازمند صرف وقت و تلاش زیادی است. اما به طور خلاصه خروجی پس از پیادهسازی مدیریت خطا به صورت زیر خواهد بود:
از اینترفیسها و Union-ها برای تجرید استفاده کنید
اینترفیسها به عنوان اشیای والدی عمل میکنند که از روی آنها میتوان اشیای دیگری ساخت. اکستنشنهای نوع اینترفیس برای بازنمایی یک اینترفیس استفاده میشوند که از نوعی اینترفیس اولیه بسط یافتهاند. برای نمونه از این روش برای بازنمایی دادههای لوکال از سوی یک سرویس گرافکیوال استفاده میشود که خودش اکستنشن یک سرویس گرافکیوال دیگر است.
Union یک نوع شیء است که اشیای زیادی را بازنمایی میکند.
یونیونهای گرافکیوال یک شیء را نمایش میدهند که میتواند یک لیست از انواع شیء گرافکیوال باشد، اما فیلدهای تضمینشدهای برای آن نوعها ارائه نمیکند. همچنین از اینترفیس متفاوت است، زیرا انواع شیء چیزی را اعلان میکنند که اینترفیس پیادهسازی میکند، اما از چیزی که یونیون در خود جای داده اطلاعی ندارند.
به مثال زیر توجه کنید. Profile یک اینترفیس است که از سوی User و همچنین Company پیادهسازی شده است. چند فیلد الزامی وجود دارند. فیلدهای دیگری نیز بر اساس نوع و الزامات متفاوت اضافه میشوند.
در مواردی که یک کوئری دارید که دو نوع بازگشت میدهد میتوانید از Unuion-های مشابه استفاده کنید. به این ترتیب کوئری search میتواند یکی از نوعهای User یا Compamny را بازگشت دهد:
از فرگمانها برای استفاده مجدد از انواع تعریف شده استفاده کنید
فرگمانها اشیای با قابلیت استفاده مجدد در GraphQL هستند. فرگمانها را میتوان مانند تابعها در زبانهای برنامهنویسی تصور کرد:
فرگمانها با استفاده از عملگر اسپرد (...) مصرف میشوند. به این ترتیب مقدار زیادی از حجم کدهای تکراری کاسته میشود.
سخن پایانی
از این که این مقاله را مطالعه کردید از شما سپاسگزاریم و امیدواریم بتوانید یک سرور GraphQL پایدار پیادهسازی کنید. رویکردهایی که در این مقاله مطرح شدند، همگی راهکارهای تست و آزموده شده و هستند. شما نیز میتوانید پیشنهادهای خود را در بخش نظرات این نوشته با ما و دیگر خوانندگان مجله فرادرس در میان بگذارید.