Apakah penginisialisasi statis besar bau kode?

8

Saya memperluas SimpleExpandableListAdapterdi Android. Saya tidak berpikir adaptor Android diterapkan dengan sangat baik, karena konstruktornya memiliki sejumlah besar argumen yang agak rumit dan tidak memiliki setter atau builder. Di kelas saya, sebagian besar argumen itu tidak bergantung pada kelas panggilan sehingga saya ingin membangunnya secara internal. Namun, argumennya bersarang Listdan array int dan string yang perlu dibangun secara pemrograman.

Karena tidak ada yang dapat dipanggil sebelum superkonstruktor, dan metode instance tidak dapat dipanggil sebelum superpanggilan kembali, saya saat ini memiliki beberapa metode statis yang saya panggil dari superpanggilan:

super(getContext(), initGroupData(), groupLayout, initGroupFrom(), initGroupTo(),
        initChildData(), childLayout, initChildFrom(), initChildTo());

Saya melihat tiga cara menangani ini: memanggil metode statis seperti saya sekarang, memiliki penginisialisasi statis besar yang mungkin memanggil metode yang sama ini untuk menginisialisasi variabel statis yang kemudian digunakan dalam superpanggilan, atau merangkum semua metode ini menjadi pembangun.

Saya pikir sekarang saya condong ke arah pembangun, tapi saya bertanya-tanya apakah ada cara yang lebih baik untuk menangani ini.

TBridges42
sumber
1
Bagaimana dengan metode / fungsi pabrik?
Paŭlo Ebermann

Jawaban:

9

Memiliki fungsi pembantu statis untuk membuat argumen konstruktor adalah solusi yang sangat masuk akal, tetapi fungsi ini terbatas dalam operasi apa yang dapat mereka lakukan karena mereka harus menghasilkan tepat satu argumen masing-masing, dan tidak dapat berkomunikasi satu sama lain.

Dalam kasus yang paling umum di mana Anda ingin mengadaptasi antarmuka Constructor(A, B, C)ke antarmuka yang lebih bermanfaat Constructor(X, Y), Anda dapat menentukan konstruktor pembantu pribadi yang mengambil pribadi ArgumentObjectdan rantai ke konstruktor yang ada. Konstruktor yang lebih bermanfaat kemudian rantai ke konstruktor helper melalui fungsi helper statis untuk membuat objek argumen:

class Constructor {
  // constructor you want to wrap
  public Constructor(A a, B b, C c) { ... }
  // better constructor you are defining
  public Constructor(X x, Y y) { this(createArgumentObject(x, y)); }
  // helper constructor using an ArgumentObject
  private Constructor(ArgumentObject ao) { this(ao.a, ao.b, ao.c); }
  // helper to create the argument object
  private static ArgumentObject createArgumentObject(X x, Y y) { ... }
  private static class ArgumentObject { ... }
}

Dalam bahasa yang tidak memiliki rangkaian konstruktor dalam kelas yang sama (seperti C ++ 03), Anda harus mendefinisikan subkelas perantara untuk konstruktor pembantu.

Namun, teknik ini hanyalah generalisasi dari penggunaan fungsi statis dalam argumen konstruktor. Solusi lain yang telah Anda usulkan memiliki berbagai kelemahan sehingga saya akan menghindarinya kecuali ada alasan yang sangat baik untuk memilihnya:

  • menerapkan pembangun yang baik membutuhkan banyak upaya untuk nilai yang sangat kecil. Jika konstruktor baru cukup sederhana, Anda dapat melakukannya tanpa pembangun. Dengan asumsi kelas yang Anda bungkus melakukan validasi yang kuat, Anda dapat membuat objek argumen publik sehingga argumen dapat diteruskan menggunakan Constructor(new Constructor.Arguments {{ foo = 42; bar = baz; }})idiom.

  • menggunakan variabel statis yang dihitung dalam blok penginisialisasi statis masuk akal untuk data benar-benar statis, tetapi harus berhati-hati untuk menghindari keadaan global. Kecuali inisialisasi sangat sederhana, Anda harus menggunakan fungsi statis untuk menginisialisasi variabel-variabel ini agar inisialisasi dapat diuji. Sekarang, satu-satunya keuntungan daripada langsung menggunakan metode statis adalah bahwa nilai-nilai hanya dihitung sekali dan digunakan kembali untuk semua inisialisasi.

    Karena pertanyaan Anda menunjukkan inisialisasi ini bisa lebih kompleks, menggunakan blok penginisialisasi statis adalah besar tidak-tidak jika testabilitas penting bagi Anda. (Jika tidak, Anda memiliki masalah yang lebih mendesak.)

amon
sumber