فيما يلي قائمة بممارسات ترميز 10 جافا التي تكون أكثر دقة من قواعد Java الفعالة من Josh Bloch. مقارنةً بقائمة Josh Bloch التي يسهل التعلم وتركز على المواقف اليومية ، ستحتوي هذه القائمة على مواقف تتضمن أشياء غير مألوفة في تصميم API/SPI ، والتي قد يكون لها تأثير كبير.
لقد واجهت هذه أثناء الكتابة والحفاظ على JOOQ (SQL على غرار DSL الداخلي في Java). باعتباره DSL داخليًا ، يتحدى JOOQ أن المترجمين والأجريين جافا إلى أقصى حد ، يجمع بين الأدوية الجيلية ، والمعلمات القابلة للتغيير والحمولات الزائدة ، والتي قد لا يوصي Josh Bloch بمثل هذه واجهة برمجة التطبيقات الواسعة.
اسمحوا لي أن أشارككم 10 أفضل الممارسات الدقيقة لترميز جافا:
1. تذكر مدمر C ++
تذكر مدمرة C ++؟ لا تتذكر؟ أنت محظوظ حقًا لأنك لست مضطرًا لتصحيح تسرب الذاكرة بسبب الذاكرة المخصصة بعد عدم إصدار حذف الكائن. بفضل Sun/Oracle لآلية جمع القمامة المنفذة!
ومع ذلك ، يوفر المدمر ميزة مثيرة للاهتمام. إنه يفهم أمر التخصيص العكسي لتحرير الذاكرة. تذكر أن هذا هو الحال في Java ، عندما تقوم بتشغيل بناء جملة Destructor Class:
هناك العديد من حالات الاستخدام الأخرى. فيما يلي مثال ملموس على كيفية تنفيذ بعض مستمعي الأحداث:
Overridepublic void قبل eventContext e) {super.beforeEvent (e) ؛ // Super Code قبل الكود الخاص بي} Overridepublic void afterevent (eventContext e) {// super code بعد رمز super.afterevent (e) ؛} مشكلة تناول الطعام في الفيلسوف الشائنة هي مثال جيد آخر على سبب أهمية ذلك. للحصول على أسئلة حول تناول الطعام فيلسوف ، يرجى التحقق من الرابط:
http://adit.io/posts/2013-05-11-TH-DINING-PHILOSOPHERS-PROMBLE-WITH-RON-SWANSON.HTML
القاعدة : كلما استخدمت قبل/بعد ، تخصيص/مجاني ، خذ/إرجاع الدلالات لتنفيذ المنطق ، فكر في الأداء بعد/مجانية/عمليات إرجاع بترتيب عكسي.
تزويد العملاء بطرق SPI التي تجعل من السهل عليهم ضخ السلوك المخصص في مكتبتك/الكود. احذر من أن أحكام SPI Evolution قد تربكك ، مما يجعلك تعتقد أنك (لا) تنوي الحاجة إلى معلمات إضافية. بالطبع ، لا ينبغي إضافة الوظائف في وقت مبكر جدًا. ولكن بمجرد نشر SPI الخاص بك ، بمجرد أن تقرر اتباع الإصدار الدلالي ، ستندم حقًا على إضافة معلمة واحدة غبية إلى SPI عندما تدرك أنه في بعض الحالات قد تحتاج إلى معلمة أخرى:
واجهة eventListener {// رسالة void سيئة (رسالة السلسلة) ؛}ماذا لو كنت بحاجة إلى معرف الرسالة ومصدر الرسائل؟ سوف يمنعك تطور API من إضافة معلمات إلى الأنواع المذكورة أعلاه. بالطبع ، مع Java 8 ، يمكنك إضافة طريقة مدافع "تدافع" قرارات التصميم السيئة في الأيام الأولى:
interface eventListener {// bad default void message (string message) {message (message ، null ، null) ؛ } // أحسن؟ رسالة باطلة (رسالة سلسلة ، معرف عدد صحيح ، مصدر الرسائل) ؛} لاحظ أنه لسوء الحظ ، لا يمكن لطريقة Defender استخدام المعدل النهائي.
ولكن سيكون من الأفضل استخدام كائنات السياق (أو كائنات المعلمة) من تلوث SPI باستخدام العديد من الطرق.
واجهة messageContext {string message () ؛ INTEGER ID () ؛ Messagesource Source () ؛} واجهة EventListener {// Awesome! رسالة باطلة (سياق messageContext) ؛} يمكنك تطوير واجهة برمجة تطبيقات MessageContext بسهولة أكبر من EventListner SPI ، لأن القليل من المستخدمين سيقومون بتنفيذه.
القاعدة : كلما تم تحديد SPI ، فكر في استخدام كائن سياق/معلمة بدلاً من كتابة طرق مع معلمات ثابتة.
ملاحظة : من الجيد أيضًا تبديل النتائج من خلال نوع Messageresult مخصص ، والذي يمكن بناؤه باستخدام واجهة برمجة تطبيقات البناء. هذا سيزيد بشكل كبير من مرونة تطور SPI.
عادة ما يضغط المبرمجون المتألقون فقط على بعض المفاتيح المختصرة لتوليد مئات أو الآلاف من الفصول المجهولة. في معظم الحالات ، لا يؤلمني القيام بذلك طالما يتم اتباع الواجهة ولم يتم انتهاك دورة حياة النوع الفرعي SPI. ولكن لا تستخدم فئات مجهولة المصدر أو المحلية أو الداخلية بشكل متكرر لسبب بسيط - سيحفظون الإشارات إلى الطبقات الخارجية. لأنه بغض النظر عن المكان الذي يذهبون إليه ، يجب أن تتبع الفئات الخارجية. على سبيل المثال ، إذا كانت العملية الخارجية للفئة المحلية غير لائقة ، فسيخضع الرسم البياني للكائن بأكمله لتغييرات دقيقة ، مما قد يتسبب في تسرب الذاكرة.
القاعدة: قبل كتابة فصول مجهولة المصدر أو المحلية أو الداخلية ، يرجى التفكير مرتين حول ما إذا كان يمكنك تحويله إلى فصول ثابتة أو عادية من المستوى الأعلى ، وبالتالي تجنب طرق إعادة كائناتها إلى مجال على المستوى الخارجي.
ملاحظة: استخدم أقواس مجعد مزدوجة لتهيئة الكائنات البسيطة:
new HashMap <string ، string> () {{put ("1" ، "a") ؛ ضع ("2" ، "B") ؛}}تستخدم هذه الطريقة مُهيئ المثيل الموضح في مواصفات JLS §8.6. يبدو جيدًا على السطح ، لكن لا ينصح به في الواقع. لأنه إذا كنت تستخدم كائن HashMap مستقل تمامًا ، فلن يحتفظ المثيل دائمًا بالمراجع إلى الكائنات الخارجية. بالإضافة إلى ذلك ، سيسمح هذا لعملية تحميل الفئة بإدارة المزيد من الفصول.
وتيرة Java8 تقترب. مع Java 8 يجلب تعبيرات Lambda ، سواء أعجبك ذلك أم لا. على الرغم من أن مستخدمي API قد يعجبهم ذلك ، إلا أنه من الأفضل أن تتأكد من إمكانية استخدامه قدر الإمكان. لذلك ، ما لم يتلقى واجهة برمجة التطبيقات الخاصة بك أنواعًا بسيطة "قياسية" ، مثل int و long و string و date ، دع واجهة برمجة التطبيقات الخاصة بك تتلقى SAM قدر الإمكان.
ما هو سام؟ سام هي طريقة مجردة واحدة [النوع]. المعروف أيضًا باسم واجهة الوظائف ، سيتم تعليقه قريبًا على أنه functionalInterface. هذه القاعدة 2 ، eventListener هي في الواقع SAM. أفضل سام لديه معلمة واحدة فقط ، لأن هذا سيؤدي إلى تبسيط كتابة تعبيرات Lambda. تخيل الكتابة
المستمعين. add (c -> system.out.println (
لاستبدال
المستمعين. }}) ؛
تخيل التعامل مع XML في JOOX. JOOX يحتوي على الكثير من سام:
$ (وثيقة) // ابحث عن عناصر مع معرف .find (c -> $ (c) .id ()! = null) // ابحث عن عناصر أطفالهم.
القواعد: كن لطيفًا مع مستخدمي API ، ابدأ في كتابة واجهات SAM/الوظيفة من الآن فصاعدًا .
ملاحظة: هناك العديد من المدونات المثيرة للاهتمام حول تعبيرات Java8 Lambda وتحسين مجموعات API:
لقد كتبت مقالة واحدة أو مقالتين حول Java Nulls ، وشرحت أيضًا إدخال فصول اختيارية جديدة في Java 8. من وجهة نظر أكاديمية أو عملية ، هذه الموضوعات مثيرة للاهتمام للغاية.
على الرغم من أن Null و NullPointerxception لا يزالان عيبًا في Java في هذه المرحلة ، إلا أنه لا يزال بإمكانك تصميم واجهة برمجة تطبيقات لن تواجه أي مشاكل. عند تصميم واجهات برمجة التطبيقات ، يجب عليك تجنب إرجاع الفارغ قدر الإمكان ، لأن المستخدمين قد يتصلون بالطريقة في السلسلة:
initialise (someargument) .calculate (data) .Dispatch () ؛
كما يتضح من الكود أعلاه ، لا يجب أن تعود أي طريقة فارغة. في الواقع ، عادة ما يعتبر استخدام NULL عدم تجانس مماثل. لقد تخلى مكتبة مثل jQuery أو Joox تمامًا عن الكائنات المطلقة.
عادة ما يستخدم فارغ في التهيئة المتأخرة. في كثير من الحالات ، ينبغي أيضًا تجنب التهيئة المتأخرة دون التأثير بشدة على الأداء. في الواقع ، إذا كان بنية البيانات المعنية كبيرة جدًا ، فيجب استخدام تهيئة التأخير بحذر.
القاعدة: يجب أن تتجنب الأساليب عودة فارغة كلما كانت. يستخدم NULL فقط لتمثيل دلالات "غير مهذبة" أو "غير موجودة".
على الرغم من أنه من المقبول إرجاع طريقة ذات قيمة فارغة في بعض الحالات ، إلا أنه لا تُرجع أبدًا مجموعة فارغة أو مجموعة فارغة! يرجى الاطلاع على طريقة java.io.file.list () ، تم تصميمها مثل هذا:
تقوم هذه الطريقة بإرجاع مجموعة من الأوتار لجميع الملفات أو الدلائل في الدليل المحدد. إذا كان الدليل فارغًا ، فإن الصفيف الذي تم إرجاعه فارغ. إرجاع NULL إذا لم يكن المسار المحدد موجودًا أو يحدث خطأ I/O.
لذلك ، عادة ما تستخدم هذه الطريقة مثل هذا:
دليل الملف = // ... if (directory.isdirectory ()) {string [] list = directory.list () ؛ if (list! = null) {for (string file: list) {// ...}}}هل تعتقد أن الفحص الفارغ ضروري؟ ستنتج معظم عمليات I/O IoExceptions ، لكن هذه الطريقة لا تُرجع فقط. لا يمكن لتخزين رسائل خطأ I/O. لذلك ، فإن مثل هذا التصميم له أوجه القصور الثلاثة التالية:
إذا نظرت إلى المشكلة من منظور المجموعات ، فإن مجموعة أو مجموعة فارغة هي أفضل تطبيق لـ "غير موجود". يعد إرجاع مجموعة أو مجموعة فارغة ذات أهمية عملية ما لم يتم استخدامها لتأخر التهيئة.
القاعدة: لا ينبغي أن تكون الصفيف أو المجموعة التي تم إرجاعها لاغية.
فائدة HTTP عديمة الجنسية. يتم نقل جميع الولايات ذات الصلة في كل طلب واستجابة. هذا هو جوهر التسمية الراحة: نقل الدولة (نقل الحالة التمثيلية). من الرائع أيضًا القيام بذلك في جافا. فكر في هذا من منظور القاعدة 2 عندما تتلقى الطريقة كائن معلمة الحالة. إذا تم نقل الدولة من خلال مثل هذا الكائن ، بدلاً من تشغيل الدولة من الخارج ، فستكون الأمور أسهل. خذ JDBC كمثال. المثال التالي يقرأ المؤشر من برنامج مخزن.
callablesTatement s = connection.preparecall ("{؟ = ...}") ؛ // معالجة مطوّلة لحالة البيان: s.registerOutParameter (1 ، cursor) ؛ s.SetStstring (2 ، "abc") ؛هذا يجعل JDBC API غريب جدا. كل كائن أمر ملعب ويصعب العمل. على وجه التحديد ، هناك مشكلتان رئيسيتان:
القواعد: المزيد من التطبيقات في النمط الوظيفي. نقل الحالة من خلال معلمات الطريقة. عدد قليل جدا من حالات التشغيل التشغيلية.
هذه طريقة سهلة نسبيا للعمل. في أنظمة الكائنات المعقدة نسبيًا ، يمكنك تحقيق تحسينات كبيرة في الأداء ، طالما أنك تصدر أحكامًا متساوية أولاً في طريقة متساوية () لجميع الكائنات:
Overridepublic Boolean يساوي (كائن آخر) {if (this == other) return true ؛ // منطق حكم المساواة الآخر ...}لاحظ أن فحوصات الدائرة القصيرة الأخرى قد تتضمن اختبارات قيمة خالية ، لذلك يجب إضافتها أيضًا:
Overridepublic Boolean يساوي (كائن آخر) {if (this == other) return true ؛ إذا (الآخر == فارغ) العودة كاذبة ؛ // بقية منطق المساواة ...}القاعدة: استخدم الدوائر القصيرة في جميع أساليب متساوية () لتحسين الأداء.
قد يختلف بعض الأشخاص مع هذا ، لأن جعل الطريقة الافتراضية إلى النهائي يتعارض مع عادة مطوري Java. ولكن إذا كان لديك تحكم كامل في الكود ، فمن المؤكد أنه من الصحيح جعل الطريقة افتراضية إلى النهائي:
هذا مناسب بشكل خاص للطرق الثابتة ، وفي هذه الحالة "تراكب" (انسداد فعلي) بالكاد يعمل. لقد صادفت مؤخرًا مثالًا على طريقة ثابتة للتظليل سيئ للغاية في Apache Tika. ألقِ نظرة:
يمتد TikainputStream TaggedInputStream لإخفاء طريقة Get () الثابتة مع تطبيق مختلف نسبيًا.
على عكس الأساليب التقليدية ، لا يمكن كتابة الطرق الثابتة مع بعضها البعض لأن المكالمة مرتبطة بالاتصال بالأسلوب الثابت في وقت الترجمة. إذا كنت محظوظًا ، فقد تحصل بطريق الخطأ على الطريقة الخاطئة.
القاعدة: إذا كان لديك تحكم كامل في واجهة برمجة التطبيقات الخاصة بك ، فقم بعمل أكبر عدد ممكن من الطرق الافتراضية للنهائي.
في المناسبات الخاصة ، يمكنك استخدام طريقة المعلمة المتغيرة "قبول الكل" لتلقي كائن ... المعلمة:
باطل قبول (كائن ... الكل) ؛
إن كتابة مثل هذه الطريقة تجلب إحساسًا صغيرًا من JavaScript للنظام الإيكولوجي Java. بالطبع قد ترغب في الحد من النوع الفعلي بناءً على الموقف الفعلي ، مثل السلسلة ... نظرًا لأنك لا ترغب في الحد من الكثير ، فقد تعتقد أنه من الجيد استبدال الكائن بـ T:
باطل قبول (t ... الكل) ؛
لكن لا. سيتم دائمًا استنتاج T ككائن. في الواقع ، قد تظن أنه لا يمكن استخدام الأدوية الجنيسة في الطرق المذكورة أعلاه. الأهم من ذلك ، قد تعتقد أنه يمكنك زيادة تحميل الطريقة أعلاه ، ولكن لا يمكنك:
void accountall (t ... all) ؛ void accountall (string message ، t ... all) ؛
هذا يبدو أنه يمكنك تمرير رسالة سلسلة اختياريا إلى الطريقة. ولكن ماذا يحدث لهذه المكالمة؟
قبول ("الرسالة" ، 123 ، "ABC") ؛المترجم يثني T as <؟ يمتد قابلة للتسلسل ومقارنة <؟ >> ، والتي ستجعل المكالمة غير واضحة!
لذلك كلما كان لديك توقيع "قبول الكل" (حتى لو كان عامًا) ، فلن تتمكن أبدًا من كتابة تحميله. قد يسمح مستهلكو API فقط للمترجم "عن طريق الخطأ" اختيار الطريقة "الصحيحة" عندما يكونون محظوظين. ولكن من الممكن أيضًا استخدام طريقة قبول الكل أو عدم استدعاء أي طريقة.
القاعدة : تجنب التوقيعات "قبول الكل" إن أمكن. إذا لم يكن الأمر كذلك ، فلا تحمل مثل هذه الطريقة.
جافا وحش. على عكس اللغات الأكثر مثالية الأخرى ، تطورت ببطء إلى ما هي عليه اليوم. قد يكون هذا أمرًا جيدًا ، لأنه في سرعة تطوير Java ، هناك بالفعل مئات التحذيرات ، ولا يمكن فهم هذه التحذيرات إلا من خلال سنوات من الخبرة.
ترقبوا المزيد من القوائم العشرة الأولى حول هذا الموضوع!
الرابط الأصلي: Jooq Translation: ImportNew.com - تشبه
رابط الترجمة: http://www.importnew.com/10138.html
[يرجى الاحتفاظ بالمصدر الأصلي والمترجم ورابط الترجمة عند إعادة الطباعة. ]