JSON API - نحن نعمل وفقا للمواصفات

في الآونة الأخيرة ، تم تقسيم تطوير الشبكة. الآن نحن لسنا جميع المبرمجين مكدس كامل - نحن الواجهة الأمامية والخلفية. وأصعب شيء في هذا الأمر ، كما في أماكن أخرى ، هو مشكلة التفاعل والتكامل.

الواجهة الأمامية مع الواجهة الخلفية تتفاعل من خلال API. وتعتمد نتيجة التطوير بأكملها على ماهية واجهة برمجة التطبيقات (API) ، ومدى توافق أو إتقان الواجهة الخلفية والواجهة الأمامية فيما بينها. إذا بدأنا جميعًا في مناقشة كيفية القيام بالترقية ، وقضاء اليوم بأكمله في إعادة صياغتها ، فقد لا نصل إلى مهام العمل.

لكي لا تزحلق وتربية holivars حول أسماء المتغيرات ، تحتاج إلى مواصفات جيدة. دعونا نتحدث عما ينبغي أن يكون عليه الأمر لجعل الحياة أسهل للجميع. في الوقت نفسه ، سنصبح خبراء في حظائر الدراجات.



لنبدأ من بعيد بالمشكلة التي نحلها.

منذ وقت طويل ، في عام 1959 ، توصل سيريل باركنسون (لا يجب الخلط بينه وبين المرض ، وهو كاتب وشخصية اقتصادية) إلى العديد من القوانين المثيرة للاهتمام. على سبيل المثال ، هذه النفقات تنمو مع الدخل ، الخ واحد منهم يسمى قانون التفاهات:

الوقت الذي يقضيه مناقشة العنصر يتناسب عكسيا مع المبلغ الذي تم النظر فيه.

كان باركنسون خبيرًا اقتصاديًا ، لذا شرح قوانينه من الناحية الاقتصادية ، شيء من هذا القبيل. إذا أتيت إلى مجلس الإدارة وتقول إنك تحتاج إلى 10 ملايين دولار لبناء محطة للطاقة النووية ، فمن المحتمل أن تتم مناقشة هذه المشكلة على أقل من تخصيص 100 جنيه للدراجة التي يتم إلقاؤها للموظفين. لأن الجميع يعرف كيفية بناء سقيفة دراجة ، لكل فرد رأيه الخاص ، والجميع يشعر بالأهمية ويرغب في المشاركة ، ومحطة الطاقة النووية شيء مجردة وبعيدة ، كما لم يتم رؤية 10 ملايين - هناك أسئلة أقل.

في عام 1999 ، ظهر قانون تفاهة الشلل الرعاش في البرمجة ، التي تم تطويرها بنشاط بعد ذلك. في البرمجة ، تم العثور على هذا القانون بشكل رئيسي في الأدب باللغة الإنجليزية وبدا وكأنه استعارة. كان يطلق عليه تأثير Bikeshed (تأثير سقيفة الدراجات) ، ولكن الجوهر هو نفسه - نحن على استعداد لسقيفة دراجة ونريد مناقشة أطول بكثير من بناء محطة توليد الكهرباء.

صاغ هذا المصطلح المطور الدنماركي Poul-Henning Kamp ، الذي شارك في إنشاء FreeBSD. أثناء عملية التصميم ، قضى الفريق وقتًا طويلاً للغاية في مناقشة كيفية عمل وظيفة النوم. هذا اقتباس من خطاب من Poul-Henning Kamp (تم تنفيذ التطوير في مراسلات البريد الإلكتروني):

لقد كان اقتراحًا للنوم (1) DTRT. إذا أعطيت حجة غير صحيحة أدت إلى اندلاع حريق العشب هذا ، فلن أقول أي شيء أكثر من ذلك ، لأنه عنصر أصغر كثيرًا من شأنه نتوقع من طول الخيط ، وحظيت بالفعل باهتمام أكثر بكثير من بعض * المشاكل * الموجودة لدينا هنا.

في هذه الرسالة ، يقول أن هناك الكثير من المشاكل الأكثر أهمية التي لم يتم حلها: "دعونا لا نتعامل مع سقيفة الدراجة ، سنقوم بشيء ما مع هذا والمضي قدمًا!"

لذا قدم بول-هنينج كامب في عام 1999 مصطلح التأثير bikeshed في الأدب باللغة الإنجليزية ، والذي يمكن إعادة صياغته على النحو التالي:

مقدار الضجيج الناتج عن التغيير في الكود يتناسب عكسيا مع تعقيد التغيير.

كلما زادت الإضافة أو التغيير الذي أجريناه ، زادت الآراء التي نحتاج إلى سماعها. أعتقد أن العديد قد قابلوا هذا. إذا حللنا سؤالًا بسيطًا ، على سبيل المثال ، كيفية تسمية المتغيرات ، فهذا لا يهم بالنسبة للجهاز - سيؤدي هذا السؤال إلى عدد كبير من holivars. ولكن لم يتم مناقشتها خطيرة ، مهمة حقا للمشاكل التجارية وتذهب في الخلفية.

ما الذي تعتقد أنه أكثر أهمية: كيف نتواصل بين الواجهة الخلفية والواجهة الأمامية ، أو مهام العمل التي نقوم بها؟ الجميع يفكر بطريقة مختلفة ، ولكن أي عميل ، وهو الشخص الذي يتوقع منك أن تحضر له المال ، سيقول: "هل لي مهام أعمالنا بالفعل!" إنه لا يهتم مطلقًا بكيفية نقل البيانات بين الواجهة الخلفية والواجهة الأمامية. ربما لا يعرف حتى ما هي الواجهة الخلفية والواجهة الأمامية.

لتلخيص المقدمة ، أود أن أقول: API هي سقيفة دراجة.


رابط العرض

