كيفية كتابة API سيئة

اكتب الكود كما لو كان مصحوبًا بمختل عقلاني عنيف يعرف مكان إقامتك.


مرحبا بالجميع!


أعمل كقائد فريق لفريق تطوير التكامل في خدمة حجز الفنادق عبر الإنترنت Ostrovok.ru وأود اليوم أن أشارك تجربتي مع العديد من واجهات برمجة التطبيقات.



كمطور لنظام يعمل مع مزودين خارجيين ، غالبًا ما صادفت عدة واجهات برمجة تطبيقات - غالبًا ما يكون SOAP / REST أو شيء مشابه لها. ومع ذلك ، فإن العمل مع العديد منهم يترك الانطباع بأنهم كتبوا ، لا يسترشدون بأي من القواعد الفنية أو المنطق السليم - كما لو كان من كتاب "نصيحة سيئة" من تأليف غريغوري أوستر. سأحاول في هذه المقالة وصف مثل هذه الحالات بأسلوب "نصيحة سيئة" والنظر في أمثلة متعلقة بـ XML. التعليقات والمناقشة هي موضع ترحيب.


الخلفية التاريخية

SOAP (من الإنجليزية. بروتوكول الوصول إلى الكائنات البسيطة - بروتوكول بسيط للوصول إلى الكائنات) - بروتوكول لتبادل الرسائل المنظمة في بيئة حوسبة موزعة. تم تصميم SOAP في الأساس لتنفيذ استدعاء الإجراء عن بُعد (RPC). الآن يتم استخدام البروتوكول لتبادل الرسائل التعسفية بتنسيق XML ، وليس فقط لإجراءات الاتصال.


انتقل إلى الأمثلة


1. تمرير XML إلى url


ماذا يريد مستخدمو API أكثر من غيرهم؟ بالطبع ، البساطة والموثوقية والدقة. لذلك دعونا لا نقرأ نص الطلب ، لكن نقبل XML كمعلومات مشفرة لعنوان url كمعلمة لمسار الطلب! ماذا يمكن أن يكون أفضل:


http://exapmple.com/xml/form.jsp?RequestName%3DHotelRequest2%26XML%3D%3C%3Fxml%2Bversion%3D%221.0%22%2Bencoding%3D%22UTF-8%22%3F%3E%0A%3CHotelRequest2%2BBuyerId%3D%22test%22%2BUserId%3D%22test%22%2BPassword%3D%22test%22%2BLanguage%3D%22en%22%2BHotel%3D%22-100%22%2BProductCode%3D%221--%22%2BArrivalDate%3D%2223.12.2018%22%2BDepartureDate%3D%2224.12.2018%22%2BArrivalTime%3D%22%22%2BDepartureTime%3D%22%22%2BCurrency%3D%222%22%2BWhereToPay%3D%223%22%2BNumberOfGuests%3D%220%22%2BNumberOfExtraBedsAdult%3D%220%22%2BNumberOfExtraBedsChild%3D%220%22%2BNumberOfExtraBedsInfant%3D%220%22%2B%2F%3E 

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


المفسد

لا أعرف لماذا تم ذلك. المشاكل هنا هي التالية: العديد من الخوادم لها حد لطول مسار الطلب الذي يمكن أن يمر بها. إذا كانت XML كبيرة في حجم البيانات ، فيمكنك أن تسبب خطأ 413 Entity كبير جدًا كأحد السيناريوهات. بالإضافة إلى ذلك ، يتزايد حجم المعلومات ، نظرًا لأننا نقوم بترميز عنوان url قبل الإرسال.


2. نقل المعلومات من خلال التداخل المفرط للكائنات البيانات


دعونا نفكر في كيفية جعل المعلومات في الإجابات صعبة قدر الإمكان؟ دعونا نستخدم هياكل متداخلة ، وحتى في أشكال مختلفة! لم يقل قال من القيام به -


 <Request> <InnerRequest> <RQ>[{"someInfo":"base64Data"}] </RQ> </InnerRequest> </Request> 

