VOL59: Improving Code Quality with SonarQube
أهلًا وسهلا بكم في العدد التاسع والخمسين من النشرة الأسبوعية لاقرأ-تِك 🚀
لا تنسوا أهلنا من صالح الدعاء,اللهم إنّا استودعناك اياهم، اللهم كُن عوناً لهم، اللهم انصرهم واحفظهم. 🇵🇸
أهلًا وسهلا بكم في العدد التاسع والخمسين من النشرة الأسبوعية لاقرأ-تِك 🚀
سواء كنت مهندس برمجيات مبتدئ أو محترف، فنشرتنا هدفها انها تثري المحتوى التقني العربي سعيا للتطوير من جودة المحتوى باللغة العربية، من خلال تقديم أحدث المستجدات والتطورات في عالم البرمجيات، بالإضافة إلى أفضل الممارسات والنصائح القيمة، ونشر أحدث المقالات وترشيحات الكتب ومحتوى ورقة وقلم اللي بينزلوا بشكل مستمر في موقع اقرأ-تِك.
في الإصدار ده الفهرس هيكون كالآتي:
Improving Code Quality with SonarQube
Deep Dive Into Rate Limiting
Isolate, Single Threaded, and Event Loop in Flutter
Uber’s Docstore Architecture
الإصدار الأول من مدونات فطين في تصميم النظم
Improving Code Quality with SonarQube
أداة مفتوحة المصدر بتحلل جودة الكود في مشروعك وبتظهرلك المشاكل الموجودة فيه في أكثر من جهة مهمة:
Code Cleanliness هل الكود مكتوب بطريقة سليمة وبيتبع أفضل الممارسات ولا لاء
Bugs and programming issues هل في أخطاء برمجية زي ال NullPointerExceptions…
Security Analysis هل في ثغرات امنية في الكود ؟
Code Coverage هل سطور الكود متغطية ب unit tests كفاية ولا لاء
ال 4 جهات دي ممكن نغفل عنهم أثناء عملية التطوير لأنهم ممكن بسهولة يعدوا من ال Compiler و من ال MR Review و خصوصًا لو أنتم في فريق صغير أو في وقت ضغط وهكذا و الكود يتنسي و تفضل المشاكل موجودة بتقول لل Exploiter أو السيناريو الغلط أنا أهو.🫠
ميزة SonarQube إنك تقدر تبني Quality Gate علي ال Codebase ككل فيديك تحليل لحالة الكود في مشروعك ككل فتظهر المشاكل و أنتم كفريق تحلوها مع الوقت , وكمان تقدر تعمل Quality Gate كجزء من ال pipeline وتشتغل إنها تحلل كل كود جديد قبل ما يوصل لل Production وبكدا نتفادى إننا نزود أي أخطاء ومشاكل جديدة.
مميزات Sonarqube
يدعم لأكثر من لغة برمجة زى Java, JavaScript, Python, C#, PHP, TypeScript وغيرها كتير.
بتقدر تدمجه بسهولة مع أدوات كتيرة في كل مراحل التطوير تقريبًا زي Jenkins, IntelliJو GitLab
ال Dashboards اللي بيقدمها شاملة وواضحة وبسيطة للتعامل
يمكنك تشغيله علي ال server الخاص بك مما يتيح خصوصية أفضل
الحلو طبعًا مبيكملش ففي مأخذين مهمين علي SonarQube كأداة:
أي نعم هو مفتوح المصدر ونسخة ال Community متاحة للاستخدام للجميع, ولكن كثير من الميزات المتقدمة مش متاحة فيها ومتاحة فقط في النسخ المدفوعة.
في المشاريع الكبيرة بيستهلك موارد كثيرة و يكون عادة أبطأ (فكروا في حالة ال Monorepo مثلاً هو Static code analysis وقدامه كمية كود ضخمة يحللها)
نصيحتنا ليكم كفريق إنكم تستخدموا محلل جودة للكود سواء SonarQube أو غيره وسواء كنتم في Startup أو في شركة كبيرة لأنه بيخلي كل فرد في الفريق يكتب كود أنضف، أكثر أمانًا، وأسهل في الصيانة ومع الوقت جودة كتابتك كفرد للكود هتعلى بسببه ما احنا عرفنا بيشتكي امتي بقي 😅.
Deep Dive Into Rate Limiting
الـ Rate Limiting هو واحد من أهم الـ Mechanisms اللي بنستخدمها في الـ Software Systems اللي عاوزينها تكون Scalable و Secure عشان نتحكم في كمية الـ Requests اللي ممكن النظام يعالجها في وقت معين.
الفكرة الأساسية هي إننا نحمي النظام من الـ abuse، سواء من users بيحاولوا يستهلكوا موارد زيادة أو من هجمات زي الـ DDoS.
فخلونا نتعرف أكتر عنه لإنه أحد الأجزاء الرئيسية في وقتنا الحالي خصوصا في الـ Distributed Systems وبنحتاجه احياناً واحنا بنعمل System Design ، وهنشرح برضو أنواع الـ algorithms المختلفة المستخدمة في الـ Rate Limiting وازاي تختار الأنسب لنظامك.
واتكلمنا في ورقة وقلم عن الموضوع ده قبل كده
ليه ممكن نحتاج الـ Rate Limiting
الـ Rate Limiting مش مجرد فكرة لحماية النظام من الـ abuse، ولكنه بيقدم layers من الـ control والـ scalability اللي بتحمي الـ backend من مشاكل مختلفة زي:
الـ Overload على الـ Resources:
عدد كبير جدًا من الـ requests ممكن يسبب ضغط على الـ servers، وده بيأثر على الـ performance لكل المستخدمين.حماية الـ APIs من الـ abuse:
سواء كان هجوم DDoS أو user بيحاول يعمل spam.تحسين تجربة المستخدم:
لما نضمن إن كل المستخدمين بياخدوا نصيب عادل من الـ resources، ده بيحسن الـ UX ككل بالنسبة للمستخدمين.
المكونات الرئيسية لأي Rate Limiter
علشان نفهم الـ Rate Limiting بعمق، لازم نبص على المكونات الأساسية اللي بتكوّن أي implementation ألا وهي:
الـ Quota: وده بيكون الحد الأقصى للـ requests اللي ممكن client يعمله خلال فترة زمنية معينة (مثلاً 100 request لكل دقيقة) وطبعًا لو حاولتوا تعملوا Integration مع Third Party APIs بتلاقوا الـ Quota دي محددة ولو بتعديها بيبدأ الـ System يبعتلك Errors على الـ Requests اللي بتبعتها.
الـ Interval: الفترة الزمنية اللي بيتم فيها تطبيق الـ limit (مثلاً دقيقة، أو ساعة).
الـ Policy: القواعد اللي بتحدد الـ behavior لما الـ limit يتعدى ودي بتختلف باختلاف نوع الـ System زي:
إننا نـ Reject requests فورًا ونبعت للـ clients انهم تعدوا الـ Quota.
ممكن نعمل Delay requests بحيث يستنوا فترة أطول وبعدين يتنفذوا.
وممكن نـ Apply exponential backoff ودي باننا بنستنى بوقت Exponential مش Fixed وليكن أول مرة هنستنى ثانيتين بعدين 4 وبعدين 8 وبعدين 16.
الـ Storage: ودي مهمة عشان نقدر نتتبع الـ requests، فالـ Rate Limiting implementation محتاج يخزن معلومات زي timestamps وعدد الـ requests. وكل ده ضروري عشان نعرف نـ Apply الـ Rate Limiting فممكن يتنفذ باستخدام:
الـ In-Memory Storage: ممكن نطبق الـ Rate Limiting باستعمال Redis أو Memcached.
الـ Distributed Systems: لو الـ API بتشتغل على أكتر من server وعاوزين نـ Apply Rate Limiting على الـ API ده فمش هينفع كل Machine تخزن Local المعلومات دي فمحتاجين Distributed Systems نقدر نرجع ليه بالنسبة لكل الـ Servers اللي موجودة.
Fixed Window Counter
إزاي الـ Fixed Window بيشتغل:
الـ Fixed Window هو أبسط algorithm لتطبيق الـ Rate Limiting. وفكرته ببساطة هي إنه بيقسم الوقت لـ windows ثابتة (مثلاً كل دقيقة) وبيسمح بعدد معين من الـ requests لكل window.
لو العدد تعدى الحد المسموح، الـ requests الزايدة بتترفض أو على حسب الـ Policy زي ما شوفنا في المكونات الرئيسية للـ Rate Limiter.
مميزات الـ Fixed Window:
بسيط وسهل التنفيذ.
مناسب للـ use cases اللي مش بتحتاج دقة عالية في تطبيق الـ Rate Limiting.
عيوب الـ Fixed Window:
مش دقيق، خصوصًا لو الـ requests وصلت في نهاية window وبداية window جديدة فموضوع الـ Overlapping ده والدقة مش بيكون أفضل حاجة فيه.
إمتى نستخدم الـ Fixed Window:
لو كانت الـ APIs اللي شغالين عليها مش بتحتاج rate control دقيق جدًا.
Isolate, Single Threaded, and Event Loop in Flutter
كثيرًا ما نسمع أن لغة Dart، وهي اللغة الأساسية لإطار Flutter، تعتمد على مبدأ الـ Single Thread، ولكن ما المقصود بهذا المفهوم؟ وما هو الـ Thread أصلًا؟ وكيف تعمل المفاهيم المرتبطة به مثل Isolate وEvent Loop في بيئة Flutter؟
في هذا المقال، سنتعرف بشكل أعمق على هذه المفاهيم، وسنشرح كيف يدير Flutter تنفيذ الأوامر البرمجية، ومعالجة المهام المختلفة دون التأثير على أداء واجهة المستخدم، مع الحفاظ على تجربة استخدام سلسة وخالية من التجميد.
مبدأ الـ Single Thread
بدايةً، يمكننا تعريف الـ Thread بأنه وحدة التنفيذ داخل البرنامج، أي المسار الذي تُنفّذ فيه مجموعة من الأوامر والتعليمات البرمجية.
وعندما نقول إن Dart تعتمد على Single Threaded Execution، فإننا نعني أنها تستخدم مسار تنفيذ واحد فقط لمعالجة جميع المهام. هذا المسار يُنفّذ التعليمات بشكل تسلسلي ومتزامن (Synchronous)، أي أن كل مهمة تنتظر انتهاء المهمة التي قبلها لتبدأ، دون وجود تنفيذ متوازي بشكل افتراضي.
ولكن، ماذا يحدث إذا كانت إحدى هذه المهام تستغرق وقتًا طويلًا، مثل طلب بيانات من الإنترنت أو قراءة ملف كبير؟ في هذه الحالة، سيتوقف تنفيذ باقي المهام إلى أن تنتهي هذه المهمة، مما يؤدي إلى تجميد واجهة المستخدم وتجربة غير مرضية.
وهنا يظهر التساؤل: كيف يتعامل Flutter مع هذا التحدي؟ وكيف يمكنه تشغيل مهام متعددة أو ثقيلة دون التأثير على السلاسة العامة للتطبيق؟
الجواب يكمن في مفاهيم مثل Isolates و Event Loop، والتي سنشرحها في الأقسام القادمة من هذا المقال.
مفهوم الـ Isolate
لكي نتمكن من تنفيذ عدة مهام في نفس الوقت دون التأثير على سلاسة واجهة المستخدم (UI) أو التسبب في تجميد التطبيق، فإن Flutter يوفر لنا ميكانيكية تُدعى Isolate.
الـ Isolate هو ببساطة وحدة تنفيذ مستقلة، أو ما يمكن تشبيهه بـ "آلة صغيرة" مسؤولة عن تنفيذ المهام بشكل متوازي (Parallel Execution). كل Isolate يمتلك Thread خاص به، مما يعني أنه لا يشارك الذاكرة (Memory) مع الـ Isolates الأخرى، بل يعمل بشكل منفصل تمامًا.
في بيئة Flutter، يوجد ما يُعرف بـ Main Isolate، وهو المسؤول عن تنفيذ واجهة المستخدم والتعامل مع التفاعلات (الضغط على الأزرار، التحريك، إلخ). هذا الـ Isolate الرئيسي لا يشارك ذاكرته مع الـ Isolates الأخرى، ولذلك لا يمكنه التواصل معها بشكل مباشر.
لكن، كيف يتم التواصل إذًا؟ يتم ذلك عبر ما يُعرف بـ Message Passing باستخدام SendPort وReceivePort. بهذه الطريقة، يمكن للـ Isolates تبادل البيانات والرسائل فيما بينها دون الحاجة لمشاركة نفس الذاكرة، وهو ما يحافظ على الأمان ويمنع التعارضات في البيانات.
هذه الآلية تمنح Flutter القدرة على تشغيل مهام ثقيلة مثل تحليل البيانات أو قراءة ملفات ضخمة أو عمليات الـ JSON parsing في خلفية التطبيق، دون التأثير على الأداء العام أو استجابة الواجهة.
خصم 50% على جميع خطط الاشتراك السنوية لفترة محدودة، تقدروا دلوقتي تشتركوا في اقرأ-تِك وتستمتعوا بكافة المقالات في كل ما يخص هندسة البرمجيات باللغة العربية والمحتوى المميز من ورقة وقلم ومدونات فطين اللي بيتميزوا بتصاميم ذات جودة عالية وكل ده بحرية كاملة وكمان مفاجآت اقرأ-تِك الجاية 🚀
وبرضو متاح الاشتراك من خلال InstaPay و VodafoneCash 🎁
مدونات فطين في تصميم النظم - الإصدار الأول 🚀
كتابة هذا الكتاب لم تكن قرارًا مخططًا... بل كانت نتيجة لتراكمات من الحيرة، الإحباط، والدهشة اللي بيواجهوا أغلب الشباب حاليًا خصوصًا في رحلة البحث عن تعلم مهارات تصميم النظم واللي أصبحت من المهارات الأساسية في الانترفيوهات بالإضافة لكونها مهمة فعلًا على جميع المستويات.
على مدار سنوات من العمل داخل شركات تكنولوجية متعددة، وجدت نفسي مرارًا أواجه بعض الأسئلة زي:
لماذا صُمّم هذا النظام بهذه الطريقة؟
لماذا لم نرَ المشكلة إلا بعد فوات الأوان؟
هل كان يمكن أن نصمم الأمر بشكل أبسط؟
الإجابات كانت دائمًا معقدة، وتعود لأبعاد تقنية وتنظيمية ونفسية أيضًا.
هذا الكتاب ليس دليلًا أكاديميًا، بل هو مجموعة من التجارب والخبرات العملية كتبتها بعين المهندس الذي يراقب، يسأل، ويُخطئ ثم يتعلّم. المجموعة دي لم يتم ترجمتها للعربية من مدونات الشركات العالمية .. بل تم اعادة شرحها وتبسيطها باللغة العربية بأسلوب مختلف حتى تتسم بالبساطة بالإضافة لتميزها بالرسوم التوضيحية الجذابة.
اخترت اسم "فَطين" لأنه الشخصية التي تمنيت لو كانت موجودة معي منذ البداية— يسأل الأسئلة الصحيحة، ويفكّر بصوت عالٍ، ويحكي لك الدروس المستفادة.
إن كنت مهندسًا في بداية الطريق، أو تعمل منذ سنين ولديك خبرة متوسطة أو متقدمة في تصميم وبناء النظم فهذا الكتاب كتبته لك ليكون مرجعًا عمليًا لك يساعدك في تطوير مهاراتك التحليلية والفكرية في بناء وتطوير النظم الضخمة.
يتناول الكتاب ما يعادل من 15 تجربة عملية مميزة من داخل الشركات العالمية في تصميم النظم الضخمة بأكتر من 160 صفحة ويضم الآتي :
Introduction Into System Design
How Uber Serves Over 40 Million Reads Per Second
How Discord Stores Trillions of Messages
Dropbox's Chrono: Scalable, Consistent and Metadata Caching Solution
Unlocking Notion's Power - The Data Model Explained
How Shopify Mitigates Deadlocks in High Concurrency Environments
How LinkedIn Improves Microservices Performance With Protobuf
How Figma Secures Internal Web Applications
How GitHub Improves Reliability of Code Push Processing
How Meta Leverages AI For Efficient Incident Response
How Stripe Architected Massive Scale Observability Solution on AWS
Change Data Capture at Pinterest
How Canva Built Scalable and Reliable Content Usage Counting Service
How Netflix Migrates Critical Traffic at Scale With No Downtime
How Slack Handles Billions of Tasks in Milliseconds
How YouTube Supports Billions of Users With MySQL
System Design Comprehensive Guide
تقدروا تشوفوا النسخة كاملة من هنا كـ E-Book ، وحاولنا نخليها بسعر رمزي يناسب الجميع 👇
وكمان وفرناه على Kindle عشان الناس اللي بتحب تجربة القراءة على الـ Kindle منحرمهاش من التجربة الممتعة دي 🎉
بفضل الله أصبح متاح حاليا دعمنا من خلال الرعاة والشراكات وفعلنا الـ Sponsorship واحنا بنرحب بجميع الشراكات مع المؤسسات والشركات وأصحاب الأعمال لبناء مجتمع عربي يشجع على القراءة والتعلم ومشاركة التجارب والخبرات العملية في هندسة البرمجيات.
دورك كشريك أو راعي هيكون محوري في دعم المحتوى وتوسيع نطاق تأثيره. فانضم لرحلتنا وكن جزءًا من صناعة مستقبل التكنولوجيا في المنطقة 🚀
تقدروا تشوفوا التفاصيل كاملة من هنا والـ Analytics بتاعتنا من خلال اقرأ-تِك والنشرة الأسبوعية 👇
Uber’s Docstore Architecture
شركة Uber بتستعمل Docstore وهو عبارة عن قاعدة البيانات الموزعة بتاعتهم واللي مبنية على MySQL و Docstore بتخزن عشرات الـ PetaBytes من البيانات وبتخدم عشرات الملايين من ال Requests في الثانية.
ودي واحدة من أكبر محركات قواعد البيانات عند Uber واللي بتستخدمها كتير من الـ Microservices في كل القطاعات التجارية أو اللي بنسميها Business Verticals عندهم.
والكلام ده من ساعة ما بدأت في 2020، عدد المستخدمين وحالات الاستخدام بتاعت Docstore في ازدياد، وكمان حجم الطلبات والبيانات في زيادة.
Motivation
شركة Uber كانت بتستعمل الـ Schemaless Types من قواعد البيانات , واللي خلتها بعد كده تقابل شوية تحديات كبيرة والي خلتها تتجه لاستعمال Cassandra كـ Database وتبقى كـ General Purpose Database لمعظم الـ Business Verticals.
ولكن مع حجم الـ Scale بتاع Uber كان الـ Operations على Cassandra كبيرة جدًا ومش فعالة بالنسبة ليهم من ناحية الكفاءة بتاعتها والـ Scale بتاع Uber ، بالاضافة كمان لان Cassandra بتدعم الـ Eventual Consistency وده Consistency Level بالنسبة لـ Uber مكنش أفضل حاجة من ناحية المتطلبات بتاعتهم خصوصا ان هم بيطمحوا لتحقيق الـ Strict Serializability Consistency Level.
ومن ثم ظهر الحاجة لتصميم Docstore واللي مبني على MySQL.
Docstore
قاعدة البيانات دي بتتميز بعدة مميزات من ضمنها انها بتوفر الـ Strict Serializability Consistency Model على مستوى الـ Partition وده كان من ضمن المتطلبات اللي Uber عاوزة تحققها وبالتالي نقدر نستنج هنا ان Uber بتضحي بالـ Availability في سبيل الـ Consistency من ناحية نظرية الـ CAP Theorem.
كمان نقدر نـ Scale Horizontally واللي اتاح الفرصة لـ Uber انها بالشكل ده قاعدة البيانات تكون بتدعم وبتخدم عدد كبير من الـ Heavy Workloads اللي عندهم.
ومش بس كده ده كمان بتوفر مميزات كتير بتحسن من انتاجية المطورين زي الـ Transactions / Materialized Views / CDC بالإضافة للمرونة في عمل الـ Modeling للبيانات وكذلك وفرة من الـ Query Support اللي الـ Clients ممكن يكونوا محتاجينها.
Docstore Architecture
هنلاقي أن Docstore متقسمة بشكل رئيسي لثلاث أجزاء أو طبقات Layers:
1- الـ Stateless Query Engine Layer
2- الـ Stateful Storage Engine Layer
3- الـ Control Plane
وللتذكير Stateless من اسمها يعني مش مسئولة عن الاحتفاظ بأي State نهائيًا أو معلومات ، بينما الـ Stateful فهي بتحتفظ بالـ State أو بعض المعلومات عشان تستفيد منها في أداء شغلها.
الـ Stateless Query Engine مسئول بشكل أساسي عن الـ Query Planning والـ Routing والـ Sharding والـ Schema Management وكمان الـ Node Health Monitoring والـ Request Parsing والـ Validation والـ AuthN/AuthZ.
والـ AuthN اللي هي اختصار لـ Authentication والـ AuthZ اختصار للـ Authorization.
بينما الـ Stateful Storage Engine مسئول بشكل أساسي عن تحقيق الـ Consensus من خلال Raft وده طبعًا بيتم استعماله بشكل أساسي في النظم الموزعة لضمان تحقيق الـ Replication بكفاءة واتساق البيانات أو ما يعرف بالـ Consistency.
والـ Storage Engine كذلك مسئول عن الـ Replication والـ Transactions والـ Concurrency Control والـ Load Management.
والـ Control Plane هم مسئول بشكل أساسي على انه يـ Assign الـ Shards للـ Docstore Partitions ويعدل ويغير من الـ Shard بناء على الـ Failure اللي ممكن تحصل في أي وقت. فهو زي المخ لعملية تحديد الـ Shards على الـ Partitions.
وزي ماحنا شايفين في الصورة احنا عندنا أكتر من Partition كل جزء بيكون عبارة عن بعض الـ MySQL Nodes مدعومة بـ NVMe SSDs واللي قادرة على انها تتحمل الأحمال الثقيلة في القراءة والكتابة Heavy Read and Write Workloads.
رؤيتنا هي إثراء المحتوى التقني العربي وجعل التعلم من خلال القراءة أمتع، وذلك من خلال إثراء المحتوى التقني باللغة العربية وتشجيع المبرمجين على القراءة بلغتهم الأم والتفكير أيضًا بها.
لذلك اتحنا الفرصة أمام الجميع للمساهمة ومساعدتنا في نشر واثراء المحتوى التقني باللغة العربية, من خلال كتابة المقالات التقنية في مختلف مجالات هندسة البرمجيات.
وجب التنويه أنه لن يتم نشر كافة الأعمال التي تصل إلينا، وإنما سيتم الانتقاء منها ما يحقق هدفنا بإثراء المحتوى التقني العربي، ولذلك قد تُطلب بعض التعديلات من الكاتب قبل النشر.
لمعرفة المزيد بخصوص :
💬 المعايير العامة لكتابة ونشر المقالات
⚡️ كيفية الإرسال
🔥 التزامات اقرأ-تِك تجاه الكتاب
يمكنكم قراءة كافة التفاصيل من هنا 👇