نبذة عن المتحدث: يعمل أليكسي أفدييف ( أفدييف ) لصالح شركة Neuron.Digital ، التي تتعامل مع الخلايا العصبية وتصنع واجهة رائعة لها. يهتم أليكس أيضًا بـ OpenSource ، وينصح الجميع. يعمل منذ فترة طويلة في مجال التطوير - منذ عام 2002 ، وجد شبكة الإنترنت القديمة ، عندما كانت أجهزة الكمبيوتر كبيرة ، وشبكة الإنترنت صغيرة ، ولم يكن عدم وجود JS يزعج أي شخص ، وقام الجميع بإنشاء مواقع على الطاولات.

كيفية التعامل مع حظائر الدراجة؟


بعد استنتاج سيريل باركنسون المحترم لقانون التفاهة ، نوقش كثيرا. اتضح أن تأثير سقيفة الدراجات هنا يمكن تجنبه بسهولة:

  1. لا تستمع للنصيحة. أعتقد أن الفكرة كذلك - إذا لم تستمع إلى النصائح ، فيمكنك فعل شيء من هذا القبيل ، لا سيما في البرمجة ، وخاصة إذا كنت مطور مبتدئ.
  2. افعل كما تريد "أنا فنان ، أرى ذلك!" - لا يوجد تأثير له تأثير bikeshed ، كل ما تحتاجه هو القيام به ، ولكن تظهر أشياء غريبة للغاية على الإخراج. وغالبا ما وجدت في لحسابهم الخاص. بالتأكيد صادفت المهام التي اضطررت لإكمالها للمطورين الآخرين وتسبب تنفيذها في حيرة.
  3. هل من المهم أن تسأل نفسك؟ إذا لم يكن الأمر كذلك ، لا يمكنك ببساطة مناقشة الأمر ، لكنها مسألة تتعلق بالوعي الشخصي.
  4. استخدام معايير موضوعية. سأتحدث عن هذه النقطة في التقرير. لتجنب تأثير سقيفة الدراجات الهوائية ، يمكنك استخدام المعايير التي تحدد بموضوعية أيهما أفضل. كانت موجودة.
  5. لا تتحدث عما لا تريد الاستماع إليه. في شركتنا ، يعد بدء مطوري الواجهة الخلفية انطوائيًا ، لذلك يحدث قيامهم بشيء لا يخبرون الآخرين به. نتيجة لذلك ، صادفنا المفاجآت. تعمل هذه الطريقة ، لكن في البرمجة ليس الخيار الأفضل.
  6. إذا كنت لا تهتم بالمشكلة ، يمكنك ببساطة تركها أو اختيار أي من الخيارات المقترحة التي نشأت في عملية holivarov.

أداة مكافحة bikeshedding


أريد أن أتحدث عن أدوات موضوعية لحل مشكلة سقيفة دراجة. لإظهار ماهية أداة مكافحة bikeshedding ، سأخبركم بقصة صغيرة.

تخيل أن لدينا مطور خلفية مبتدئ. لقد جاء مؤخرًا إلى الشركة ، وتم تكليفه بتصميم خدمة صغيرة ، على سبيل المثال ، مدونة ، تحتاج إلى كتابة بروتوكول REST لها.

روي فيلدينج ، مؤلف كتاب REST

في الصورة ، روي فيلينج ، الذي دافع في عام 2000 عن أطروحته "الأساليب المعمارية وتصميم هندسة البرمجيات الشبكية" ، وبالتالي قدم مصطلح REST. علاوة على ذلك ، اخترع HTTP ، وهو في الواقع أحد مؤسسي الإنترنت.

REST هي مجموعة من المبادئ المعمارية التي توضح كيفية تصميم بروتوكولات REST وواجهات برمجة تطبيقات REST وخدمات RESTful. هذه هي مبادئ معمارية مجردة ومعقدة جدا. أنا متأكد من أن أيا منكم لم يشهد أي وقت مضى API مصنوعة بالكامل وفقا لجميع المبادئ راستفول.

متطلبات الهندسة المعمارية REST


سأقدم بعض المتطلبات لبروتوكولات REST ، والتي سأشير إليها بعد ذلك واعتمد عليها. هناك الكثير منهم ، يمكنك قراءة المزيد عنها في ويكيبيديا.

1. نموذج خادم العميل.
أهم مبدأ REST ، أي تفاعلنا مع الواجهة الخلفية. وفقًا لـ REST ، فإن الواجهة الخلفية هي خادم ، والواجهة الأمامية هي عميل ، ونتواصل بتنسيق خادم عميل. الأجهزة المحمولة هي أيضا عميل. مطورو الساعات والساعات والثلاجات والخدمات الأخرى - أيضًا تطوير جزء العميل. RESTful API هو الخادم الذي يصل إليه العميل.

2. عدم وجود شرط.
يجب ألا تكون هناك حالة على الخادم ، أي أن كل ما هو مطلوب للإجابة يأتي في الطلب. عندما يتم تخزين جلسة على الخادم ، وبناءً على هذه الجلسة ، تأتي إجابات مختلفة ، وهذا يعد انتهاكًا لمبدأ REST.

3. توحيد الواجهة.
هذا أحد المبادئ الأساسية التي يجب أن يعتمد عليها REST API. ويشمل ما يلي:

  • تحديد المورد هو كيف ينبغي لنا بناء عنوان URL. في REST ، ننتقل إلى الخادم للحصول على نوع من الموارد.
  • التلاعب بالموارد من خلال العرض. يعرض الخادم لنا وجهة نظر مختلفة عن ما يكمن في قاعدة البيانات. لا يهم إذا قمت بتخزين المعلومات في MySQL أو PostgreSQL - لدينا وجهة نظر.
  • رسائل تصف ذاتيًا - أي أن الرسالة تحتوي على معرف وروابط حيث يمكنك الحصول على هذه الرسالة مرة أخرى - كل ما هو مطلوب للعمل مع هذا المورد مرة أخرى.
  • Hypermedia هو رابط إلى الإجراءات التالية مع مورد. يبدو لي أنه لا يوجد REST API واحد يقوم بذلك ، ولكن تم وصفه بواسطة Roy Fielding.

