لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 10/23/20 في كل الموقع
-
مرحباً، أنا لا أنصحك بتشتيت نفسك في تعلم التقنيات و مُشاهدة الدروس تِباعاً فالأفضل لك التركيز على لغة واحدة حالياً. أيضاً تعلم الدروس فقط بدون جمع و توظيف ما تعلمته في مشاريع حقيقية لن يُفيدك في شيء و سيؤدي بك للوقوع في مُشكلة إسمها المعرفة المُزيفة و دوامة الدروس يعني تدخل دورة تشاهد دروسها ثم تدخل دورة ثانية و هكذا بدون الخروج بمشروع كامل مُنفصل يحوي ما تعلمته، شيء طبيعي أن الطالب أو المُتعلم يستطيع التطبيق وراء المُدرب أو الذي يشرح الدورة لكن أنا أتحدث عن مشروع مُنفصل بينك و بين نفسك هنا يظهر مدى إستوعابك للدروس و طريقة تعاملك مع حل المشكلات التي تواجهك ضِفْ على ذلك كل ما قمت بعمل مشروع ما ستزيد خبرتك و سيتطور مُستواك. ضع لنفسك هدف و احرص على تحقيقه مثلاً ولْنَقُل أنك تريد أن تُصبح مُطور تطبيقات أصيلة للأندرويد بالتالي: عليك دراسة أساسيات لغة جافا و تطبيق بعض المشاريع لترسيخ هذه المفاهيم ثم تنتقل إلى فهم مبادئ البرمجة الكائنية و بعدها تنتقل إلى دراسة الأندرويد و تبني تطبيقات فعلية على منصة أندرويد و اهتم بكل ما يخص برمجة الأندرويد من تقنيات و أساليب لأن هذا سيجعلك مُتميز في مجالك و يخدم هدفك الذي وضعته. لا تتعلم كل شيء و لا تتعلم بشكل همجي و إنما ضع خطة و هدف لنفسك، إعرف كل شيء عن شيء و شيئ عن كل شيئ . لا تُضيع وقتك في الإنتقال من تقنية إلى أخرى و من لغة إلى أخرى و إعرف أن التخصص ضرورة حتمية لابد منها و بعد إكتسابك للخبرة اللازمة في مجالك و قيامك بمشاريع إحترافية يُمكنك حينها تعلم تقنية أو لغة جديدة أو الدخول إلى مجال آخر و هذا الشيء أنت من يُقرره بالأخير. بالتوفيق.2 نقاط
-
الخيط (Thread) هو نوع معين أو خاص من العمليات، حيث ينشئ نظام التشغيل حيز عناوين جديدًا عند إنشاء عملية، ويتضمن هذا الحيز جزء الشيفرة أو نص البرنامج (text segment) والجزء الساكن (static segment) وجزء الكومة (heap)، وينشئ نظام التشغيل أيضًا خيط تنفيذ (thread of execution) جديدًا يتضمن عداد البرنامج (program counter) وحالة عتاد أخرى واستدعاء المكدس. العمليات التي رأيتها لحد الآن هي عمليات ذات خيط وحيد (single-threaded) أي يوجد خيط تنفيذ واحد فقط يعمل في كل حيز عناوين، وستتعرف على العمليات ذات الخيوط المتعددة (multi-threaded)، أي التي تملك خيوطًا متعددة تعمل في نفس حيز العناوين. تتشارك كل الخيوط بنفس جزء الشيفرة ضمن العملية الواحدة أي أنها تشغّل نفس الشيفرة، ولكن تشغّل هذه الخيوط المختلفة أجزاءً مختلفة من تلك الشيفرة، وتتشارك الخيوط ضمن العملية الواحدة بنفس الجزء الساكن (static segment)، لذلك إذا غيّر أحد الخيوط متغيرًا عامًا (global variable) فإن بقية الخيوط ترى هذا التغيير، ويتشاركون أيضًا بالكومة (heap) لذلك تستطيع الخيوط التشارك بقطع الذاكرة المخصصة ديناميكيًا (dynamically-allocated chunks)، ولكن يكون لكل خيطٍ جزء المكدس الخاص به لذلك تستطيع الخيوط استدعاء دوالٍ دون التداخل مع بعضها البعض، ولا تصل الخيوط عادةً إلى المتغيرات المحلية لخيطٍ آخر، حيث لا تستطيع الوصول إليها في بعض الأحيان. إنشاء الخيوط (Creating threads) الخيوط القياسية الأكثر شيوعًا والمستخدمة مع C هي خيوط POSIX أو اختصارًا Pthreads. تعرّف خيوط POSIX القياسية نموذج خيط (thread model) وواجهةًَ (interface) لإنشاء الخيوط والتحكم بها، وتوفّر معظم نسخ UNIX تطبيقًا ل Pthreads. يشبه استخدامُ Pthreads استخدامَ معظم مكتبات لغة C حيث: تضمّن ملفات الترويسات (headers files) في بداية برنامجك. تكتب الشيفرة التي تستدعي دوالًا معرّفة باستخدام Pthreads. تربط (link) البرنامج عند تصريفه (compile) مع مكتبة Pthread. يضمِّن البرنامج ملفات الترويسات التالية: #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> أول اثنين من ملفات الترويسات السابقة هما تضمين لمكتبات قياسية، أما ملف الترويسات الثالث فيُستخدم من أجل Pthreads، ويُستخدم ملف الترويسات الرابع من أجل متغيرات تقييد الوصول (semaphores). يمكنك استخدام الخيار -l في سطر الأوامر لتصريف البرنامج مع مكتبة Pthread باستخدام الأداة gcc كما يلي: gcc -g -O2 -o array array.c -lpthread يصرّف الأمر السابق ملفًا مصدريًا يدعى array.c مع معلومات تنقيح الأخطاء (debugging info) والتحسين (optimization) ويربطه مع مكتبة Pthread ثم يولّد ملفًا تنفيذيًا يدعى array. إنشاء الخيوط (Creating threads) تدعى دالة Pthread التي تنشئ خيوطًا pthread_create، وتُظهر الدالة التالية كيفية استخدامها: pthread_t make_thread(void *(*entry)(void *), Shared *shared) { int n; pthread_t thread; n = pthread_create(&thread, NULL, entry, (void *)shared); if (n != 0) { perror("pthread_create failed"); exit(-1); } return thread; } الدالة make_thread هي دالة مغلّفة (wrapper) وكُتبت لجعل الدالة pthread_create سهلة الاستخدام ولتوفير التحقق من الأخطاء (error-checking). نوع القيمة المعادة من الدالة pthread_create هو pthread_t والذي يمكنك التفكير به كمعرّف (id) أو مِقبض (handle) للخيط الجديد. إذا نجح تنفيذ الدالة pthread_create فستعيد القيمة 0 وتعيد الدالة make_thread مقبض الخيط الجديد، وإذا ظهر خطأ فتعيد الدالة pthread_create شيفرة الخطأ وتطبع الدالة make_thread رسالة خطأ وتنتهي. Shared المعامل الثاني للدالة make_thread هو عبارة عن بنية (structure) عُرِّفت لتتضمن القيم المشتركة بين الخيوط، حيث يمكنك تعريف نوع جديد من خلال استخدام عبارة typedef كما يلي: typedef struct { int counter; } Shared; والمتغير المشترك الوحيد في هذه الحالة هو counter، وتخصص الدالة make_shared حيّزًا للبنية Shared وتهيئ محتوياتها كما يلي: Shared *make_shared() { Shared *shared = check_malloc(sizeof(Shared)); shared->counter = 0; return shared; } لديك الآن بنية بيانات مشتركة وإذا عدتَ إلى الدالة make_thread وتحديدًا المعامل الأول الذي هو عبارة عن مؤشر (pointer) إلى دالة، وتأخذ هذه الدالة مؤشر void وتعيد مؤشر void أيضًا. إذا أصبح نظرك مشوشًا بسبب صيغة تصريح هذا النوع فلست الوحيد في ذلك، على كل حال إن الهدف الأساسي من هذا المعامل هو أن يحدد للدالة مكان بدء تنفيذ الخيط الجديد، وتدعى هذه الدالة entry: void *entry(void *arg) { Shared *shared = (Shared *)arg; child_code(shared); pthread_exit(NULL); } يجب أن يُصرَّح عن معامل الدالة entry كمؤشر void، ولكنه في هذا البرنامج مؤشرٌ إلى بنية Shared لذلك يمكن تبديل نوعه (typecast) ثم تمريره إلى الدالة child_code التي تقوم بالعمل الحقيقي، حيث تطبع الدالة child_code قيمة المتغير المشترك counter ثم تزيد قيمته كما يلي: void child_code(Shared *shared) { printf("counter = %d\n", shared->counter); shared->counter++; } تستدعي الدالةُ entry الدالةََ pthread_exit بعد أن تنتهي الدالة child code وتعيد قيمةً، حيث يمكن أن تُستخدم الدالة pthread_exit لتمرير قيمة إلى الخيط الذي يُضم (join) مع الخيط الحالي، وبالتالي في هذه الحالة لا يبقى شيء للخيط الابن لعمله فتُمرَّر القيمة الخالية NULL، وأخيرًا تنشئ الشيفرة التالية الخيوط الأبناء (child threads) كما يلي: int i; pthread_t child[NUM_CHILDREN]; Shared *shared = make_shared(1000000); for (i = 0; i < NUM_CHILDREN; i++) { child[i] = make_thread(entry, shared); } NUM_CHILDREN هو ثابت وقت التصريف (compile-time constant) الذي يحدد عدد الخيوط الأبناء، و child هي مصفوفة مقابض الخيوط (thread handles). ضم الخيوط (Joining threads) إذا أراد خيطٌ انتظار خيطٍ آخر ليكتمل فإنه يستدعي الدالة pthread_join، وتجد فيما يلي الدالة المغلّفة للدالة pthread_join: void join_thread(pthread_t thread) { int ret = pthread_join(thread, NULL); if (ret == -1) { perror("pthread_join failed"); exit(-1); } } معامل الدالة المغلّفة هو مقبض الخيط الذي تنتظره ليكتمل، وعمل الدالة المغلّفة هو فقط استدعاء الدالة pthread_join والتحقق من النتيجة. يستطيع أي خيط أن يضم أي خيطٍ آخر، ولكن في النماذج الأكثر شيوعًا ينشئ الخيط الأب (parent thread) كل الخيوط الأبناء ويضمها (join). تجد فيما يلي الشيفرة التي تنتظر الخيوط الأبناء بها: for (i = 0; i < NUM_CHILDREN; i++) { join_thread(child[i]); } تنتظر هذه الحلقات أحد الخيوط الأبناء في كل مرة وذلك حسب ترتيب إنشائها، ولا يوجد ضمان أن تكتمل الخيوط الأبناء في هذا الترتيب ولكن تعمل هذه الحلقة بصورة صحيحة حتى في حال لم يحدث ذلك، فإذا تأخر أحد الخيوط الأبناء فيجب أن تنتظر الحلقة، ويمكن أن تكتمل الخيوط الأبناء الأخرى خلال وقت الانتظار هذا، حيث لا يمكن أن تنتهي هذه الحلقة إلا في حال اكتمال جميع الخيوط الأبناء. يمكنك الاطلاع على المثال ضمن counter/counter.c ثم تصريفه وتشغيله كما يلي: $ make counter gcc -Wall counter.c -o counter -lpthread $ ./counter فعند تشغيله مع 5 خيوط أبناء سينتج الخرج التالي: counter = 0 counter = 0 counter = 1 counter = 0 counter = 3 وسينتج خرج آخر عندما تشغله على حاسوبك، وإذا شغلته مرة أخرى سينتج خرج مختلف أيضًا، فماذا يحدث؟ الأخطاء المتزامنة (Synchronization errors) مشكلة البرنامج السابق أن الخيوط الأبناء تستطيع الوصول إلى المتغير المشترك counter بدون تزامن، لذلك تستطيع عدة خيوط قراءة نفس قيمة المتغير counter قبل أن يزيد أي خيطٍ قيمته. يمكن أن تشرح سلسلة الأحداث التالية الخرج الذي حصلت عليه سابقًا: Child A reads 0 Child B reads 0 Child C reads 0 Child A prints 0 Child B prints 0 Child A sets counter=1 Child D reads 1 Child D prints 1 Child C prints 0 Child A sets counter=1 Child B sets counter=2 Child C sets counter=3 Child E reads 3 Child E prints 3 Child D sets counter=4 Child E sets counter=5 يمكن أن تُقاطَع الخيوط في أماكن مختلفة في كل مرة تشغّل فيها البرنامج، أو قد يختار المجدول خيوطًا مختلفة ليشغّلها، لذلك ستكون سلسلة الأحداث والنتائج مختلفة. افترض أنك تريد فرض بعض الترتيب، أي مثلًا تريد أن يقرأ كل خيط قيمةً مختلفة للمتغير counter ثم يزيدها، وبالتالي تُظهر قيمة المتغير counter عدد الخيوط التي نفّذت الدالة child_code، ويمكنك استخدام كائن المزامنة (mutex) لتطبيق ذلك، حيث كائن المزامنة (mutex) هو عبارة عن كائن (object) يضمن حدوث إقصاء متبادل (mutual exclusion) لكتلة من الشيفرة، أي ينفّذ خيطٌ واحد فقط كتلة الشيفرة في نفس الوقت. كتبتُ، يقول الكاتب، نموذجًا يدعى mutex.c يوفر كائنات المزامنة، ستجد فيما يلي نسخةً من الدالة child_code التي تستخدم كائن المزامنة لتأمين تزامن الخيوط: void child_code(Shared *shared) { mutex_lock(shared->mutex); printf("counter = %d\n", shared->counter); shared->counter++; mutex_unlock(shared->mutex); } حيث يجب على كل خيط أن يقفل (lock) كائن المزامنة قبل أن يصل أي خيطٍ آخر إلى المتغير المشترك counter، وهذا يؤدي إلى حظر كل الخيوط الأخرى من الوصول إلى هذا المتغير. افترض أن الخيط A قفل كائن المزامنة وهو في منتصف الدالة child_code، فإذا وصل الخيط B ونفّذ الدالة mutex_lock يتوقف تنفيذ الخيط B. ينفّذ الخيط A الدالة mutex_unlock عندما ينتهي، وبالتالي يسمح للخيط B متابعة تنفيذه، أي تنفّذ الخيوط الدالة child_code على التوالي بحيث ينفّذها خيطٌ واحدٌ فقط في نفس الوقت، وبالتالي لا يتعارض أي خيط مع الخيوط الأخرى، وإذا شغّلت الشيفرة مع 5 خيوط أبناء سينتج: counter = 0 counter = 1 counter = 2 counter = 3 counter = 4 وهذا هو المطلوب. يجب إضافة كائن المزامنة Mutex إلى البنية Shared لكي يعمل هذا الحل بالصورة الصحيحة: typedef struct { int counter; Mutex *mutex; } Shared; وتهيئته في الدالة make_shared: Shared *make_shared(int end) { Shared *shared = check_malloc(sizeof(Shared)); shared->counter = 0; shared->mutex = make_mutex(); //-- هذا السطر جديد return shared; } كائن المزامنة (Mutex) تعريفي، يقول الكاتب، ل Mutex هو مغلّف لنوعٍ يدعى pthread_mutex_t وهو معرّفٌ في واجهة برمجة التطبيقات للخيوط POSIX، ولإنشاء كائن مزامنة POSIX يجب تخصيص حيزٍ للنوع pthread_mutex_t ثم استدعاء الدالة pthread_mutex_init. إحدى مشاكل واجهة برمجة التطبيقات هذه أن النوع pthread_mutex_t يتصرف كبنية (structure)، لذلك إذا مررته كوسيط سينشئ نسخةً تجعل كائن المزامنة يتصرف بصورة غير صحيحة، ويمكنك تجنب ذلك من خلال تمرير النوع pthread_mutex_t باستخدام عنوانه. تجعل الشيفرة التي كتبتها، يقول الكاتب، الأمور أسهل من خلال تعريف نوعٍ هو النوع Mutex الذي هو عبارة عن اسم للنوع pthread_mutex_t يمكن قراءته بطريقة أسهل: #include <pthread.h> typedef pthread_mutex_t Mutex; ثم تعريف دالةٍ هي الدالة make_mutex التي تخصص حيّزًا لكائن المزامنة وتهيئته: Mutex *make_mutex() { Mutex *mutex = check_malloc(sizeof(Mutex)); int n = pthread_mutex_init(mutex, NULL); if (n != 0) perror_exit("make_lock failed"); return mutex; } القيمة المعادة هي مؤشر يمكن أن تمرره كوسيط دون أن يسبب نسخًا غير مرغوبة. الدوال التي تستخدم لقفل وفك قفل كائن المزامنة هي دوالٌ مغلّفة بسيطة لدوال POSIX: void mutex_lock(Mutex *mutex) { int n = pthread_mutex_lock(mutex); if (n != 0) perror_exit("lock failed"); } void mutex_unlock(Mutex *mutex) { int n = pthread_mutex_unlock(mutex); if (n != 0) perror_exit("unlock failed"); } ترجمة -وبتصرّف- للفصل Threads من كتاب Think OS A Brief Introduction to Operating Systems1 نقطة
-
البرمجة يا صديقي العزيز ليست كتابة كود فقط - الوعي الحقيقي لكيفية عمل الجهاز وبرمجته بالاضافة الي كيفية عمل برمجة OOP وفهمها الحقيقي بالكامل هو الذي سيساعدك فيما بعد في تعلم ايا لغة برمجة بسرعة كبيرة جميع اللغات تعتمد الأن في بناءها علي مفهوم OOP - Data Structue وكل الأوامر المستخدمة والطرق مبينة عليهم حرفيا انصحك بشدة في تعلم هذه المفاهيم وتجربتها بما فيه الكفاية في الجافا باعتبارها لغة رائدة في المجال وتطبق Strict Typing وهو أحد الأمور المهمة المفقودة في لغة البايثون ولغة الجافا سكربت . باﻹضافة الي تعلم كيفية تعامل الذاكرة الخاصة بالجهاز مع المتغيرات وحفظها وحذفها وربما من الجيد القاء نظرة سريعة على لغة C مثلا مثل هذه الأمور تزيد من وعيك في كيفية عمل الجهاز والذاكرة والتي فيما بعد ستسرع جداً من تعلمك أيا لغة أخرى ستجد نفسك فيما بعد تتعلم أيا لغة برمجة في ظرف اسبوع لا أكثر لن تجد اي صعوبة الا في بعض الامور الخاصة بهذه اللغة وبعض الطرق Methods الجاهزة التي تطبقها وأريد ان أزيد ان اللغات اليوم تتجه الى التخصص بمعنى أن البايثون لغة سهلة تستطيع تعلم كيفية كتابة الأوامر فيها أخي العزيز في أيام فقط ولكن بعد ذلك ستكتشف أن قوة البايثون تعتمد علي المكتبات الجاهزة والتي تحتاج الي دراسة أيضا لمعرفة كيف تعمل وما هي Methods التي توفرها ومن أكثر الأمثلة انتشارا هذه الأيام الذكاء الصناعي وتعلم الآلة والتي حسب رائي الشخصي تحتاج الى معرفة كبيرة جدا في الرياضيات والإحصاء أيضا أعتقد ان من الأفضل بدلاً من أن تتعلم بشكل يومي كيفية عمل البايثون والذي لا يختلف كثيراً عن عمل الجافا أن تتعلم قليلاً من الإحصاء والرياضيات بشكل معمق أكثر أو أي شئ أخر تخصصي والذي سيساعدك جدا في البايثون1 نقطة
-
تطوير واجهات المستخدم لا يقتصر على بناء واجهات مواقع الويب فقط بل هي تشمل واجهات تطبيقات الجوال و تطبيقات سطح المكتب كذلك أو حتى ال terminal . و لكلٍ منهم التقنيات الخاصة به. و لكن إذا كنت مطور JavaScript و تعلمت مكتبة React فإنه يمكنك بناء واجهات المستخدم لتطبيقات الجوال و تطبيقات سطح المكتب باستخدام نفس الأساسيات التي تستخدمها لتطوير واجهات الويب باستخدام مكتبات مثل react native لتطبيقات الجوال و react desktop لتطبيقات سطح المكتب "و لكن مكتبة electron أفضل" و غيرها.1 نقطة
-
إذا كان سؤالك عن تصميم واجهة المستخدم ui/ux وهي مرحلة قبل تنفيذ الأكواد وبدء العمل على تطوير الموقع أو التطبيق . فجميع الأعمال تتطلب تصميم تجربة المستخدم ui/ux لا ينحصر فقط في الويب أيضاً الأبليشكن موبايل وبرامج desktop يتطلبوا أن يكن في مصمم تجربة مستخدم يعمل قبل تنفيذ الأكواد على التصميم ينشئ تصميم x d او psd أو أياً كان البرنامج المستخدم . وإذا كان سؤالك المقصود بي مطور front-end ينحصر فقط في مجال الويب فسوف أقول لك أيضاً لا ينحصر فيمكن لمبرمج Front-end أن يتعلم بعض الإضافات والمكتبات مثل React Native ويصبح يمكنه أن يطور تطبيقات موبايل .1 نقطة
-
مرحبا صديقي, يمكنك تعلم ماتشاء من لغات البرمجة لكنه يعتبر إضاعة للوقت بسبب الإنغماس في تفاصيل صغيرة التي تختلف بها لغات البرمجة عن بعضها .. فجميع اللغات تشترك في فكرة if - else - for - while - function - class أي أنها مفاهيم يقوم مطورو لغة البرمجة بكتابة Syntax محدد ليتسنى للمطورين استخدامها و بناء البرامج بها أي أن جميع لغات البرمجة متشابهة إنما اختيارك للغة التي ستحترفها يعتمد على سوق العمل و الفترة الزمنية التي ستكون أنت شخصيا جاهزا لدخول سوق العمل فيها لأنه لا نستطيع معرفة ماهي لغة البرمجة التي ستسيطر أو توفر فرص عمل أكثر بعد سنتين من الآن .. بعد تعاملك مع مفهوم OOP البرمجة كائنية التوجه أنصحك بالانتقال للغة جافا سكربت JavaScript لأنها مستخدمة في مختلف بيئات التطوير من الويب لتطبيقات الهواتف الى السيرفرات .. و تعلم تصميم الويب وهو الأسهل بالتوفيق1 نقطة
-
لا مشكلة في ذلك فبالجامعة درست أكثر من 3 لغات بتوازٍ وهي C++ و PHP و JS ولغات أخرى في أن واحد (لكن الحمد لله كنت مثلك وبدأت التعلم في سنك كنت دارس لهذه اللغات قبل إلتحاقي بالجامعة ولم أجد مشكلة في تعلمهم محددا بتوازٍ عكس باقي الطلبة). الحمد لله أنت الأن أنت فوق المتوسط بلغة الجافا كما قلت إذن يمكنك أن تبدأ في تعلم البايثون وبالضبط لغة البايثون لأنها حقا لغة جد جد سهلة ورائعة أكثر من ما تتصور وفي الحقيقة تخليت عن لغتي التي كنت أحب يوما ألا وهي الجافا مقابل البايثون والأن أي شيئ أريده تنفيذه أبرمجه بالبايثون, تعلمتها أيضا من قناة الأستاذ محمد عيسى من هنا بسنة 2015 بالإضافة للموقع الرسمي لها وبعض المصادر الأخرى ك tutorialspoint, لكن في الوقت الحالي يوجد شرح جد محترف لها مقدم من طرف الأستاذ أسامة الزيرو من هنا. أنصحك وبشدة أن تكمل مسارك في البايثون فهي لغة المستقبل وفي نفس الوقت أتمم دورة جافا متقدم حتى تكون لك الخبرة في كلا اللغتين وإشتغل بالإثنان بينما الإحتراف أتركه مع البايثون.1 نقطة
-
لا تٌشتت نفسك كثيرًا. التركيز في أمر واحد أفضل. من الأفضل إكمال دراسة جافا الآن و بعد أن تصل لما تريد يمكنك أن تبدأ في تعلم بايثون بسهولة كبيرة. لاحظ أن كلًّا من اللغتين تعتمدان على البرمجة كائنية التوجه OOP أي أنهما متشابهتان في المبادئ و لكن يختلفان في طريقة الكتابة فقط. كما أن التركيز في لغة واحدة سيجعلك تصل لنتائج أسرع بإذن الله. أما تعلُّم اللغتين في نفس الوقت سيأتي بنتيجة عكسية و بعد وقت سسترك كلًا منهما. أيضًا لا داعي للعجلة كثيرًا فسنُّك مازال صغيرًا و أمامك الكثير من الوقت لتتعلم. بالتوفيق.1 نقطة
-
من الأفضل في أي مجال تريد النجاح فيه، أن تركز فيه ولا تتشتت أو تتردد في متابعته. و نحن نتحدث عن لغة برمجة فمن الأفضل عدم اللجوء للغة أخرى و أنت لم تنهي بعد لغة معينة، عليك الإستمرار بالجافا و التطبيق العملي و تحديد ما تود تطويره بهذه اللغة، تطوير تطبيقات الموبايل مثلًا سيكون خيار جيد بالنسبة لك. ومن ناحية الخبرة تكون قد أخذت الخبرة الكافية و الإحتراف في لغة الجافا مما قد يؤهلك للعمل، ولكن حين تشتت نفسك ستكون النتائج غير مرضية.1 نقطة
-
1 نقطة