پیاده سازی GraphQl در Asp Core  قسمت اول

با رشد و اضافه شدن نیازمندی های پروژه هر روز شاید پیدایش تکنولوژی جدید هستیم در این مقاله قصد داریم به صورت ساده و در قالب یک مثال کوچک یکی از تکنولوژی های روز را معرفی و پیاده سازی کنیم.خوشحال میشم نظراتتون رو در قسمت کامنت مطرح کنید توجه داشته باشید در این مقاله نگاه کلی به graphql خواهیم داشت اگر قصد دارید به صورت کاملتری یاد بگیرید داکیومنت graphql و لینک هایی که در قسمت منابع قرار دارند را می توانید مطالعه کنید. هدف من از این مقاله یادگیری مطلبی بود که به اشتراک بزارم چون این کار بهم حس خوبی میده.و اینکه اگه این مقاله براتون مفید بود، میتونید تو کافیته منو یک قهوه مهمون کنید.یا اینکه تو کافیته ثبت نام کنید و کافیته رو به اشتراک بگذراید : ) https://www.coffeete.ir/sobhan اگه تجربه نوشتن وب سرویس ها رو داشته اید مطمئناً با واژه API REST اشنایی دارید.REST یک سبک معماری است که به کاربر اجازه می دهد درخواست های خود را به صورت http ارسال کرده و response را در یک قالب مشخص دریافت کنند .این قابلیت به کلاینت های مختلف اجازه می دهد بتوانند داده طبق قوانین از پیش تعریف شده گرفته و پردازش کنند. رفته رفته با همه گیر شدن معماری rest قوانین جدید تحت عنوان restful لحاظ شدند که برنامه نویس ها را طبق یک چارچوب مشخص وادار به توسعه وب سرویس ها میکنند به طور مثال در restful خروجی باید مشخص و به صورت json باشد یا استفاده از http verb ها برای وب سرویس های مختلف. در ادامه یک روش دیگر تحت عنوان GraphQL برای فراخوانی وب سرویس ها استفاده میکنیم و بررسی میکنیم چرا و کجاها باید از GraphQL استفاده کنیم همچنین در یک مثال ساده و کاربردی را پیاده سازی خواهیم کرد. برای اطلاعت بیشتر درباره restfull این مقاله را مطالعه کنید.؛ GraphQL : یک زبان open-source مبتنی بر کوئری (query language) است که توسط فیسبوک در سال 2012 برای بهبود و بهینه سازی اپلیکیشن هایش ایجاد کرد و در سال 2015 به صورت عمومی قابل دسترس قرار داد .دلیل ابداع GraphQL حجم دیتا رو به افزونی بود که فیسبوک باید به پلتفرم های گوشی انتقال میداد حجم و افزونگی دیتا به قدری بود که کش ها هم به سختی جوابگو بودند و منابع زیادی از سرور صرف این موضوع میشد برای رفع مشکل گفته شده فیسبوک برای اولین بار بر روی پلتفرم های همراه GraphQL را پیاده سازی کرد که رفته رفته در spa هام قابل پیاده سازی شد.اگر وارد سایت graphql.org شوید به صورت زیر graphql را تعریف کرده است همچنین سورس اصلی را هم میتوانید از ریپازیتوری گفته شده در سایت مشاهد کنید .A query language for your APIGraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.یکی از دلایلی که ایجاب به یادگیری GraphQL میکند کامیونیتی و شرکت های استفاده کننده از GraphQL میباشند اگر وارد سایت GraphQL شده باشید میتوانید لیست شرکت های بزرگ که از GraphQL استفاده می کنند را مشاهده کنید.چرا باید از GraphQL استفاده کنیم ؟ کاهش رفت و برگشت به سرور : در GraphQL کمترین back-and-forth (رفت و برگشت) را خواهیم داشت چون تمام نیازمندی های کلاینت با اولین درخواست برآورده خواهد شد.افزونگی یا نقص دیتا نداریم : بسته به نیازی کلاینت دیتا واکشی میشود نه بیشتر نه کمتر.مستندات : با استفاده از GraphQL هر endpoint میتواند مستندات استفاده از GraphQL را در اختیار کلاینت ها قرار داد مثل swagger در restful.کاهش پهنای باند : GraphQL معمولا با درخواست کمی به پهنای باند کمتری نیاز دارد . چون کلاینت ها بسته به نیاز خود دیتا را واکشی می کنند در نتیجه پهنای باند کمتری اشغال میشود.تفاوت GraphQL با RESTبرخلاف restful که برای هر وب سرویس باید یک ادرس منحصر بفرد داشته باشیم در GraphQL فقط از یک ادرس مربوط به endpoint استفاده میکنیم.؛ restful فقط با http کار میکند در حالی که GraphQL به http نیازی ندارددر restful سرور payload و response را مشخص میکند ولی در GraphQL کلاینت بسته به نیازی که دارد payload و response را مشخص میکند.؛restful و GraphQL هردو از json استفاده میکنند.در این لینک و این لینک میتوانید به صورت کامل تر GraphQL و REST را مورد بررسی قرار دهید.دقت کنید هر دو تکنولوژی بسته به نیازمندی هرکدام میتواند مفید باشد و لزوما برتری خاصی نسبت به هم ندارند .در ادامه با چند اصطلاح کاربردی GraphQL اشنا خواهیم شد.؛ Schema : همانطور که گفته شد در GraphQL یک endpoint وجود دارد ، هر endpoint دارای Schema بخصوص خود میباشد که ساختار کلی از type ها و فیلدها را در اختیار استفاده کنندگان قرار می دهد .مثال زیر schema مربوط به یک endpoint میباشد.کلاینت با مشاهده schema می تواند ساختار مربوط به داده ها را مشاهده و طبق نیازمندی که دارند CRUD خود را پیاده سازی کنند.در ادامه بیشتر به schama آشنا خواهیم شد type Book { id: ID title: String published: Date author: Author } type Author { id: ID name: String book: [Book] }هر schema شامل سه route type اصلی تحت عناوین زیر میباشد که در این مقاله Query و Mutation توضیح و پیاده سازی خواهیم کرد.type Query { .... } type Mutation { ... } type Subscription { ... }؛ Query : کوئری ها برای fetch کردن داده ها از سرور می باشند .همانطور که گفته شد طبق نیازمندی های کلاینت Query نوشته شده در سرور اجرا میشود به طور مثال در Query زیر فقط name را نیاز داریم که بر اساس ورودی ، در خروجی فقط فیلد name را میتوان مشاهده کرد.دستور بالا ساده ترین حالت Query در GraphQL است که از ساختار Query هم میتوان تشخیص داد که فیلد name را از hero را بازگشت می دهد .syntax در Queryها ساده و قابل فهم هستند و با یک نگاه خروجی را میتوان حدس زد.؛ Fields : میتوان گفت فیلد ها کوچکترین جزء در GraphQL محسوب میشوند . به طور مثال در مثال بالا name یک فیلد محسوب میشود.؛ Arguments : میتوان Query هایی به ارگومان های خاصی ارسال کرد به طور مثال نام و وزن کسی که شناسه 1000 را دارد به صورت زیر خواهد بود؛ Variables : میتوانید در Query ها از متغیر هم استفاده کنید بدین معنی داده ای را خارج از Query به داخل Query ارسال کرد . در مثال زیر مقدار postFilter میتوان از یک ابجکت جاوا اسکریپتی باشدquery post($filter: PostFilter) { queryPost(filter: $filter) { title text author { name } } }؛Aliases : با اسفاده از Aliases میتوان خروجی سرور را تغیر نام داد مثال زیر را در نظر بگیریدquery getUsers { users(role: ADMIN) { id firstName lastName phone username } users(role: ACCOUNTANT) { id firstName lastName phone username } }کوئری بالا قرار است دو کاربر مختلف با ارگومان های ACCOUNTANT و ADMIN بازگشت دهد ولی کوئری بالا با خطایی تحت عنوان زیر خواهد بود { &quoterrors&quot: [ { &quotmessage&quot: &quotFields &quotusers&quot conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.&quot, &quotlocations&quot: [ { &quotline&quot: 2, &quotcolumn&quot: 3 }, { &quotline&quot: 9, &quotcolumn&quot: 3 } ] } ] }این خطا بدین معنی است که داده های مختلف از یک نوع درون یک selection قرار گرفته اند برای رفع این مشکل از Aliases به شکل زیر استفاده میکنیمquery getUsers { admins: users(role: ADMIN) { id firstName lastName phone username } accountants: users(role: ACCOUNTANT) { id firstName lastName phone username } } ؛Fragments : به طور خلاصه میتوان گفت به اشتراک گذاشتن فیلد ها بین عملیات است عملیات میتواند شامل Query یا Mutation باشد.در مثال زیر ما یک Fragments ایجاد کرده ایم که میتوانیم بین همه type های person به اشتراک بگزاریمA fragment is basically a reusable piece of query.fragment NameParts on Person { firstName lastName }در مثال بالا NameParts نام Fragments (دلخواه) بر روی person است که باید قبلا ایجاد کرده باشیم.نحوه استفاده ان به شکل زیر استquery GetPerson { people(id: &quot7&quot) { ...NameParts } }اگر از frgment استفاده نکنید Query شما شبیه زیر خواهد شد .query GetPerson { people(id: &quot7&quot) { firstName lastName avatar(size: LARGE) } }اگر بخوایم به oop تعیم بدیم خیلی شبیه ارثبری است .وقتی که یک کلاس داریم و قصد داریم برحسب نیاز فیلد های مشترک رو بین کلاس های فرزند به اشتراک بگذراریم.؛Fragment ها را میتوان به صورت inline هم پیاده سازی کرد.برای اطلاعت بیشتر درباره Fragments میتوانید لینکای زیر را مطالعه کنید#1 #2 ؛Directives : برای اعمال تنظیمات بر روی فیلدها میباشد به طور مثال میتوانیم به صورت داینامیک فیلدهایی که نیاز داریم سمت سرور ارسال کنیم . GraphQL به صورت توکار چنتا Directives دارد که یکی انرا به ذکر مثال توضیح خواهیم داد شیوه کار Directives به یک صورت است و نیاز به مثال های بیشتری نیست . همچنین بسته به نیاز میتوانید custom Directives پیاده سازی کنید.به طور مثل Query زیر اگر مقدار showName برابر با false باشد فیلد name به سرور ارسال نمیشود و طبق تعریفی که داشیم در خروجی هم نشان داده نمیشود.query getUsers($showName: Boolean) { users { id name @include(if: $showName) } }برای اطلاعات بیشتر میتوانید لیتک های زیر را مطالعه کنید#1 #2؛Mutation : بیشتر نیازمندی ما در پروژه برای fetch داده است ولی گاهی اوقات نیاز داریم داده ای را در سرور تغییر دهیم .تغیر داده میتوان شامل حذف واپدیت و اضافه کردن داده جدید باشد برای اینکار در GraphQL از Mutation استفاده میکنیم .Mutation خیلی شبیه کوئری میباشد به مثال زیر توجه کنیدmutation AddNewPet ($name: String!, $petType: PetType) { addPet(name: $name, petType: $petType) { id name petType } }در مثال بالا addpet که از نوع mutation می باشد که دو ارگومان name و type را گرفته و برای ثبت به سرور ارسال میکند در ادامه سه فیلد id,name,type را بازگشت می دهد. مثال دیگر از mutation به صورت زیر استمیتوان گفت کوئری ها مثل http get رفتار میکنند و mutation شبیه Post , Delete ,Put هستند.Query fetch data - like a GET in the restMutation changes data - like DELETE or a POST in rest. تا اینجای کار به صورت آکادمیک درباره GraphQL صحبت کردیم .برای درک بهتر این لینک را باز کنید در سایت معرفی شده میتوانید توضیحاتی که گفته شد را مشاهده و تست کنید .در مقاله بعدی برای درک بهتر یک پروژه ساده را پیاده سازی خواهیم کرد. منابع.educative.iohowtographql.comlucasconstantino.github.iotutorialspoint.com graphql-aspnet.github.io eat.bananacakepop.com graphqlbin.com howtographql.com dgraph.io learning.atheros.ai