هناك 3 مبادئ أخرى لا أذكرها لأنها ليست مهمة في قصتي.

مدونة مريحة


العودة إلى البداية مطور الواجهة الخلفية ، الذي طلب منه تقديم خدمة للمدونة على RESTful. أدناه مثال على نموذج أولي.



هذا موقع يحتوي على مقالات ، يمكنك التعليق عليها ، والمقالة والتعليقات لها مؤلف - قصة قياسية. سيقوم مطور الواجهة الخلفية للمبتدئين بعمل واجهة برمجة تطبيقات RESTful لهذه المدونة.

نحن نعمل مع جميع بيانات المدونة على أساس CRUD .

يجب أن يكون من الممكن إنشاء وقراءة وتحديث وحذف أي مورد. دعونا نحاول أن نطلب من مطور الواجهة الخلفية الخاص بنا إنشاء AP RESTful استنادًا إلى مبدأ CRUD. بمعنى ، كتابة طرق لإنشاء مقالات ، والحصول على قائمة بالمقالات أو مقالة واحدة ، وتحديثها وحذفها.

دعونا نرى كيف يمكن أن يفعل ذلك.


كل شيء خاطئ هنا فيما يتعلق بجميع مبادئ REST . الشيء الأكثر إثارة للاهتمام هو أنه يعمل. لقد حصلت في الواقع على واجهات برمجة التطبيقات (APIs) التي بدت على هذا النحو بالنسبة للعميل ، إنه حظيرة للدراجات ، وبالنسبة للمطورين ، إنها فرصة للاسترخاء والدفاع ، وبالنسبة لمطور مبتدئ ، إنه مجرد عالم جديد شجاع يتعثر فيه كل مرة يسقط ويحطم رأسه. لديه لإعادة مرارا وتكرارا.


هذا هو خيار الراحة. استنادًا إلى مبادئ تحديد الموارد ، نعمل مع الموارد - مع المقالات ونستخدم أساليب HTTP التي اقترحها روي فيلدنج. لم يستطع استخدام عمله السابق في عمله التالي.

لتحديث المقالات ، يستخدم الكثيرون طريقة PUT ؛ وله دلالات مختلفة قليلاً. تعمل طريقة PATCH على تحديث الحقول التي تم تمريرها ، ويقوم PUT ببساطة باستبدال مقال بآخر. بواسطة الدلالات ، PATCH هو دمج ، ويتم استبدال PUT.

سقط مطور الواجهة الخلفية للمبتدئين لدينا ، فاختاروا قائلين: "كل شيء على ما يرام ، افعل ذلك من هذا القبيل" ، وأعده بصدق. ولكن بعد ذلك سوف يجد طريقًا كبيرًا عبر الأشواك.

لماذا هذا صحيح؟

  • لأن روي فيلدينغ قال ذلك ؛
  • لأنها الراحة ؛
  • لأن هذه هي المبادئ المعمارية التي تقوم عليها مهنتنا الآن.

ومع ذلك ، هذا هو "سقيفة دراجة" ، والطريقة السابقة ستعمل. أجهزة الكمبيوتر التي أبلغت قبل REST ، وعملت كل شيء. ولكن الآن ظهر معيار في هذه الصناعة.

حذف المادة


النظر في مثال حذف مقال. افترض أن هناك طريقة مورد / DELETE / articles طبيعية ، والتي تزيل المقالة بمعرف. HTTP يحتوي على رؤوس. يقبل رأس قبول نوع البيانات التي يريد العميل تلقيها استجابة. قام junior بكتابة خادم يقوم بإرجاع 200 OK ، نوع المحتوى: application / json ، ويمرر نصًا فارغًا:

01. DELETE /articles/ 1 /1.1
02. Accept: application/json


01. HTTP/1.1 200 OK
02. Content-Type: application/json
03. null

لقد حدث خطأ شائع جدًا هنا - جسم فارغ . يبدو أن كل شيء منطقي - تم حذف المقالة ، 200 موافق ، رأس التطبيق / json موجود ، ولكن على الأرجح سوف يسقط العميل. سوف يلقي خطأ لأن نص فارغ غير صالح. إذا حاولت تحليل سلسلة فارغة من أي وقت مضى ، فأنت تواجه حقيقة أن أي محلل json يتعثر ويتعطل في هذا.

كيفية إصلاح هذا الوضع؟ ربما كان الخيار الأفضل هو تمرير json. إذا ذكرنا: "قبول ، أعطنا json" ، فإن الخادم يقول: "Content-Type ، أنا أعطيك json" ، Give json. كائن فارغ ، صفيف فارغ - ضع شيئًا هناك - سيكون هذا هو الحل ، وسوف ينجح.

لا يزال هناك حل. بالإضافة إلى 200 موافق ، هناك رمز استجابة 204 - لا يوجد محتوى. مع ذلك ، لا يمكنك نقل الجسم. ليس الجميع يعلم عن هذا.

لذلك أنا أدى إلى أنواع الوسائط.

أنواع التمثيل الصامت


تشبه أنواع الوسائط امتداد الملف ، فقط على الويب. عندما نقوم بنقل البيانات ، يجب أن نبلغ أو نطلب أي نوع نريد استلامه استجابةً لذلك.

  • بشكل افتراضي ، هذا هو النص / عادي - مجرد نص.
  • إذا لم يتم تحديد أي شيء ، فسيعني المتصفح على الأرجح التطبيق / octet-stream - مجرد دفق بسيط.

يمكنك تحديد نوع معين فقط:

  • التطبيق / قوات الدفاع الشعبي ؛
  • صورة / بابوا نيو غينيا ؛
  • التطبيق / json ؛
  • التطبيق / XML ؛
  • application / vnd.ms-excel.

