سؤال

أنا الآن أعمل مع التعليمات البرمجية التي تبدو وكأنها

public String getName(User user) {
     user.setSth(...);
     return user.getName();
}

أعتقد أنه من الممارسات السيئة تغيير الكائنات التي تم تمريرها كمعلمات. هل هناك أداة بالكشف عن هذا النوع من التعليمات البرمجية؟ نظرت إلى Findbugs، PMD و CheckStyle، ولكن لا يمكن العثور على أي تحقق لهذا.

ملاحظة آسف للمثال السيئ.

هل كانت مفيدة؟

المحلول

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

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

نصائح أخرى

لن تجد أي شيء لأنه، من وجهة نظر أداة، "GetName" و "Studth" هي مجرد مكالمات طريقة. يقول البشر "هذا ما better" و "هذا هو studter" ولكن الأدوات لا. في الواقع، GetName () ليس مجرد Getter لأن Getters لا يقبل الحجج.

لذلك لا يمكن للأداة رؤية أي شيء غير عادي لأن الأساليب تغيير الكائنات طوال الوقت.

إذا كنت ترغب في إنفاذ هذه القاعدة، فابحث في تمديد ببيانات و PMD. كلاهما يسمح لك بتحديد قيود إضافية. ما تبحث عنه هو ربما:

  • إذا كان اسم الطريقة يبدأ ب "الحصول"
  • وطريقة مكالمات الجسم طريقة أي كائن يمر كمعلمة

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

هل يمكن أن تجعل User ثابت (أعلن ذلك final, ، تعلن جميع الخصائص final ونخة عن setters. أعلم أن هذا ليس ممتلا في كل مكان ولكن في العديد من الأماكن جيدة ولن يكون لديك أي مشاكل في تمرير ذلك إلى وظائف أخرى).

إذا كان عليك "تغيير" شيء ما، فيمكنك تنفيذ وظائف مثل newId في تلك العينة:

public final class User {
    private final String name;
    private final int id;

    User(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public User newId(int newId) {
        return new User(this.name, newId);
    }

    //getters here;
}

بنيت في String, Integer, ، ... الفصول تفعل ذلك أيضا.

يمكنك إنشاء واجهة تسمى UserView تحتوي فقط على "Jetters"، وجعل المستخدم ينفذه واستخدام واجهة USERVIEW الجديدة كوعي المعلمة.

interface UserView{
 public String getName();
...

class User implements UserView...

public String getName(UserView user) {
     user.setSth(...); // Will not compile
     return user.getName();
}

في الواقع هذا شيء في C ++ كان من السهل جدا القيام به عبر const التصفيات. سوف تحدد المعلمة كما const ولهذه المعلمة يمكنك فقط استدعاء الأساليب المعرفة كما const - عادة، betters.

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

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

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

بعض الروابط:

http://prog.vub.ac.be/dmp/

http://www.cs.bris.ac.uk/publications/pub_master.jsm؟id=1000273.

وبقية

http://www.google.com/search؟num=100&hl=en&q=declarativeStaprogramming.

أنت تبحث عن شيء مثل "const" في C ++ التي ستنفذ في جعل قيمة المعلمة غير قابلة للتغيير مثل المرجع الذي تم تمريره. كائنات ثابتة تضمن ذلك، إذا كنت تستطيع العيش معهم.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top