interface - تسمية الواجهة في Java




naming-conventions (10)

= v = تستخدم البادئة "I" أيضًا في إطار Wicket ، حيث اعتدت على ذلك بسرعة. بشكل عام ، أرحب بأي اتفاقية تقصر أسماء فئات Java المرهقة. ومع ذلك ، من المتاعب أن يكون كل شيء أبجديًا تحت عنوان "أنا" في الدلائل وفي Javadoc.

تشبه ممارسة الترميز Wicket Swing ، حيث يتم إنشاء العديد من مثيلات عنصر التحكم / القطعة كفئات داخلية مجهولة باستخدام إعلانات الأسلوب المضمن. بشكل مزعج ، فإنه يختلف 180 درجة من التأرجح في ذلك Swing يستخدم بادئة ("J") لفئات التنفيذ.

اللاحقة "إمبل" هي اختصار بشجاعة ولا تدويل جيد. لو أننا على الأقل ذهبنا مع "Imp" سيكون ذلك لطيفًا (وقصيرًا). يتم استخدام "Impl" في IOC ، خاصةً الربيع ، لذا فنحن دائمًا ما نتعامل معه حاليًا. فإنه يحصل على schizo قليلا بعد 3 اتفاقيات مختلفة في ثلاثة أجزاء مختلفة من مصدر واحد ، على الرغم من.

تقوم معظم لغات OO بادئة أسماء واجهاتها برأس مال I ، فلماذا لا تقوم Java بذلك؟ ما هو الأساس المنطقي لعدم اتباع هذه الاتفاقية؟

لشرح ما أعنيه ، إذا كنت أرغب في الحصول على واجهة مستخدم وتطبيق مستخدم ، سيكون لدي خياران في Java:

  1. فئة = المستخدم ، واجهة = UserInterface
  2. Class = UserImpl ، Interface = المستخدم

أين في معظم اللغات:

فئة = المستخدم ، واجهة = IUser

الآن ، يمكنك القول بأنك تستطيع دائمًا اختيار اسمًا وصفيًا أكثر لتنفيذ المستخدم وتزول المشكلة ، لكن استخدام جافا لنهج POJO للأشياء ومعظم حاويات IOC تستخدم DynamicProxies على نطاق واسع. هذان الشيءان يعنيان أنه سيكون لديك الكثير من الواجهات مع تنفيذ POJO واحد.

لذا ، أعتقد أن سؤالي يتلخص في: "هل يستحق الأمر اتباع اتفاقية تسمية الواجهة الأوسع خاصة في ضوء حيث يبدو أن إطارات جافا تتجه؟"


هل هذا اصطلاح تسمية أوسع بأي معنى حقيقي؟ أنا أكثر على الجانب C ++ ، وليس حقا على جاوة والأحفاد. كم عدد مجتمعات اللغات التي تستخدم الاتفاقية I؟

إذا كان لديك اتفاقية تسمية قياسية لمتجر مستقل عن اللغة هنا ، فاستخدمها. إذا لم يكن الأمر كذلك ، فانتقل إلى اصطلاح تسمية اللغة.


بعد مبادئ OO الجيدة ، يجب أن تعتمد شفرتك (بقدر ما هو عملي / ممكن) على الأفكار التجريدية بدلاً من الفصول الملموسة. على سبيل المثال ، من الأفضل بشكل عام كتابة أسلوب مثل هذا:

public void doSomething(Collection someStuff) {
    ...
}

من هذا:

public void doSomething(Vector someStuff) {
    ...
}

إذا اتبعت هذه الفكرة ، فأنا أؤكد أن شفرتك ستكون أكثر قابلية للقراءة إذا أعطيت أسماء واجهات مثل "المستخدم" و "BankAccount" (على سبيل المثال) ، بدلاً من "IUser" أو "UserInterface" أو أشكال أخرى.