تعد محتويات نوع المحتوى وقبولها مهمة ومهمة.

يجب أن يمر كل من واجهة برمجة التطبيقات (API) والعميل برموز نوع المحتوى وقبولها.

إذا كانت واجهة برمجة التطبيقات مبنية على JSON ، فاختار دائمًا قبول: application / json و application-Type application / json.

أنواع الملفات سبيل المثال.


تشبه أنواع الوسائط هذه الأنواع من الملفات ، فقط على الإنترنت.

رموز الإجابة


المثال التالي لمغامرات المطور الصغير لدينا هو رموز الاستجابة.



أطرف معدل الاستجابة هو 200 موافق. الجميع يحبه - وهذا يعني أن كل شيء سار على ما يرام. كان لدي حتى حالة - تلقيت أخطاء 200 موافق . يوجد شيء ما على الخادم ، استجابةً للاستجابة ، تأتي صفحة HTML تم تجميع خطأ HTML عليها. طلبت تطبيق json بالكود 200 OK ، وفكرت في كيفية العمل به؟ تذهب بالرد ، ابحث عن كلمة "خطأ" ، تعتقد أن هذا خطأ.

هذا يعمل ، ومع ذلك ، في HTTP هناك العديد من الرموز الأخرى التي يمكنك استخدامها ، وتوصي REST باستخدامها على REST. على سبيل المثال ، يمكن الرد على إنشاء كيان (مقالة):

  • 201 Created هو رمز ناجح. تم إنشاء المقالة ، استجابةً تحتاج إلى إرجاع المقالة التي تم إنشاؤها.
  • 202 مقبول يعني أنه تم قبول الطلب ، لكن نتائجه ستكون في وقت لاحق. هذه عمليات طويلة الأمد. في مقبول ، لا يمكن إرجاع أي شخص. وهذا هو ، إذا كنت لا تعطي نوع المحتوى في الاستجابة ، فإن الجسم قد لا يكون كذلك. أو نوع المحتوى / النص - هذا كل شيء ، لا أسئلة. السلسلة الفارغة هي نص / مستوى صالح.
  • 204 لا يوجد محتوى - قد يكون الجسم غائبًا تمامًا.
  • 403 ممنوع - غير مسموح لك بإنشاء هذه المقالة.
  • 404 غير موجود - لقد صعدت في مكان خاطئ ، لا توجد مثل هذه الطريقة ، على سبيل المثال.
  • 409 الصراع هو الحالة القصوى التي يستخدمها عدد قليل من الناس. تكون هناك حاجة في بعض الأحيان إذا كنت تقوم بإنشاء معرف على العميل ، وليس على الواجهة الخلفية ، وفي ذلك الوقت تمكن شخص ما بالفعل من إنشاء هذه المقالة. الصراع هو الجواب الصحيح في هذه الحالة.

خلق الكيان


المثال التالي: نقوم بإنشاء كيان ، قل Content-Type: application / json ، ونمرر هذا التطبيق / json. وهذا يجعل العميل - الواجهة الأمامية لدينا. لنقم بإنشاء هذه المقالة بالذات:

01. POST /articles /1.1
02. Content-Type: application/json
03. { "id": 1, "title": " JSON API"}


الكود قد يأتي ردا:

  • 422 كيان غير قابل للمعالجة - كيان غير معالج. يبدو أن كل شيء رائع - دلالات ، هناك رمز.
  • 403 ممنوع
  • 500 خادم داخلي خطأ.

لكن من غير المفهوم تمامًا ما حدث بالضبط: ما نوع الكيان الذي لا تتم معالجته ، لماذا لا يجب أن أذهب إلى هناك ، وما الذي حدث أخيرًا للخادم؟

إرجاع الأخطاء


تأكد (والصغار لا يعرفون ذلك) في الاستجابة ، وإرجاع الأخطاء. هذا هو الدلالي والصحيح. بالمناسبة ، لم يكتب Fielding عن ذلك ، أي تم اختراعه لاحقًا وتم بناؤه على قمة REST.

قد ترجع الواجهة الخلفية صفيفًا به أخطاء في الاستجابة ، وقد يكون هناك عدة.

01. HTTP/1.1 422 Unprocessable Entity
02. Content-Type: application/json
03.
04. { "errors": [{
05. "status": "422",
06. "title": "Title already exist",
07. }]}


يمكن أن يكون لكل خطأ حالته وعنوانه. هذا شيء عظيم ، لكنه بالفعل في مستوى الاتفاقية على رأس REST. قد يكون هذا أداة مكافحة الإقلاع عن التدخين للتوقف عن الجدال وتقديم واجهة برمجة تطبيقات جيدة ومناسبة على الفور.

أضف ترقيم الصفحات


المثال التالي: يأتي المصممون إلى مطور الواجهة الخلفية الخاص بنا ويقولون: "لدينا العديد من المقالات ، نحتاج إلى ترقيم الصفحات. لقد رسمنا هذا ".


لننظر في الأمر بمزيد من التفصيل. بادئ ذي بدء ، 336 صفحة مذهلة. عندما رأيت هذا ، فكرت في كيفية الحصول على هذا الرقم. أين أحصل على 336 ، لأنني عندما أطلب قائمة بالمقالات ، أحصل على قائمة بالمقالات. على سبيل المثال ، هناك 10 آلاف منها ، أحتاج إلى تنزيل جميع المقالات ، مع تقسيم عدد الصفحات ومعرفة هذا الرقم. لفترة طويلة جدًا سأقوم بتحميل هذه المقالات ، أحتاج إلى طريقة للحصول على عدد الإدخالات بسرعة. ولكن إذا كانت API الخاصة بنا تُرجع قائمة ، فأين نضع هذا العدد من السجلات بشكل عام ، لأن مجموعة من المقالات تأتي كرد فعل. اتضح أنه نظرًا لأن عدد السجلات لا يتم وضعه في أي مكان ، فيجب إضافته إلى كل مقالة بحيث يقول كل مقال: "وهناك الكثير منا جميعًا!"

