"Statis" sebagai petunjuk semantik tentang kewarganegaraan?

11

Saya baru-baru ini melakukan refactoring proyek berukuran sedang di Jawa untuk kembali dan menambahkan tes unit. Ketika saya menyadari betapa sakitnya mengejek para lajang dan statika, saya akhirnya "mendapatkan" apa yang telah saya baca tentang mereka selama ini. (Saya salah satu dari orang-orang yang perlu belajar dari pengalaman. Oh well.)

Jadi, sekarang saya menggunakan Spring untuk membuat objek dan menyambungkannya ke sekitar, saya menyingkirkan statickata kunci kiri dan kanan. (Jika saya berpotensi ingin mengejeknya, itu tidak benar-benar statis dalam arti yang sama dengan Math.abs () adalah, kan?) Masalahnya adalah, saya sudah terbiasa menggunakan staticuntuk menunjukkan bahwa suatu metode tidak mengandalkan pada keadaan objek apa pun. Sebagai contoh:

//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
    public static Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
ThirdPartyLibraryWrapper.newThingy(input);
//After
public class ThirdPartyFactory {
    public Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
thirdPartyFactoryInstance.newThingy(input);

Jadi, di sinilah ia menjadi sensitif. Saya menyukai cara lama karena huruf kapital mengatakan kepada saya bahwa, sama seperti Math.sin (x), ThirdPartyLibraryWrapper.newThingy (x) melakukan hal yang sama dengan cara yang sama setiap kali. Tidak ada status objek untuk mengubah bagaimana objek melakukan apa yang saya minta. Berikut adalah beberapa kemungkinan jawaban yang saya pertimbangkan.

  • Tidak ada orang lain yang merasakan hal ini sehingga ada yang salah dengan saya. Mungkin saya belum benar-benar menginternalisasi cara OO dalam melakukan sesuatu! Mungkin saya menulis di Jawa tetapi berpikir dalam FORTRAN atau semacamnya. (Yang akan mengesankan karena saya belum pernah menulis FORTRAN.)
  • Mungkin saya menggunakan staticness sebagai semacam proksi untuk imutabilitas untuk keperluan penalaran tentang kode. Yang sedang berkata, petunjuk apa yang harus saya miliki dalam kode saya untuk seseorang yang datang untuk mempertahankannya untuk mengetahui apa yang stateful dan apa yang tidak?
  • Mungkin ini harus datang secara gratis jika saya memilih metafora objek yang bagus? misalnya thingyWrappertidak terdengar seperti itu memiliki keadaan bebas dari bungkusnya Thingyyang mungkin dapat berubah. Demikian pula, thingyFactorysuara seperti itu harus kekal tetapi bisa memiliki strategi berbeda yang dipilih di antara pada saat penciptaan.
leoger
sumber

Jawaban:

12

Saya menyukai cara lama karena huruf kapital mengatakan kepada saya bahwa, sama seperti Math.sin (x), ThirdPartyLibraryWrapper.newThingy (x) melakukan hal yang sama dengan cara yang sama setiap kali. Tidak ada status objek untuk mengubah bagaimana objek melakukan apa yang saya minta.

Itu cara yang tepat untuk melakukannya, ya. Yang mengatakan, statictidak memberikan jaminan kekekalan atau kegigihan negara. Bahwa Anda menggunakannya sebagai saran untuk jaminan semacam itu memang masuk akal, tetapi itu sama sekali tidak terjamin.

Pertimbangkan yang berikut ini:

public static class Logger
{
    public static int LogLevel { get; set; }

