27. تمرين التطبيق: الإصدار 9
نعود إلى الإصدار 7 من تمرين التطبيق، وبدلاً من تبادل العميل وخادم الويب لسلاسل JSON، سيتبادلان الآن XML.
تظل البنية كما هي:

27.1. خادم الويب

يتم إنشاء المجلد [http-servers/04] عن طريق نسخ المجلد [http-servers/02]، باستثناء المجلد الفرعي [utilities]. ثم يتم تغيير العناصر التالية:

يتم تعديل ملف [config] على النحو التالي:
# dépendances absolues
absolute_dependencies = [
# dossiers du projet
# BaseEntity, MyException
f"{root_dir}/classes/02/entities",
# InterfaceImpôtsDao, InterfaceImpôtsMétier, InterfaceImpôtsUi
f"{root_dir}/impots/v04/interfaces",
# AbstractImpôtsdao, ImpôtsConsole, ImpôtsMétier
f"{root_dir}/impots/v04/services",
# ImpotsDaoWithAdminDataInDatabase
f"{root_dir}/impots/v05/services",
# AdminData, ImpôtsError, TaxPayer
f"{root_dir}/impots/v04/entities",
# Constantes, tranches
f"{root_dir}/impots/v05/entities",
# index_controller
f"{root_dir}/impots/http-servers/01/controllers",
# scripts [config_database, config_layers]
script_dir,
# Logger, SendAdminMail
f"{root_dir}/impots/http-servers/02/utilities",
]
- السطر 21: حدد الدليل الخاص بالأدوات المساعدة التي تبقى في [http-servers/02]؛
يتغير البرنامج النصي الرئيسي [main] على النحو التالي:
- التغيير الوحيد هو في السطر 23: نرسل الآن استجابة بتنسيق XML؛
يتم تعريف الدالة [xml_response] في الوحدة النمطية [myutils]:
- السطر 3: تأخذ الدالة [xml_response] كمعلمات:
- قاموس [result] المراد تحويله إلى XML؛
- رمز الحالة [status_code] الذي سيتم إرجاعه إلى عميل الويب؛
- السطر 5: نستخدم مكتبة [xmltodict] لتوليد سلسلة XML؛
- السطر 8: نستخدم رأس [Content-Type] لإخبار العميل بأننا نرسل XML؛
يجب استيراد الدالة [xml_response] إلى البرنامج النصي [__init__.py]:
from .myutils import set_syspath, json_response, decode_flask_session, xml_response
ثم يجب تضمين الوحدة النمطية [myutils] في الوحدات النمطية على مستوى الجهاز. يتم ذلك في محطة PyCharm باستخدام الأمر [pip install .] (في مجلد الحزم).
27.2. عميل الويب
27.2.1. الكود
يتم إنشاء مجلد [http-clients/04] عن طريق نسخ عميل [http-clients/02]. ثم نقوم بتعديل فئة [ImpôtsDaoWithHttpClient] على النحو التالي:
- السطر 30: أصبحت استجابة HTTP [response] الواردة من خادم الويب الآن سلسلة XML. تظهر السجلات تنسيقها:
2020-07-27 15:53:47.886283, Thread-2 : <?xml version="1.0" encoding="utf-8"?>
<réponse><result><marié>non</marié><enfants>2</enfants><salaire>100000</salaire><impôt>19884</impôt><surcôte>4480</surcôte><taux>0.41</taux><décôte>0</décôte><réduction>0</réduction></result></réponse>
يبلغ طول السلسلة [<?xml version="1.0" encoding="utf-8"?>] 38 حرفًا. علاوة على ذلك، إذا نظرنا إلى ملف السجل باستخدام محرر سداسي عشري، نرى أنه بعد هذه السلسلة يوجد حرف سطر جديد \n. ثم يأتي الرد <response>…</response>. وبالتالي، تبدأ سلسلة XML التي نحتاج إلى تحويلها بعد أول 39 حرفًا من سلسلة XML. تبدأ عند الحرف رقم 39، مع ترقيم الحرف الأول برقم 0. يتم الحصول على هذه السلسلة باستخدام التعبير [response.text[39:]].
إذا قمنا بتشغيل العميل (اتبع الإجراء من الأمثلة السابقة)، فسنحصل على نفس النتائج في ملف [results.json] كما في الإصدارات السابقة. السجلات هي كما يلي:
2020-07-27 16:21:14.015941, Thread-1 : début du thread [Thread-1] avec 2 contribuable(s)
2020-07-27 16:21:14.016940, Thread-1 : début du calcul de l'impôt de {"id": 1, "marié": "oui", "enfants": 2, "salaire": 55555}
2020-07-27 16:21:14.016940, Thread-2 : début du thread [Thread-2] avec 3 contribuable(s)
2020-07-27 16:21:14.018939, Thread-2 : début du calcul de l'impôt de {"id": 3, "marié": "oui", "enfants": 3, "salaire": 50000}
2020-07-27 16:21:14.019979, Thread-3 : début du thread [Thread-3] avec 3 contribuable(s)
2020-07-27 16:21:14.019979, Thread-3 : début du calcul de l'impôt de {"id": 6, "marié": "oui", "enfants": 3, "salaire": 100000}
2020-07-27 16:21:14.021938, Thread-4 : début du thread [Thread-4] avec 2 contribuable(s)
2020-07-27 16:21:14.021938, Thread-4 : début du calcul de l'impôt de {"id": 9, "marié": "oui", "enfants": 2, "salaire": 30000}
2020-07-27 16:21:14.021938, Thread-5 : début du thread [Thread-5] avec 1 contribuable(s)
2020-07-27 16:21:14.022939, Thread-5 : début du calcul de l'impôt de {"id": 11, "marié": "oui", "enfants": 3, "salaire": 200000}
2020-07-27 16:21:14.031942, Thread-1 : <?xml version="1.0" encoding="utf-8"?>
<réponse><result><marié>oui</marié><enfants>2</enfants><salaire>55555</salaire><impôt>2814</impôt><surcôte>0</surcôte><taux>0.14</taux><décôte>0</décôte><réduction>0</réduction></result></réponse>
2020-07-27 16:21:14.031942, Thread-1 : fin du calcul de l'impôt de {"id": 1, "marié": "oui", "enfants": 2, "salaire": 55555, "impôt": 2814, "surcôte": 0, "taux": 0.14, "décôte": 0, "réduction": 0}
2020-07-27 16:21:14.031942, Thread-1 : début du calcul de l'impôt de {"id": 2, "marié": "oui", "enfants": 2, "salaire": 50000}
2020-07-27 16:21:14.034941, Thread-4 : <?xml version="1.0" encoding="utf-8"?>
<réponse><result><marié>oui</marié><enfants>2</enfants><salaire>30000</salaire><impôt>0</impôt><surcôte>0</surcôte><taux>0.0</taux><décôte>0</décôte><réduction>0</réduction></result></réponse>
…
2020-07-27 16:21:17.055931, Thread-3 : fin du thread [Thread-3]
2020-07-27 16:21:17.059930, Thread-2 : <?xml version="1.0" encoding="utf-8"?>
<réponse><result><marié>non</marié><enfants>3</enfants><salaire>100000</salaire><impôt>16782</impôt><surcôte>7176</surcôte><taux>0.41</taux><décôte>0</décôte><réduction>0</réduction></result></réponse>
2020-07-27 16:21:17.060971, Thread-2 : fin du calcul de l'impôt de {"id": 5, "marié": "non", "enfants": 3, "salaire": 100000, "impôt": 16782, "surcôte": 7176, "taux": 0.41, "décôte": 0, "réduction": 0}
2020-07-27 16:21:17.060971, Thread-2 : fin du thread [Thread-2]
على جانب الخادم، السجلات هي كما يلي:
2020-07-27 16:32:04.983020, Thread-46 : [index] requête : <Request 'http://127.0.0.1:5000/?marié=oui&enfants=2&salaire=50000' [GET]>
2020-07-27 16:32:04.983020, Thread-46 : [index] mis en pause du thread pendant 1 seconde(s)
2020-07-27 16:32:04.984021, Thread-47 : [index] requête : <Request 'http://127.0.0.1:5000/?marié=oui&enfants=2&salaire=55555' [GET]>
2020-07-27 16:32:04.984021, Thread-47 : [index] mis en pause du thread pendant 1 seconde(s)
…
2020-07-27 16:32:07.001271, Thread-56 : [index] mis en pause du thread pendant 1 seconde(s)
2020-07-27 16:32:07.003078, Thread-54 : [index] {'réponse': {'result': {'marié': 'oui', 'enfants': 5, 'salaire': 100000, 'impôt': 4230, 'surcôte': 0, 'taux': 0.14, 'décôte': 0, 'réduction': 0}}}
2020-07-27 16:32:07.006078, Thread-55 : [index] {'réponse': {'result': {'marié': 'oui', 'enfants': 3, 'salaire': 200000, 'impôt': 42842, 'surcôte': 17283, 'taux': 0.41, 'décôte': 0, 'réduction': 0}}}
2020-07-27 16:32:08.002824, Thread-56 : [index] {'réponse': {'result': {'marié': 'non', 'enfants': 2, 'salaire': 100000, 'impôt': 19884, 'surcôte': 4480, 'taux': 0.41, 'décôte': 0, 'réduction': 0}}}
- يستمر المسجل في كتابة قاموس الاستجابة بدلاً من سلسلة XML المرسلة إلى العميل. هذا ليس خطأً بل أمر مقصود؛
27.2.2. اختبار طبقة [DAO] للعميل

فئة الاختبار [TestHttpClientDao] هي نفسها الموجودة في |الإصدار 7| وتُنتج النتائج نفسها.