ومع ذلك ، هناك اصطلاح أعلى واجهة برمجة تطبيقات REST التي تعمل على حل هذه المشكلة.

طلب قائمة


لجعل واجهة برمجة التطبيقات قابلة للتوسعة ، يمكنك على الفور استخدام معلمات GET لترقيم الصفحات: حجم الصفحة الحالية ورقمها ، بحيث يتم إرجاع جزء الصفحة الذي طلبناه بالضبط. هذا مريح. ردا على ذلك ، لا يمكنك إعطاء مجموعة على الفور ، ولكن إضافة تداخل إضافي. على سبيل المثال ، سيحتوي مفتاح البيانات على صفيف ، وستحتوي البيانات التي طلبناها ، ومفتاح التعريف ، الذي لم يكن موجودًا من قبل ، على الإجمالي.

01. GET /articles? page[size]=30&page[number]=2
02. Content-Type: application/json

01. HTTP/1.1 200 OK
02. {
03. "data": [{ "id": 1, "title": "JSONAPI"}, ...],
04. "meta": { "count": 10080 }
05. }

بهذه الطريقة ، يمكن لـ API إرجاع معلومات إضافية. بالإضافة إلى العد ، قد يكون هناك بعض المعلومات الأخرى - إنها قابلة للمد. الآن ، إذا لم يفعل المبتدئين ذلك فورًا ، وفقط بعد أن طُلب منه القيام بالتبعية ، قام بعد ذلك بإجراء تغيير غير متوافق مع الوراء ، وكسر واجهة برمجة التطبيقات ، وكان على جميع العملاء إعادة ذلك - عادة ما يكون ذلك مؤلمًا.

ترقيم مختلف. أنا أقدم العديد من الخارقة الحياة التي يمكنك استخدامها.

[إزاحة] ... [الحد]


01. GET /articles? page[offset]=30&page[limit]=30
02. Content-Type: application/json

01. HTTP/1.1 200 OK
02. {
03. "data": [{ "id": 1, "title": "JSONAPI"}, ...],
04. "meta": { "count": 10080 }
05. }

أولئك الذين يعملون مع قواعد البيانات قد يكون لديهم بالفعل [مجموعة إزاحة] ... [الحد]. استخدامه بدلاً من الصفحة [الحجم] ... صفحة [الرقم] سيكون أسهل. هذا هو نهج مختلف قليلا.

وضع المؤشر


01. GET /articles? page[published_at]=1538332156
02. Content-Type: application/json


01. HTTP/1.1 200 OK
02. {
03. "data": [{ "id": 1, "title": "JSONAPI"}, ...],
04. "meta": { "count": 10080 }
05. }


يستخدم موقع المؤشر مؤشرًا للكيان الذي يبدأ به تحميل السجلات. على سبيل المثال ، يكون مناسبًا جدًا عند استخدام ترقيم الصفحات أو التحميل في القوائم التي تتغير كثيرًا. دعنا نقول باستمرار يتم كتابة مقالات جديدة على بلوق. الصفحة الثالثة الآن ليست هي نفس الصفحة الثالثة التي ستكون في دقيقة واحدة ، ولكن إذا انتقلنا إلى الصفحة الرابعة ، فسنحصل على بعض السجلات من الصفحة الثالثة عليها ، لأن القائمة بأكملها ستنتقل.

يتم حل هذه المشكلة عن طريق ترقيم الصفحات المؤشر. نقول: "قم بتحميل المقالات التي تأتي بعد المقال المنشور في ذلك الوقت" - لم يعد هناك أي تحول تقني بحت ، وهذا أمر رائع.

مشكلة N +1


المشكلة التالية التي سيواجهها بالتأكيد مطورنا المبتدئ هي مشكلة N + 1 (سوف يفهمها الداعمون). لنفترض أنك تريد سرد قائمة بعشرة مقالات. نقوم بتحميل قائمة بالمقالات ، ولكل مقالة مؤلف ولكل منها تحتاج إلى تنزيل مؤلف. نحن نشحن:

  • 1 طلب للحصول على قائمة المقالات ؛
  • 10 طلبات لمؤلفي كل مقال.

المجموع: 11 استفسار لعرض قائمة صغيرة.

إضافة الروابط


في الخلفية ، يتم حل هذه المشكلة في جميع ORMs - تحتاج فقط إلى تذكر لإضافة هذا الاتصال. يمكن أيضًا استخدام هذه الاتصالات في الواجهة الأمامية. ويتم ذلك على النحو التالي:

01. GET /articles? include =author
02. Content-Type: application/json

يمكنك استخدام معلمة GET خاصة ، وسميها بما في ذلك (كما في الخلفية) ، مع تحديد الروابط التي نحتاج إلى تحميلها مع المقالات. لنفترض أننا قمنا بتحميل المقالات ، ونريد الحصول على المؤلف فورًا جنبًا إلى جنب مع المقالات. الجواب يشبه هذا:

