بناء البرمجيات - الأسبوع 1
9 دقائق قراءة
شرائح الدرس
1 / 16
جامعة المنصورة
- الفصل الدراسي الأول - 2020-2021
- قسم نظم المعلومات
- كلية الحاسبات والمعلومات
- [CS ---] بناء البرمجيات
- الفرقة: 4
- المعمل: 1
- د. عمر الزكي
- عبد الرحمن جمال
جدول المحاضرة
- أهداف بناء البرمجيات.
- الأدوات.
- لماذا نستخدم جافا (Java) في هذا المقرر
- فهم بيئة عمل جافا.
- أنواع الذاكرة (المكدس Stack، الكومة Heap)
- النوع القيمي (Value type) مقابل النوع المرجعي (Reference type)
- الفحص الساكن (Static Checking)
- التنميط الساكن (Static typing)
- 2
أهداف بناء البرمجيات
- الأمان من الأخطاء. الصحة (السلوك الصحيح الآن) والدفاعية (السلوك
- الصحيح في المستقبل).
- سهولة الفهم. يجب أن يتواصل الكود مع المبرمجين المستقبليين الذين يحتاجون إلى
- فهمه وإجراء تعديلات عليه (إصلاح الأخطاء أو إضافة ميزات جديدة). قد يكون
- ذلك المبرمج المستقبلي أنت نفسك، بعد أشهر أو سنوات من الآن. ستُفاجأ بمقدار
- ما تنساه إن لم تدوّنه، وبمدى استفادة نفسك المستقبلية من وجود تصميم جيد.
- الجاهزية للتغيير. البرمجيات تتغيّر دائمًا. بعض التصاميم تجعل إجراء
- التغييرات سهلاً؛ بينما تتطلب تصاميم أخرى التخلص من كمّ كبير من الكود وإعادة كتابته
- 3
يجب كتابة البرامج مع مراعاة هدفين:
- التواصل مع الحاسوب. أولاً بإقناع المترجم (Compiler) بأن برنامجك منطقي - صحيح نحويًا (Syntactically) وصحيح من ناحية الأنواع (Type-correct). ثم ضبط المنطق ليعطي النتائج الصحيحة أثناء التشغيل.
- التواصل مع أشخاص آخرين. جعل البرنامج سهل الفهم، بحيث عندما يحتاج شخص ما لإصلاحه أو تحسينه أو تكييفه مستقبلاً، يستطيع فعل ذلك بسهولة.
- 4
الأدوات
- سنستخدم جافا كلغة برمجة، لذا نحتاج إلى إعداد بيئة العمل.
- نستخدم Eclipse كبيئة تطوير متكاملة (IDE)، أو يمكنك استخدام أي بيئة تطوير أخرى تفضلها.
- 5
لماذا نستخدم جافا في هذا المقرر
- الأمان
-
- تمتلك جافا فحصًا ساكنًا (Static checking)، ويشمل بشكل أساسي فحص الأنواع (Type checking)، إضافة لأنواع أخرى من الفحوص الساكنة، مثل التأكد من أن الكود يُعيد قيمًا من الدوال (Methods) المصرَّح بأنها تُعيد قيمًا.
-
- لغة جيدة لتعلّم ممارسات هندسة البرمجيات الجيدة.
-
- يسهُل عليك فهم ما تحتاج إلى فعله عندما تتعلّم كيفية القيام به في لغة آمنة ذات فحص ساكن.
- الانتشار الواسع
-
- تُستخدم جافا على نطاق واسع في البحث العلمي والتعليم والصناعة. تعمل جافا على منصات عديدة، وليس فقط على ويندوز/ماك/لينكس
-
- تمتلك جافا مجموعة واسعة من المكتبات المفيدة والمثيرة للاهتمام (سواء مكتبتها المدمجة الضخمة أو مكتبات أخرى متاحة على الإنترنت)
- أدوات تطوير مجانية ممتازة (بيئات تطوير متكاملة مثل Eclipse، والمحررات، والمترجمات، وأطر الاختبار، ومحلّلات الأداء (Profilers)، وأدوات تغطية الكود، وأدوات فحص أسلوب الكتابة)
- 6
فهم بيئة عمل جافا
- تم تطوير جافا (JAVA) بواسطة شركة Sun Microsystems عام 1991، واستحوذت عليها لاحقًا شركة Oracle. طوّرها جيمس جوسلينج (James Gosling) وباتريك نوتون (Patrick Naughton). وهي لغة برمجة بسيطة. كتابة البرنامج وترجمته (Compiling) وتصحيح أخطائه (Debugging) أمر سهل في جافا.
- قبل أن نبدأ تعلّم جافا، لنتعرّف على المصطلحات الشائعة في جافا
- الآلة الافتراضية لجافا (JVM - Java Virtual Machine)
- حزمة تطوير جافا (JDK - Java Development Kit)
- بيئة تشغيل جافا (JRE - Java Runtime Environment)
- 7
فهم بيئة عمل جافا
-
- كتابة البرنامج
-
- تتم ترجمة (Compilation) البرنامج بواسطة مترجم javac، وهو المترجم الأساسي لجافا المُضمَّن في حزمة تطوير جافا (JDK). يأخذ برنامج جافا كمدخل، ويولّد كود جافا الوسيط (Bytecode) كمخرج.
-
- في المرحلة الثالثة، تقوم الآلة الافتراضية لجافا (JVM) بتنفيذ الكود الوسيط الذي ولّده المترجم. تُسمّى هذه مرحلة تشغيل البرنامج.
- الوظيفة الأساسية لـJVM هي تنفيذ الكود الوسيط الذي ينتجه المترجم. لكل نظام تشغيل آلة افتراضية (JVM) مختلفة، إلا أن الناتج الذي تنتجه بعد تنفيذ الكود الوسيط يكون متطابقًا عبر جميع أنظمة التشغيل. لهذا السبب نسمّي جافا لغة مستقلة عن المنصة (Platform independent).
- 8
فهم بيئة عمل جافا
- الكود الوسيط (Bytecode)
- يقوم مترجم javac الخاص بـJDK بترجمة الكود المصدري لجافا إلى كود وسيط (Bytecode) بحيث يمكن تنفيذه بواسطة JVM. يحفظ المترجم الكود الوسيط في ملف بامتداد .class.
- حزمة تطوير جافا (JDK)
- هذه حزمة تطوير جافا الكاملة التي تتضمن بيئة تشغيل جافا (JRE)، والمترجمات، وأدوات متنوعة مثل JavaDoc، ومصحّح أخطاء جافا (Debugger)، وغيرها.
- لكي تُنشئ برنامج جافا وتترجمه وتشغّله، تحتاج إلى تثبيت JDK على جهازك.
- 9
فهم بيئة عمل جافا
- بيئة تشغيل جافا (JRE)
- الـJRE جزء من JDK، بمعنى أن JDK يتضمن JRE. عندما يكون JRE مثبتًا على جهازك، يمكنك تشغيل برنامج جافا، لكن لن تستطيع ترجمته. يتضمن JRE الآلة الافتراضية JVM، ودعم إضافات المتصفح (Plugins) والتطبيقات المصغّرة (Applets). عندما تحتاج فقط إلى تشغيل برنامج جافا على جهازك، فأنت تحتاج إلى JRE فقط.
- 10
لنلخّص
- الآلة الافتراضية لجافا (JVM) هي آلة افتراضية تعمل على الجهاز الفعلي (حاسوبك) وتنفّذ الكود الوسيط لجافا. لا تفهم JVM الكود المصدري لجافا مباشرة، لذلك نحتاج إلى مترجم javac الذي يترجم ملفات *.java للحصول على ملفات *.class التي تحتوي على الأكواد الوسيطة التي تفهمها JVM. تجعل JVM جافا لغة قابلة للنقل (اكتب مرة واحدة، شغّل في أي مكان). لكل نظام تشغيل آلة افتراضية JVM مختلفة، إلا أن الناتج الذي تنتجه بعد تنفيذ الكود الوسيط يكون متطابقًا عبر جميع أنظمة التشغيل
- 11
الفحص الساكن (Static Checking)
- الأنواع (Types)
- الفحص الساكن مقابل الفحص الديناميكي
- المصفوفات (Arrays) والمجموعات (Collections)
- التكرار (Iterating)
- الدوال (Methods)
- تغيير محتوى المتغيرات (Mutating) مقابل إعادة إسناد المتغيرات (Reassigning)
- 12
ماذا يحدث فعليًا عند تعريف متغير من نوع بدائي (Primitive)
- 13
أنواع الذاكرة (المكدس Stack، الكومة Heap)
- 14
متتالية Hailstone
- 15
جافا مقابل بايثون
- 16
الأنواع (Types)
- 17
- أهم فرق دلالي بين كود بايثون وكود جافا أعلاه هو تعريف المتغير n، الذي يحدّد نوعه: int.
- int (للأعداد الصحيحة مثل 5 و-200، لكن ضمن نطاق ± 2^31 تقريبًا، أي حوالي ± 2 مليار)
- long (للأعداد الصحيحة الأكبر حتى ± 2^63)
- boolean (لقيمتَي true أو false)
- double (للأعداد ذات الفاصلة العائمة، التي تمثّل مجموعة جزئية من الأعداد الحقيقية)
- char (للحروف المفردة مثل 'A' و'$')
- تمتلك جافا أيضًا أنواعًا كائنية (Object types)، على سبيل المثال:
- String تمثّل سلسلة من المحارف (Characters)، مثل سلسلة النص في بايثون.
- وفقًا لاصطلاح جافا، تُكتب الأنواع البدائية (Primitive types) بأحرف صغيرة، بينما تبدأ الأنواع الكائنية بحرف كبير.
التنميط الساكن (STATIC TYPING)
- جافا لغة ذات تنميط ساكن (Statically-typed). أنواع جميع المتغيرات معروفة وقت الترجمة (قبل تشغيل البرنامج)، وبالتالي يستطيع المترجم استنتاج أنواع جميع التعبيرات (Expressions) أيضًا. فإذا كان a وb معرَّفَين كـint، يستنتج المترجم أن a+b هو أيضًا int. تقوم بيئة Eclipse بهذا أثناء كتابتك للكود بالفعل، لذا تكتشف الكثير من الأخطاء وأنت لا تزال تكتب.
- في اللغات ذات التنميط الديناميكي (Dynamically-typed) مثل بايثون، يُؤجَّل هذا النوع من الفحص إلى وقت التشغيل (أثناء تشغيل البرنامج).
- .
- 18
الفحص الساكن، والفحص الديناميكي، وعدم الفحص
- من المفيد التفكير في ثلاثة أنواع من الفحص التلقائي التي يمكن أن توفرها اللغة:
- الفحص الساكن (Static checking): يُكتشف الخطأ تلقائيًا قبل تشغيل البرنامج حتى.
- الفحص الديناميكي (Dynamic checking): يُكتشف الخطأ تلقائيًا أثناء تنفيذ الكود.
- عدم الفحص (No checking): لا تساعدك اللغة في اكتشاف الخطأ إطلاقًا. عليك مراقبته بنفسك، وإلا ستحصل على إجابات خاطئة.
- 19
الفحص الساكن
- الأخطاء النحوية (Syntax errors)، مثل علامات ترقيم زائدة أو كلمات غير صحيحة. حتى اللغات ذات التنميط الديناميكي مثل بايثون تقوم
- بهذا النوع من الفحص الساكن. فإذا كان لديك خطأ في المسافات البادئة (Indentation) في برنامج بايثون الخاص بك، ستكتشفه قبل
- أن يبدأ البرنامج بالتشغيل.
- أسماء خاطئة، مثل Math.sine(2). (الاسم الصحيح هو sin.)
- عدد خاطئ من المعاملات (Arguments)، مثل Math.sin(30, 20).
- أنواع معاملات خاطئة، مثل Math.sin("30").
- أنواع إرجاع خاطئة، مثل return "30"; من دالة مصرَّح بأنها تُعيد int.
- 20
الفحص الديناميكي
- قيم معاملات غير مسموحة. على سبيل المثال، التعبير الصحيح x/y يكون خاطئًا فقط عندما تكون y فعليًا
- صفرًا؛ وإلا فهو يعمل بشكل صحيح. لذا في هذا التعبير، القسمة على صفر ليست خطأً ساكنًا، بل خطأً
- ديناميكيًا. الفهارس (Indexes) خارج النطاق، مثل استخدام فهرس سالب أو كبير جدًا على سلسلة نصية.
- 21
مفاجأة: الأنواع البدائية ليست أعدادًا حقيقية بالمعنى الدقيق
- القسمة الصحيحة (Integer division). العملية 5/2 لا تُعيد كسرًا، بل تُعيد عددًا صحيحًا مقطوعًا. لذا هذا مثال
- على حالة كنا نأمل أن تكون خطأ ديناميكيًا (لأن الكسر لا يمكن تمثيله كـ
- عدد صحيح)، لكنها غالبًا ما تُنتج إجابة خاطئة بدلاً من ذلك.
- فيضان الأعداد الصحيحة (Integer overflow). نوعا int وlong هما في الحقيقة مجموعتان محدودتان من الأعداد الصحيحة، ولهما قيم
- عظمى وصغرى. ماذا يحدث عند إجراء عملية حسابية تكون نتيجتها موجبة جدًا أو سالبة جدًا بحيث لا تتّسع
- ضمن ذلك النطاق المحدود؟ تفيض العملية الحسابية بصمت (تلتف حول نفسها - Wraps around)، وتُعيد عددًا صحيحًا من
- مكان ما ضمن النطاق المسموح لكنه ليس الإجابة الصحيحة.
- قيم خاصة في أنواع الفاصلة العائمة. تمتلك الأنواع ذات الفاصلة العائمة مثل double عدة قيم خاصة
- ليست أعدادًا حقيقية: NaN (اختصار "Not a Number" أي "ليس رقمًا")، وPOSITIVE_INFINITY (اللانهاية الموجبة)، وNEGATIVE_INFINITY (اللانهاية السالبة). لذا عندما تُطبّق عمليات معينة على قيمة من نوع double كنت تتوقع أن تُنتج
- أخطاءً ديناميكية، مثل القسمة على صفر أو أخذ الجذر التربيعي لعدد سالب، ستحصل بدلاً من ذلك على إحدى
- هذه القيم الخاصة. وإذا واصلت الحساب بها، ستنتهي بإجابة نهائية خاطئة.
- 22
الأنواع المُعرَّفة مسبقًا (Pre-defined types)
- 23
(أ) خطأ ساكن (ب) خطأ ديناميكي (ج) لا يوجد خطأ، لكن الإجابة خاطئة
- 24
المصفوفات (ARRAYS) والقوائم (List)
- المصفوفات (Arrays) متتاليات ذات طول ثابت من نوع آخر، أما القائمة (List) فذات طول غير ثابت.
- 25
الدوال (Methods)
- 26
تغيير محتوى القيم مقابل إعادة إسناد المتغيرات
- عندما تُسند قيمة إلى محتوى قيمة قابلة للتغيير (Mutable) - مثل مصفوفة أو قائمة - فأنت تُغيّر المراجع (References) داخل تلك القيمة.
- التغيير شرّ لا بدّ منه. يتجنّب المبرمجون الجيدون الأشياء القابلة للتغيير، لأنها قد تتغيّر بشكل غير متوقع.
- الثبات (Immutability - الحصانة من التغيير) مبدأ تصميمي رئيسي في هذا المقرر. الأنواع الثابتة (Immutable types) هي أنواع لا يمكن لقيمها أن تتغيّر أبدًا بعد إنشائها. (على الأقل ليس بطريقة مرئية للعالم الخارجي - هناك بعض الدقائق حول ذلك سنتحدث عنها أكثر في محاضرة مستقبلية عن الثبات.) أيّ من الأنواع التي ناقشناها حتى الآن ثابت، وأيّها قابل للتغيير؟
- تمنحنا جافا أيضًا مراجع ثابتة (Immutable references): متغيرات تُسنَد لها قيمة مرة واحدة ولا يُعاد إسنادها أبدًا. لجعل المرجع ثابتًا، عرّفه باستخدام الكلمة المفتاحية final:
- Final int num;
- 27