إن أجزاء الشفرة الوحيدة التي ينبغي أن تهتم بالطبقات الفعلية الفعلية هي الأماكن التي يتم فيها بناء الطبقات الخرسانية. يجب كتابة كل شيء آخر باستخدام الواجهات.

إذا قمت بذلك ، يجب أن تكون أسماء الفئات "القبيحة" ملموسة مثل "UserImpl" مخفية بأمان من بقية رمز ، والتي يمكن أن تستمر بمرح استخدام أسماء واجهة "لطيفة".


في C # هو

public class AdminForumUser : UserBase, IUser

جاوة تقول

public class AdminForumUser extends User implements ForumUserInterface

ولهذا السبب ، لا أظن أن الاتفاقيات مهمة بنفس القدر في جافا للواجهات ، حيث يوجد اختلاف واضح بين التوريث وتنفيذ الواجهة. أود أن أقول فقط اختيار أي اصطلاح تسمية تريده ، طالما كنت متسقة واستخدام شيء لإظهار الناس أن هذه هي واجهات. لم تكن قد فعلت جافا في بضع سنوات ، ولكن كل واجهات ستكون فقط في دليلهم الخاص ، وكان هذا هو الاتفاقية. أبدا حقا كان لديه أي مشاكل معها.


قد يكون هناك عدة أسباب لا تستخدم Java بشكل عام اصطلاح IUser.

  1. جزء من الأسلوب Object-Oriented هو أنه لا يجب عليك معرفة ما إذا كان العميل يستخدم واجهة أو فئة تطبيق. لذا ، حتى القائمة عبارة عن واجهة و String هي فئة فعلية ، قد يتم تمرير طريقة منها - لا معنى للتمييز البصري بين الواجهات.

  2. بشكل عام ، سوف نفضل استخدام الواجهات في كود العميل (تفضل القائمة إلى ArrayList ، على سبيل المثال). لذلك لا معنى لجعل الواجهات تبرز كاستثناءات.

  3. يفضّل اصطلاح التسمية Java أسماء أطول مع المعاني الفعلية للبادئات المجرية. بحيث يكون هذا الرمز مقروءًا قدر الإمكان: تمثل القائمة قائمة ، ويمثل المستخدم مستخدمًا - وليس وحدة IUser.


وكما قال ملصق آخر ، فمن المفضل عادة أن يكون لديك واجهات تعريف تحدد القدرات وليس الأنواع. أنا لا أميل إلى "تنفيذ" شيء مثل "المستخدم" ، وهذا هو السبب في "IUser" في كثير من الأحيان ليست ضرورية في الواقع كما هو موضح هنا. كثيرا ما أرى الطبقات كأسماء وواجهات مثل الصفات:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

في بعض الأحيان ، لا تكون الصفة منطقية ، لكنني سأظل أستخدم بشكل عام واجهات لنموذج السلوك ، والإجراءات ، والقدرات ، والخصائص ، إلخ ، ... وليس الأنواع.

أيضا ، إذا كنت حقا سوف تجعل مستخدم واحد فقط وتطلق عليه اسم المستخدم ، فما الفائدة من وجود واجهة IUser؟ وإذا كنت ستحصل على عدة أنواع مختلفة من المستخدمين الذين يحتاجون إلى تطبيق واجهة مشتركة ، ما الذي يؤدي إلى إلحاق "I" بالواجهة التي توفر لك اختيار أسماء التطبيقات؟

أعتقد أن أحد الأمثلة الأكثر واقعية هو أن بعض أنواع المستخدمين يجب أن يكونوا قادرين على تسجيل الدخول إلى واجهة برمجة تطبيقات معينة. يمكننا تعريف واجهة تسجيل الدخول ، ومن ثم الحصول على فئة رئيسية "المستخدم" مع SuperUser ، DefaultUser ، AdminUser ، AdministrativeContact ، etc suclasses ، بعضها سوف أو لن ينفذ واجهة تسجيل الدخول (تسجيل الدخول؟) حسب الضرورة.