01. /1.1 200
02. { "data": [{
03. { attributes: { "id": 1, "title": "JSON API" },
04. { relationships: {
05. "author": { "id": 1, "name": "Avdeev" } }
06. }, ...
07. }]}


تم نقل سمات المقالة الخاصة إلى البيانات وتمت إضافة العلاقات الرئيسية. نضع جميع الاتصالات في هذا المفتاح. وبالتالي ، مع طلب واحد ، تلقينا جميع البيانات التي سبق أن تلقت 11 طلبًا. هذا هو اختراق الحياة بارد أن يحل المشكلة مع N + 1 على الواجهة الأمامية بشكل جيد.

مشكلة تكرار البيانات


لنفترض أنك تريد عرض 10 مقالات تشير إلى المؤلف ، وجميع المقالات بها مؤلف واحد ، لكن الكائن مع المؤلف كبير جدًا (على سبيل المثال ، اسم أخير طويل للغاية ، ويستغرق ميغابايت). يتم تضمين مؤلف واحد في الإجابة 10 مرات ، وسوف يستغرق 10 إدخالات لنفس المؤلف في الإجابة 10 ميغابايت.

نظرًا لأن جميع الكائنات متشابهة ، يتم حل مشكلة تضمين مؤلف واحد 10 مرات (10 ميغابايت) بمساعدة التطبيع ، والذي يتم استخدامه في قواعد البيانات. في الواجهة الأمامية ، يمكنك أيضًا استخدام التطبيع في العمل مع واجهة برمجة التطبيقات - هذا رائع جدًا.

01. /1.1 200
02. { "data": [{
03. "id": "1″, "type": "article",
04. "attributes": { "title": "JSON API" },
05. "relationships": { ... }
06. "author": { "id": 1, "type": "people" } }
07. }, ... ]
08. }


نقوم بتمييز جميع الكيانات بنوع ما (هذا هو نوع التمثيل ، نوع المورد). قدم روي فيلدنج مفهوم المورد ، أي أنهم طلبوا مقالات - تلقوا "مقالة". في العلاقات ، نضع رابطًا لنوع الأشخاص ، أي أنه لا يزال لدينا مورد الأشخاص في مكان آخر. والمورد نفسه الذي نأخذه في مفتاح منفصل مدرج ، والذي يقع على نفس مستوى البيانات.

01. /1.1 200
02. {
03. "data": [ ... ],
04. "included": [{
05. "id": 1, "type": "people",
06. "attributes": { "name": "Avdeev" }
07. }]
08. }


وبالتالي ، تندرج جميع الكيانات ذات الصلة في مثيل واحد في المفتاح الخاص المضمّن. نحن فقط تخزين الروابط ، ويتم تخزين الكيانات نفسها في.

انخفض حجم الطلب. هذا هو اختراق الحياة التي لا يعرف النهاية الخلفية. سوف يكتشف لاحقًا عندما يحتاج إلى كسر واجهة برمجة التطبيقات.

ليست جميع حقول الموارد مطلوبة


يمكن تطبيق الاختراق التالي في الحياة عندما لا تكون جميع حقول الموارد مطلوبة. يتم ذلك باستخدام معلمة GET خاصة ، والتي تسرد السمات المراد إرجاعها ، مفصولة بفواصل. على سبيل المثال ، المقالة كبيرة ، ويمكن أن يكون هناك ميغابايت في حقل المحتوى ، ونحن بحاجة إلى عرض قائمة الرؤوس فقط - نحن لسنا بحاجة إلى المحتوى في الاستجابة.

GET /articles ?fields[article]=title /1.1

01. /1.1 200 OK
02. { "data": [{
03. "id": "1″, "type": "article",
04. "attributes": { "title": " JSON API" },
05. }, ... ]
06. }


إذا كنت تحتاج ، على سبيل المثال ، أيضًا إلى تاريخ النشر ، يمكنك كتابة "تاريخ نشر" مفصول بفواصل. استجابة لذلك ، سيأتي حقلان في الصفات. هذه اتفاقية يمكن استخدامها كأداة لمكافحة bikeshedding.

البحث عن طريق المقالات


غالبًا ما نحتاج إلى عمليات البحث والمرشحات. هناك اصطلاحات لهذا - مرشحات خاصة الحصول على المعلمات:

GET /articles ?filters[search]=api HTTP/1.1 - البحث ؛
GET /articles ?fiIters[from_date]=1538332156 HTTP/1.1 - تنزيل المقالات من تاريخ محدد ؛
GET /articles ?filters[is_published]=true HTTP/1.1 - تنزيل المقالات المنشورة للتو ؛
GET /articles ?fiIters[author]=1 HTTP/1.1 - تحميل المواد مع المؤلف الأول.

فرز المواد


GET /articles ?sort=title /1.1 - حسب العنوان ؛
GET /articles ?sort=published_at HTTP/1.1 - حسب تاريخ النشر ؛
GET /articles ?sort=-published_at HTTP/1.1 - حسب تاريخ النشر في الاتجاه المعاكس ؛
GET /articles ?sort=author,-publisbed_at HTTP/1.1 - أولاً حسب المؤلف ، ثم حسب تاريخ النشر في الاتجاه المعاكس ، إذا كانت المقالات من المؤلف نفسه.

تحتاج إلى تغيير عناوين المواقع


الحل: الوسائط التشعبية ، التي ذكرتها بالفعل ، يمكن القيام بها على النحو التالي. إذا أردنا أن يكون الكائن (المورد) يصف نفسه بنفسه ، يمكن للعميل أن يفهم من خلال الوسائط التشعبية ما الذي يمكن عمله به ، ويمكن أن يتطور الخادم بشكل مستقل عن العميل ، ثم يمكننا إضافة روابط إلى قائمة المقالات ، إلى المقال نفسه باستخدام مفاتيح روابط خاصة :

01. GET /articles /1.1
02. {
03. "data": [{
04. ...
05. "links": { "self": "http://localhost/articles/1"
},
06. "relationships": { ... }
07. }],
08. "links": { "self": " http://localhost/articles " }
09. }

أو ذات الصلة ، إذا كنا نريد أن نقول للعميل كيفية تحميل تعليق على هذه المقالة:

01. ...
02. "relationships": {
03. "comments": {
04. "links": {
05. "self": "http://localhost/articles/l/relationships/comments
",
06. "related": " http://localhost/articles/l/comments "
07. }
08. }
09. }