    public static void Log(string message, int logLevel)
    {
        if (logLevel >= LogLevel)
        {
            // logs the message, but only if it is important enough.
        }
    }
}

Kelas ini tidak hanya memegang keadaan, tetapi perilaku Logger.Log()metode berubah ketika keadaan itu diubah. Ini adalah latihan yang sangat sah dari staticpola kelas, tetapi tidak memiliki jaminan semantik yang Anda sarankan.

Robert Harvey
sumber
Saya telah memberi Anda tanda centang karena Anda menyajikan tandingan yang berguna sebagai dasar intuisi saya, tetapi saya masih ingin mendapatkan pemikiran Anda tentang bagaimana saya harus menyatakan bahwa kontrak / harapan tentang kurangnya status dan kurangnya efek samping melalui pengkodean konvensi.
leoger
1
Biasanya harapan tersebut dimasukkan dalam dokumentasi untuk metode ini; hal yang sama berlaku untuk keamanan benang.
Robert Harvey
5

Menurut pendapat saya apa yang Anda katakan - semua fungsi statis menjadi nullipotent - adalah cara OO yang baik dalam menulis kode dalam banyak kasus, tetapi saya tidak percaya bahwa ketika Anda melihat fungsi statis, Anda harus secara otomatis menganggap bahwa itu tidak memiliki efek samping . Situasinya mungkin lebih kompleks; mengambil contoh fungsi Class.forName(String)yang tampaknya stateless tetapi sebenarnya memuat kelas ke dalam memori dan akhirnya instantiates bidang statis / jalankan penginisialisasi statis; ini adalah contoh fungsi idempoten (panggilan akhirnya setelah yang pertama tidak membuat perbedaan) tetapi ini bukan fungsi murni (tidak dapat dikatakan tidak memiliki efek samping). Ini juga merupakan pilihan yang baik, tetapi mungkin ada kasus di mana tiga panggilan berbeda ke fungsi yang sama menghasilkan tiga hasil yang berbeda; misalnya jika Anda meneleponThread.currentThread() dalam aplikasi multi-utas tidak ada jaminan Anda akan menerima utas yang sama setiap saat.

Yang sedang berkata, petunjuk apa yang harus saya miliki dalam kode saya untuk seseorang yang datang untuk mempertahankannya untuk mengetahui apa yang stateful dan apa yang tidak?

Solusi yang tepat adalah mendokumentasikan (Javadoc misalnya); juga, dari nama fungsi dan dari apa yang dilakukannya terkadang dapat disimpulkan bahwa fungsi statis adalah fungsi murni. Misalnya, tidak ada alasan bagi seseorang untuk percaya bahwa Assert.assertTrue(boolean)dari JUnit akan mengubah keadaan di suatu tempat. Di sisi lain ketika fungsi seperti System.clearProperty(String)dipanggil, cukup jelas bahwa akan ada efek samping.

m3th0dman
sumber
Apa perbedaan antara "nullipotent" dan "stateless"?
Pacerier
@Pacerier Seharusnya tidak ada perbedaan.
m3th0dman
4

Yang sedang berkata, petunjuk apa yang harus saya miliki dalam kode saya untuk seseorang yang datang untuk mempertahankannya untuk mengetahui apa yang stateful dan apa yang tidak?

Anda dapat membuatnya statis. FxCop di dunia C # akan mendorong Anda untuk membuat hal-hal statis yang tidak ada variabel anggota referensi. Ini adalah hal yang benar untuk dilakukan (biasanya).

Ketika saya menyadari betapa sakitnya mengejek para lajang dan statika, saya akhirnya "mendapatkan" apa yang telah saya baca tentang mereka selama ini.

Memindahkan mereka semua ke instance mungkin bukan pendekatan yang tepat. Sebaliknya, pisahkan ketergantungan pada metode statis dari kelas yang menggunakannya. Anda dapat menguji metode statis secara terpisah, dan kemudian mengganti ketergantungan pada konsumen ketika mereka perlu diuji.

Telastyn
sumber
Dapatkah Anda memberi saya contoh "memisahkan ketergantungan pada metode statis"? Bagi saya tidak jelas apa yang Anda aktifkan. Saya sudah menyembunyikan detail implementasi dalam metode statis. Pada akhirnya, kelas yang menggunakannya perlu mencapai fungsionalitas itu. Apakah Anda mengatakan saya harus membuat objek instan yang memiliki pembungkus tipis untuk semua metode statis?
leoger
1
@leoger - kelas yang menggunakan metode statis tidak perlu mencapai fungsionalitas jika Anda menguji kelas itu, jika tidak, Anda tidak akan mengejek metode statis.
Telastyn