من واقع تجربتي ، تنطبق اتفاقية "أنا" على الواجهات التي تهدف إلى توفير عقد لفئة معينة ، خاصة عندما تكون الواجهة نفسها ليست فكرة مجردة عن الفصل.

على سبيل المثال ، في حالتك ، كنت أتوقع رؤية IUser فقط إذا كان المستخدم الوحيد الذي تنوي IUser هو User . إذا كنت تخطط لأن يكون لديك أنواع مختلفة من المستخدمين - NoviceUser ، ExpertUser ، إلخ. - أتوقع رؤية واجهة User (وربما ، فئة AbstractUser تقوم بتنفيذ بعض الوظائف الشائعة ، مثل get/setName() ).

وأود أيضا أن نتوقع واجهات التي تحدد القدرات - قابلة Comparable ، Iterable ، وما إلى ذلك - ليتم تسميتها مثل هذا ، وليس مثل IComparable أو IIterable .


قال بوب لي مرة في عرض تقديمي:

ما الهدف من الواجهة إذا كان لديك تطبيق واحد فقط.

لذلك ، عليك أن تبدأ بتطبيق واحد أي بدون واجهة. في وقت لاحق تقرر ، حسنا ، هناك حاجة لواجهة هنا ، لذلك قمت بتحويل صفك إلى واجهة.

ثم يصبح من الواضح: الطبقة الأصلية الخاصة بك كان يسمى المستخدم. الواجهة الخاصة بك الآن تسمى المستخدم. ربما لديك UserProdImpl و UserTestImpl. إذا قمت بتصميم التطبيق الخاص بك بشكل جيد ، فإن كل فئة (باستثناء تلك التي تقوم بإنشاء مستخدم) لن تتغير ولن تلاحظ فجأة أن يتم تمريرها واجهة.

حتى يتضح -> واجهة تطبيق المستخدم UserImpl.


هناك أيضا اتفاقية أخرى ، تستخدمها العديد من المشاريع مفتوحة المصدر بما في ذلك الربيع.

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

أنا شخصيا لا أحب البادئة "أنا" لسبب بسيط أن لها اتفاقية اختيارية. لذلك إذا اعتمدت هذا يعني IIOPConnection واجهة ل IOPConnection؟ ماذا لو لم يكن الفصل الدراسي يحتوي على البادئة "I" ، فهل أعلم أنه ليس واجهة .. فالرد هنا لا ، لأن الاتفاقيات لا يتم اتباعها دائمًا ، وسيعمل حفظها على إنشاء المزيد من العمل الذي تحفظه الاتفاقية نفسها.


يمكن العثور على تفسير هنا: http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm

فئة تجريدية هي فئة يتم تنفيذها جزئيًا بواسطة المبرمج فقط. قد تحتوي على طريقة واحدة أو أكثر من الطرق التجريدية. الطريقة المجردة هي ببساطة تعريف دالة يعمل على إخبار مبرمج أنه يجب تنفيذ الطريقة في فئة فرعية.

واجهة تشبه فئة مجردة. بالفعل واجهات تشغل نفس مساحة الاسم مثل الطبقات وفئات مجردة. ولهذا السبب ، لا يمكنك تعريف واجهة بالاسم نفسه لفئة. الواجهة هي فئة مجردة بالكامل. لم يتم تنفيذ أي من أساليبها وبدلاً من التصنيف الفرعي للفئة منها ، يقال إنها تنفذ هذه الواجهة.

على أي حال أجد هذا الشرح من واجهات مربكة إلى حد ما. التعريف الأكثر شيوعًا هو: تحدد الواجهة عقدًا يجب على الفئتين التنفيذيتين تنفيذه. يتكون تعريف الواجهة من تواقيع أعضاء عامين ، دون أي رمز تنفيذ.





java interface naming-conventions