يرى العميل وجود رابط ، يتبعه ، يقوم بتحميل تعليق. إذا لم يكن هناك رابط ، فلا توجد تعليقات. هذا مريح ، لكن قلة قليلة تفعل. جاء تطبيق Fielding وفقًا لمبادئ REST ، لكن لم يدخل كل منهم صناعتنا. نحن نستخدم بشكل رئيسي اثنين أو ثلاثة.

في عام 2013 ، كل الاختراقات الحياتية التي أخبرتك عنها ، اندمج ستيف كلابنيك في مواصفات JSON API وسجلت كنوع وسائط جديد أعلى JSON . لذلك ، أصبح مطور الواجهة الخلفية للناشئين ، الذي يتطور تدريجيًا ، إلى JSON API.

JSON API


يتم وصف كل شيء بالتفصيل على الموقع http://jsonapi.org/implementations/ : هناك قائمة تضم 170 تطبيقًا مختلفًا للمواصفات لـ 32 لغة برمجة - ويتم إضافتها فقط في الكتالوج. تمت كتابة المكتبات والمحللات والمسلسلات وما إلى ذلك.

نظرًا لأن هذه المواصفات مفتوحة المصدر ، فإن الجميع يستثمرون فيها. كتبت ، من بين أشياء أخرى ، شيئًا بنفسي. أنا متأكد من أن هناك الكثير من هؤلاء الناس. يمكنك الانضمام إلى هذا المشروع بنفسك.

JSON API الايجابيات


تعمل مواصفات JSON API على حل عدد من المشكلات - اتفاقية مشتركة للجميع . نظرًا لوجود اتفاق عام ، لا نجادل داخل الفريق - يتم توثيق حظيرة الدراجات. لدينا اتفاق على المواد اللازمة لصنع دراجة هوائية وكيفية طلاءها.

الآن ، عندما يرتكب المطور خطأً وأراه ، لا أبدأ المناقشة ، لكنني أقول: "ليس من خلال واجهة برمجة تطبيقات JSON API!" وتظهر في مكان في المواصفات. إنهم يكرهونني في الشركة ، لكنهم اعتادوا عليها تدريجيًا ، وبدأ الجميع في الإعجاب بـ JSON API. نقدم خدمات افتراضية جديدة وفقًا لهذه المواصفات. لدينا مفتاح تاريخ ، ونحن على استعداد لإضافة التعريف ، وتشمل المفاتيح. يوجد عوامل تصفية معلمة GET محجوزة للمرشحات. لا نناقش ما نسميه مرشح - نحن نستخدم هذه المواصفات. فهو يصف كيفية عمل عنوان URL.

نظرًا لأننا لا نجادل ، ولكننا نقوم بمهام العمل ، فإن إنتاجية التطوير أعلى . لدينا المواصفات الموضحة ، وقراءة المطور الواجهة الخلفية ، وجعل API ، ونحن ثمل على - العميل سعيد.

تم حل المشكلات الشائعة بالفعل ، على سبيل المثال ، مع ترقيم الصفحات. هناك الكثير من التلميحات في المواصفات.

نظرًا لأن هذا هو JSON (بفضل Douglas Crockford لهذا التنسيق) ، فهو أكثر إيجازًا من XML ، ومن السهل جدًا قراءته وفهمه .

حقيقة أن هذا هو المصدر المفتوح يمكن أن يكون زائد وناقص ، لكني أحب المصدر المفتوح.

سلبيات JSON API


نما الكائن (التاريخ والسمات والمضمون وما إلى ذلك) - تحتاج الواجهة الأمامية إلى تحليل الإجابات: تكون قادرة على التكرار على المصفوفات ، والتجول حول الكائن ومعرفة كيفية الحد من الأعمال. ليس كل المطورين المبتدئين يعرفون هذه الأشياء المعقدة. هناك مكتبات من المتسللين / deserializers ، يمكنك استخدامها. بشكل عام ، هذا يعمل فقط مع البيانات ، لكن الكائنات كبيرة.

والخلفية لها ألم:

  • السيطرة على التعشيش - تشمل يمكن تسلقها بعيدا جدا ؛
  • تعقيد استعلامات قاعدة البيانات - يتم بناؤها في بعض الأحيان بشكل تلقائي ، وتبين أنها صعبة للغاية ؛
  • الأمان - يمكنك الصعود إلى الأدغال ، خاصةً إذا كنت تتصل بمكتبة ما ؛
  • المواصفات صعبة القراءة. إنها باللغة الإنجليزية ، وقد أخافت ذلك بعيدًا ، لكن الجميع اعتادوا عليه تدريجيًا ؛
  • لا تطبق جميع المكتبات المواصفات جيدًا - فهذه مشكلة مفتوحة المصدر.

مطبات JSON API


قليلا من المتشددين.

عدد العلاقات في المشكلة غير محدود. إذا قمنا بتضمين ، طلب مقالات ، إضافة تعليقات إليها ، فاستجابة لذلك ، سوف نتلقى جميع تعليقات هذه المقالة. هناك 10000 تعليق - احصل على جميع التعليقات 10000:

GET /articles/1?include=comments /1.1

01. ...
02. "relationships": {
03. "comments": {
04. "data": [0 ... ∞]
05. }
06. }


وبالتالي ، جاء في الواقع 5 ميغابايت لطلبنا ردا: "هو مكتوب في المواصفات - من الضروري إعادة صياغة الطلب بشكل صحيح:

GET /comments? filters[article]=1& page[size]=30 HTTP/1.1

01. {
02. "data": [0 ... 29]
03. }


نطلب التعليقات مع مرشح حسب المادة ، ويقول: "30 قطعة ، من فضلك" والحصول على 30 تعليق. هذا غموض.

نفس الأشياء يمكن أن تصاغ بشكل غامض :

GET /articles/1 ?include=comments HTTP/1.1 - طلب مقال مع التعليقات ؛
GET /articles/1/comments HTTP/1.1 - اطلب التعليقات على المقال ؛
GET /comments ?filters[article]=1 HTTP/1.1 - طلب التعليقات مع مرشح حسب المقالة.