في الواقع ، xml من المستوى العلوي ، بداخله هو xml آخر ، وداخله json ، حيث يتم تقديم البيانات في base64 ، ومرة ​​أخرى json فيها ، وسوف تحتوي بالفعل على المعلومات التي نحتاجها! حل كبير ، مثل قصة خيالية حول وفاة Koshchei ، مخبأة في بيضة.


المفسد

واحدة من أكثر العيوب الملحوظة هو التباطؤ في تحليل الاستجابة حتى يتم اجتياز جميع الهياكل المتداخلة ، وبعد ذلك قد يتضح أن رمز الخطأ سلكي في json ، بدلاً من المستويات الأعلى. أفهم أن ترميز البيانات الثنائية في base64 داخل xml / json هو ممارسة شائعة ، ولكن ترميز تنسيق مختلف داخل تنسيق مختلف يتجاوز بالفعل الخير والشر.


3. إضافة معلومات غير مرتبطة ببيانات الطلب وغير صالحة في تنسيق البيانات


افترض أن XML تأتي إلينا في نص الطلب ، ونقوم بمعالجتها ونقدم إجابة. يبدو الأمر معقدًا جدًا لنظام مصمم جيدًا ومحمّل بشكل كبير. دعنا نلزم المستخدمين بإرسال نوع البيانات في نص الطلب. كيف نفعل هذا؟ الحق في نص الطلب ، بالطبع.


 XML= <Request> ... </Request> 

بهذه الطريقة البسيطة ، سنعرف دائمًا أننا تلقينا طلبًا بتنسيق XML.


المفسد

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


4. الازدواجية في البيانات دون الحاجة


لنفترض أن لدينا معلومات مهمة للغاية في بنية استجابة XML. كيف تظهر هذا للمستخدم؟ الأكثر وضوحا - دعنا نظهرها عدة مرات كجزء من الإجابة ، ثم سوف ينتبه إليها بالتأكيد.


 <Response> <Obj Info="Important"> <ObjSetting Info="Important"/> <Name>SomeName</Name> <Info>Important</Info> </Obj> </Response> 

بعد ذلك ، سوف ينتبه المستخدم النهائي بالتأكيد إلى حقل المعلومات.


المفسد

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


5. تمرير المعلمات من نفس النوع بشكل فردي ، وليس مجموعة


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


 <Request> <Age1>20</Age> <Age2>20</Age> <Age3>0</Age> <Age4>0</Age> </Request> 

المفسد

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


6. إعادة توجيه المعلومات من الطلبات السابقة كجزء من سلسلة الاتصال API


حان الوقت للتفكير في أمان واجهة برمجة التطبيقات. كيف نفهم أن المستخدم يتلقى معلومات من إجاباتنا السابقة؟ دعه يرسل لنا جوابنا ، بالطبع!


 <Request> <RequestInfo/> <PreviosResp> ... </PreviosResp> </Request> 

المفسد

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


7. لا تستخدم علامات الخطأ التي حدثت ، مثل علامة خطأ أو رمز http


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


 <Response> <ImportantInfo/> </Response> 

- مع رمز استجابة 200 موافق.


المفسد

الاختلاط في الأخطاء التي ارتكبت هي ممارسة سيئة للغاية. المشكلة هي أن كل شيء يبدو كما لو أنه لا توجد أي مشاكل في الإجابة: لا توجد علامة <Error> ، تشير الحالة http إلى أن كل شيء في محله. في هذه الحالة ، من الضروري القيام بالتحقق الإضافي من المعلومات المستلمة حتى لا تكون هناك عواقب غير متوقعة بالفعل في نظامنا.


استنتاج
على الرغم من الكم الهائل من الوثائق المتعلقة بالعمل مع تقنيات SOAP / XML وتصميم API ، لا تزال العديد من المشكلات ذات صلة ، وبعض الحلول تتعارض مع المنطق السليم. آمل أن أتمكن من هذا المقال من لفت انتباه مطوري البرامج إلى أنجح الطرق من أجل تقليل عددهم في المستقبل.

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


All Articles