هذا هو نفس الشيء - نفس البيانات ، التي يتم الحصول عليها بطرق مختلفة ، هناك بعض الغموض. هذا المأزق غير مرئي على الفور.

تتحول العلاقات متعددة الأشكال بين الأشكال إلى REST بسرعة كبيرة.

01. GET /comments?include=commentable /1.1
02.
03. ...
04. "relationships": {
05. "commentable" : {
06. "data": { "type": "article", "id": "1″ }
07. }
08. }


هناك اتصال متعدد الأشكال يمكن التعليق عليه في الواجهة الخلفية - يزحف إلى REST. لذلك يجب أن يحدث ، ولكن يمكن أن يكون متنكر. لا يمكنك إخفاءه في JSON API - سيظهر.

قم بتكوين علاقات متعددة لكثير من الخيارات المتقدمة . أيضًا ، تظهر جميع جداول الاتصال:

01. GET /users?include =users_comments /1.1
02.
03. ...
04. "relationships": {
05. "users_comments": {
06. "data": [{ "type": "users_comments", "id": "1″ }, ...]
07. },
08. }


اختيال


Swagger هي أداة كتابة الوثائق عبر الإنترنت.

لنفترض أنه طُلب من مطور الواجهة الخلفية لدينا كتابة الوثائق الخاصة بواجهة برمجة التطبيقات الخاصة به ، وقد كتبها. يكون ذلك سهلاً إذا كانت API بسيطة. إذا كانت هذه واجهة برمجة تطبيقات JSON ، فلا يمكن كتابة Swagger بهذه السهولة.

مثال: Swagger pet store. يمكن فتح كل طريقة ، انظر الرد والأمثلة.



هذا مثال لنموذج الحيوانات الأليفة. هنا واجهة رائعة ، كل شيء سهل القراءة.



وهذه هي الطريقة التي يبدو بها إنشاء نموذج JSON API:



هذه ليست كبيرة جدا. نحتاج إلى بيانات ، في شيء يحتوي على علاقات ، تحتوي البيانات على 5 أنواع من النماذج ، إلخ. يمكنك كتابة Swagger ، فإن Open API هو شيء قوي ، لكنه معقد.

البديل


هناك مواصفات OData ، التي ظهرت بعد ذلك بقليل - في عام 2015. هذه هي "أفضل طريقة للراحة" ، كما يؤكد الموقع الرسمي. يبدو مثل هذا:

01. GET http://services.odata.org/v4/TripRW/People HTTP/1.1 - GET request؛
02. OData-Version: 4.0 - رأس خاص مع الإصدار ؛
03. OData-MaxVersion: 4.0 - رأس الإصدار الخاص الثاني

الجواب يشبه هذا:

01. HTTP/1.1 200 OK
02. Content-Type: application/json; odata.metadata=minimal
03. OData-Version: 4.0
04. {
05. '@odata.context': 'http://services.odata.org/V4/
06. '@odata.nextLink' : 'http://services.odata.org/V4/
07. 'value': [{
08. '@odata.etag': 1W/108D1D5BD423E51581′,
09. 'UserName': 'russellwhyte',
10. ...

هنا هو التطبيق الموسعة / json والكائن.

لم نستخدم OData ، أولاً ، لأنه يشبه واجهة برمجة تطبيقات JSON ، ولكنه ليس موجزًا. هناك أشياء ضخمة ويبدو لي أن كل شيء أسوأ بكثير القراءة. خرج OData أيضًا في Open Source ، لكنه أكثر تعقيدًا.

ماذا عن GraphQL؟


بطبيعة الحال ، عندما كنا نبحث عن تنسيق API جديد ، واجهنا هذه الضجة.

عتبة دخول عالية.

من وجهة نظر الواجهة الأمامية ، يبدو كل شيء رائعًا ، لكن لا يمكنك جعل المطور الجديد يكتب GraphQL ، لأنك تحتاج إلى دراسته أولاً. إنه يشبه SQL - لا يمكنك كتابة SQL على الفور ، يجب عليك على الأقل قراءة ما هي عليه ، والاطلاع على البرامج التعليمية ، أي أن عتبة الإدخال تزداد.

تأثير الانفجار الكبير.

إذا لم يكن هناك API في المشروع ، وبدأنا في استخدام GraphQL ، وبعد شهر أدركنا أنه لا يناسبنا ، فستكون الأوان قد فات. يجب أن تكتب العكازات. يمكنك أن تتطور مع JSON API أو OData - أبسط RESTful ، والتحسين التدريجي ، يتحول إلى JSON API.

الجحيم على الواجهة الخلفية.

تستدعي GraphQL الجحيم على الواجهة الخلفية - واحدة تلو الأخرى ، تمامًا مثل واجهة برمجة تطبيقات JSON التي تم تنفيذها بالكامل ، لأن GraphQL تتحكم بالكامل في الاستعلامات ، وهذه مكتبة ، وستحتاج إلى حل الكثير من المشكلات:

  • مراقبة التعشيش ؛
  • العودية
  • الحد من التردد.
  • التحكم في الوصول.

بدلا من الاستنتاجات


أوصي بوقف الجدل حول سقيفة الدراجة ، واتخاذ أداة مكافحة bikeshedding كمواصفات وقم فقط بإنشاء API مع مواصفات جيدة.

للعثور على المعيار الخاص بك لحل مشكلة سقيفة الدراجات ، يمكنك الاطلاع على هذه الروابط:

http://jsonapi.org
http://www.odata.org
https://graphgl.org
http://xmlrpc.scripting.com
https://www.jsonrpc.org

: alexey-avdeev.com github .

, Frontend Conf , 27 28 ++ . , .

? ? ? , ? !

, , , , .

Source: https://habr.com/ru/post/ar433322/


All Articles