Di tim saya, kami telah membersihkan banyak barang lama dalam proyek monolitik besar (seluruh kelas, metode, dll.).
Selama tugas pembersihan itu saya bertanya-tanya apakah ada semacam anotasi atau perpustakaan yang lebih bagus dari biasanya @Deprecated
. Ini @FancyDeprecated
harus mencegah pembangunan proyek dari berhasil jika Anda belum membersihkan kode lama yang tidak digunakan setelah tanggal tertentu berlalu.
Saya telah mencari di internet dan tidak menemukan apa pun yang memiliki kemampuan yang dijelaskan di bawah ini:
- harus berupa anotasi, atau sesuatu yang serupa, untuk dimasukkan ke dalam kode yang Anda ingin hapus sebelum tanggal tertentu
- sebelum tanggal itu kode akan dikompilasi dan semuanya akan bekerja secara normal
- setelah tanggal itu kode tidak akan dikompilasi dan itu akan memberi Anda pesan yang memperingatkan Anda tentang masalah tersebut
Saya rasa saya sedang mencari unicorn ... Apakah ada teknologi serupa untuk bahasa program apa pun?
Sebagai rencana, BI sedang memikirkan kemungkinan membuat keajaiban dengan beberapa unit test kode yang dimaksudkan untuk dihapus yang mulai gagal pada "batas waktu". Apa yang Anda pikirkan tentang ini? Ada ide yang lebih baik?
sumber
Jawaban:
Saya tidak berpikir ini akan menjadi fitur yang berguna ketika itu benar-benar melarang kompilasi. Ketika pada 01/06/2018 sebagian besar kode tidak akan mengkompilasi yang dikompilasi sehari sebelumnya, tim Anda akan dengan cepat menghapus anotasi itu lagi, kode dibersihkan atau tidak.
Namun, Anda dapat menambahkan beberapa anotasi khusus ke kode seperti
dan buat alat kecil untuk memindai anotasi tersebut. (Satu liner sederhana dalam grep akan melakukannya, jika Anda tidak ingin menggunakan refleksi). Dalam bahasa lain selain Jawa, komentar standar yang cocok untuk "grepping", atau definisi preprosesor dapat digunakan.
Kemudian jalankan alat itu sesaat sebelum atau setelah tanggal tertentu, dan jika masih menemukan anotasi itu, ingatkan tim untuk segera membersihkan bagian kode tersebut.
sumber
Ini akan menjadi fitur yang dikenal sebagai bom waktu . JANGAN BUAT BOM WAKTU.
Kode, tidak peduli seberapa baik Anda menyusun dan mendokumentasikannya, akan berubah menjadi kotak hitam hampir-mitos yang tidak dipahami jika ia hidup di luar usia tertentu. Hal terakhir siapa pun di masa depan kebutuhan adalah satu lagi modus kegagalan aneh yang menangkap mereka benar-benar terkejut, pada saat kemungkinan terburuk, dan tanpa obat yang jelas. Sama sekali tidak ada alasan untuk secara sengaja menghasilkan masalah seperti itu.
Lihatlah dengan cara ini: jika Anda terorganisir dan menyadari basis kode Anda cukup bahwa Anda peduli tentang usang dan menindaklanjutinya, maka Anda tidak perlu mekanisme dalam kode untuk mengingatkan Anda. Jika tidak, kemungkinan Anda juga tidak mengetahui aspek-aspek lain dari basis kode, dan mungkin tidak akan dapat merespons alarm tepat waktu dan dengan benar. Dengan kata lain, bom waktu tidak memiliki tujuan yang baik bagi siapa pun. Katakan saja tidak!
sumber
Dalam C # Anda akan menggunakan
ObsoleteAttribute
cara berikut:Idenya di sini adalah untuk membuat perubahan melanggar tanpa rasa sakit mungkin bagi pengguna yang terkena dampak, dan untuk memastikan bahwa mereka dapat terus menggunakan fitur untuk setidaknya satu versi perpustakaan.
sumber
libfoo.so.2
danlibfoo.so.3
dapat hidup berdampingan satu sama lain dengan baik, hilir Anda dapat terus menggunakan perpustakaan lama sampai mereka dialihkan.Anda salah mengerti apa arti "usang". Berarti usang:
Kamus Oxford
Menurut definisi, fitur usang masih akan dikompilasi.
Anda ingin menghapus fitur pada tanggal tertentu. Tidak apa-apa. Cara Anda melakukannya adalah menghapusnya pada tanggal itu .
Sampai saat itu, tandai sebagai usang, usang, atau apa pun bahasa pemrograman Anda menyebutnya. Dalam pesan, sertakan tanggal itu akan dihapus dan hal yang menggantikannya. Ini akan menghasilkan peringatan, menunjukkan bahwa pengembang lain harus menghindari penggunaan baru dan harus mengganti penggunaan lama sedapat mungkin. Pengembang itu akan mematuhi atau mengabaikannya, dan seseorang harus berurusan dengan konsekuensi ketika dihapus. (Tergantung situasinya, mungkin Anda atau pengembang yang menggunakannya.)
sumber
Jangan lupa bahwa Anda perlu mempertahankan kemampuan untuk membangun dan men-debug versi kode yang lebih lama untuk mendukung versi perangkat lunak yang telah dirilis. Menyabotase bangunan setelah tanggal tertentu berarti Anda juga berisiko mencegah diri Anda melakukan pemeliharaan dan dukungan yang sah di masa depan.
Selain itu, sepertinya solusi sepele untuk mengatur jam mesin saya kembali satu atau dua tahun sebelum dikompilasi.
Ingat, "usang" adalah peringatan bahwa sesuatu akan hilang di masa depan. Saat Anda ingin secara paksa mencegah orang menggunakan API itu, hapus saja kode yang terkait . Tidak ada gunanya meninggalkan kode di basis kode jika beberapa mekanisme membuatnya tidak dapat digunakan. Menghapus kode memberi Anda waktu kompilasi pemeriksaan yang Anda cari, dan tidak memiliki solusi sepele.
Sunting: Saya melihat Anda merujuk ke "kode lama yang tidak digunakan" dalam pertanyaan Anda. Jika kode tersebut benar-benar tidak digunakan , tidak ada gunanya mencabutnya. Hapus saja.
sumber
Saya belum pernah melihat fitur seperti itu sebelumnya - sebuah anotasi yang mulai berlaku setelah tanggal tertentu.
The
@Deprecated
dapat cukup, namun. Menangkap peringatan dalam CI, dan membuatnya menolak untuk menerima bangunan jika ada. Ini mengalihkan tanggung jawab dari kompiler ke pipeline build Anda, tetapi memiliki keuntungan bahwa Anda dapat (semi) dengan mudah mengubah pipeline build dengan menambahkan langkah-langkah tambahan.Perhatikan bahwa jawaban ini tidak sepenuhnya menyelesaikan masalah Anda (mis. Pengembangan lokal di atas mesin pengembang masih akan berhasil, meskipun dengan peringatan) dan mengasumsikan bahwa Anda telah menyiapkan dan menjalankan pipa CI.
sumber
Anda mencari kalender atau daftar agenda .
Alternatif lain adalah dengan menggunakan peringatan kompiler khusus atau pesan kompiler, jika Anda berhasil memiliki sedikit jika ada peringatan dalam basis kode Anda. Jika Anda memiliki terlalu banyak peringatan, Anda harus menghabiskan upaya tambahan (sekitar 15 menit?) Dan harus mengambil peringatan kompiler dalam laporan pembangunan yang diberikan integrasi berkelanjutan Anda pada setiap bangunan.
Pengingat bahwa kode perlu diperbaiki adalah baik dan perlu. Kadang-kadang pengingat ini memiliki tenggat waktu dunia nyata yang ketat, jadi meletakkannya di penghitung waktu mungkin juga diperlukan.
Tujuannya adalah untuk terus-menerus mengingatkan orang bahwa masalah itu ada dan perlu diperbaiki dengan jangka waktu tertentu - fitur yang hanya memecah build pada waktu tertentu tidak hanya tidak melakukan itu, tetapi fitur itu sendiri merupakan masalah yang perlu diperbaiki dengan jangka waktu tertentu.
sumber
Salah satu cara untuk berpikir tentang ini adalah apa yang Anda maksud dengan waktu / tanggal ? Komputer tidak tahu apa konsep-konsep ini: mereka harus diprogram dalam cara apa pun. Ini cukup umum untuk merepresentasikan waktu dalam format UNIX "detik sejak zaman", dan itu umum untuk memasukkan nilai tertentu ke dalam program melalui panggilan OS. Namun, tidak peduli seberapa umum penggunaan ini, penting untuk diingat bahwa ini bukan waktu "aktual": ini hanya representasi logis.
Seperti yang orang lain tunjukkan, jika Anda membuat "tenggat waktu" menggunakan mekanisme ini, itu sepele untuk memberi makan di waktu yang berbeda dan memutus "tenggat waktu" itu. Hal yang sama berlaku untuk mekanisme yang lebih rumit seperti meminta server NTP (bahkan melalui koneksi "aman", karena kami dapat mengganti sertifikat kami sendiri, otoritas sertifikat atau bahkan menambal perpustakaan crypto). Pada awalnya mungkin terlihat bahwa orang-orang tersebut bersalah karena bekerja di sekitar mekanisme Anda, tetapi mungkin itu terjadi secara otomatis dan untuk alasan yang baik . Sebagai contoh, adalah ide yang baik untuk membuat build yang dapat direproduksi , dan alat untuk membantu hal ini dapat secara otomatis mereset / mencegat panggilan sistem non-deterministik tersebut. Libibaketime melakukan hal itu,menyetel semua stempel waktu file ke
1970-01-01 00:00:01
, fitur record / replay Qemu memalsukan semua interaksi perangkat keras, dll.Ini mirip dengan hukum Goodhart : jika Anda membuat perilaku program bergantung pada waktu logis, maka waktu logis berhenti menjadi ukuran yang baik dari waktu "aktual". Dengan kata lain, orang pada umumnya tidak akan mengacaukan jam sistem, tetapi mereka akan melakukannya jika Anda memberi mereka alasan.
Ada representasi waktu logis lainnya: salah satunya adalah versi perangkat lunak (baik aplikasi Anda atau ketergantungan). Ini adalah representasi yang lebih diinginkan untuk "tenggat waktu" daripada misalnya waktu UNIX, karena itu lebih spesifik untuk hal yang Anda pedulikan (mengubah set fitur / API) dan karenanya cenderung menginjak-injak masalah ortogonal (misalnya mengutak-atik waktu UNIX untuk mengatasi batas waktu Anda bisa berakhir dengan memecah file log, tugas cron, cache, dll.).
Seperti yang dikatakan orang lain, jika Anda mengontrol perpustakaan dan ingin "mendorong" perubahan ini, Anda dapat mendorong versi baru yang mencemari fitur (menyebabkan peringatan, untuk membantu konsumen menemukan dan memperbarui penggunaannya), lalu versi baru lainnya yang menghilangkan fitur sepenuhnya. Anda dapat mempublikasikan ini segera setelah satu sama lain jika Anda suka, karena (lagi) versi hanyalah representasi waktu yang logis, mereka tidak perlu terkait dengan waktu "aktual". Versi semantik dapat membantu di sini.
Model alternatif adalah "menarik" perubahan. Ini seperti "paket B" Anda: tambahkan tes ke aplikasi yang menggunakan, yang memeriksa bahwa versi ketergantungan ini setidaknya nilai baru. Seperti biasa, merah / hijau / refactor untuk menyebarkan perubahan ini melalui basis kode. Ini mungkin lebih tepat jika fungsi tidak "buruk" atau "salah", tetapi hanya "cocok untuk kasus penggunaan ini".
Pertanyaan penting dengan pendekatan "tarikan" adalah apakah versi ketergantungan dihitung sebagai "unit" ( fungsionalitas ), dan karenanya layak untuk diuji; atau apakah itu hanya detail implementasi "pribadi", yang seharusnya hanya dilakukan sebagai bagian dari tes unit ( fungsionalitas ) yang sebenarnya. Saya akan mengatakan: jika perbedaan antara versi dependensi benar-benar dihitung sebagai fitur aplikasi Anda, maka lakukan tes (misalnya, memeriksa bahwa versi Python>> = 3.x). Jika tidak, maka jangantambahkan tes (karena akan rapuh, tidak informatif dan terlalu membatasi); jika Anda mengontrol perpustakaan maka turunkan rute "push". Jika Anda tidak mengontrol perpustakaan maka gunakan saja versi apa pun yang disediakan: jika tes Anda lulus maka tidak layak membatasi diri Anda; jika mereka tidak lulus maka itulah "tenggat waktu" Anda di sana!
Ada pendekatan lain, jika Anda ingin mencegah penggunaan fitur dependensi tertentu (misalnya memanggil fungsi-fungsi tertentu yang tidak cocok dengan sisa kode Anda), terutama jika Anda tidak mengontrol ketergantungan: minta standar pengkodean Anda melarang Saya tidak menyarankan penggunaan fitur-fitur ini, dan tambahkan tanda centang pada fitur-fitur Anda
Masing-masing akan berlaku dalam keadaan yang berbeda.
sumber
Anda mengelola ini di tingkat paket atau perpustakaan. Anda mengontrol paket dan mengontrol visibilitasnya. Anda bebas untuk menarik kembali visibilitas. Saya telah melihat ini secara internal di perusahaan besar dan hanya masuk akal dalam budaya yang menghormati kepemilikan paket bahkan jika paket tersebut bersifat open source atau bebas untuk digunakan.
Ini selalu berantakan karena tim klien tidak ingin mengubah apa pun, jadi Anda sering memerlukan putaran daftar putih saja saat Anda bekerja dengan klien tertentu untuk menyetujui tenggat waktu untuk bermigrasi, mungkin menawarkan dukungan kepada mereka.
sumber
Salah satu persyaratan adalah untuk memperkenalkan gagasan tentang waktu ke dalam bangunan. Dalam C, C ++, atau bahasa lainnya / membangun sistem yang menggunakan C-seperti preprocessor 1 , salah satu bisa memperkenalkan cap waktu melalui mendefinisikan untuk preprocessor pada waktu membangun:
CPPFLAGS=-DTIMESTAMP()=$(date '+%s')
. Ini kemungkinan akan terjadi di makefile.Dalam kode kita akan membandingkan token itu dan menyebabkan kesalahan jika waktu habis. Perhatikan bahwa menggunakan fungsi makro menangkap kasus yang tidak didefinisikan seseorang
TIMESTAMP
.Atau, seseorang bisa "mendefinisikan" kode yang dimaksud ketika saatnya tiba. Itu akan memungkinkan program untuk dikompilasi, asalkan tidak ada yang menggunakannya. Katakanlah, kami memiliki tajuk yang mendefinisikan api, "api.h", dan kami tidak mengizinkan panggilan
old()
setelah waktu tertentu:Konstruk serupa mungkin akan menghilangkan
old()
fungsi tubuh dari beberapa file sumber.Tentu saja ini bukan bukti bodoh; seseorang dapat dengan mudah mendefinisikan yang lama
TIMESTAMP
dalam kasus bangunan darurat Jumat malam yang disebutkan di tempat lain. Tapi itu, saya pikir, agak menguntungkan.Ini jelas hanya berfungsi ketika perpustakaan dikompilasi ulang - setelah itu kode usang tidak ada lagi di perpustakaan. Itu tidak akan mencegah kode klien dari menautkan ke binari usang.
1 C # hanya mendukung definisi sederhana dari simbol preprosesor, tanpa nilai numerik, yang membuat strategi ini tidak dapat dijalankan.
sumber
TIMESTAMP
untuk dikompilasi ulang pada setiap build. Ini juga akan melumpuhkan alat seperticcache
. Ini berarti bahwa waktu kompilasi tipikal untuk penambahan bertahap akan meningkat secara signifikan tergantung pada seberapa banyak basis kode dipengaruhi oleh fitur yang ditinggalkan dengan cara ini.TIMESTAMP
nilainya dengan, katakanlah, 86400, untuk mendapatkan rincian setiap hari dan dengan demikian lebih sedikit kompilasi ulang.Di Visual Studio, Anda bisa mengatur skrip pra-bangun yang melempar kesalahan setelah tanggal tertentu. Ini akan mencegah kompilasi. Berikut skrip yang menampilkan kesalahan pada atau setelah 12 Maret 2018 ( diambil dari sini ):
Pastikan untuk membaca jawaban lain di halaman ini sebelum menggunakan skrip ini.
sumber
Saya mengerti tujuan dari apa yang Anda coba lakukan. Tetapi seperti yang telah disebutkan orang lain, sistem build / compiler mungkin bukan tempat yang tepat untuk menegakkan ini. Saya menyarankan lapisan yang lebih alami untuk menegakkan kebijakan ini adalah variabel SCM atau lingkungan.
Jika Anda melakukan yang terakhir, pada dasarnya tambahkan flag fitur yang menandai menjalankan pra-penghentian. Setiap kali Anda membangun kelas yang sudah usang atau memanggil metode yang sudah usang, periksa tanda fitur. Cukup tentukan satu fungsi statis
assertPreDeprecated()
dan tambahkan ini ke setiap jalur kode yang sudah usang. Jika sudah diatur, abaikan panggilan panggilan. Jika tidak ada pengecualian. Setelah tanggal berlalu, batalkan flag fitur di lingkungan runtime. Setiap panggilan lama yang ditinggalkan ke kode akan muncul di log runtime.Untuk solusi berbasis SCM, saya akan menganggap Anda menggunakan git dan git-flow. (Jika tidak, logikanya mudah disesuaikan dengan VCS lain). Buat cabang baru
postDeprecated
. Di cabang itu hapus semua kode yang sudah tidak digunakan lagi, dan mulailah bekerja untuk menghapus referensi apa pun hingga kompilasi. Setiap perubahan normal terus dilakukan kemaster
cabang. Terus gabungkan setiap perubahan kode terkait yang tidak usangmaster
kembali ke dalampostDeprecated
untuk meminimalkan tantangan integrasi.Setelah tanggal penghentian berakhir, buat
preDeprecated
cabang baru darimaster
. Kemudian bergabungpostDeprecated
kembalimaster
. Dengan asumsi rilis Anda keluar darimaster
cabang, Anda sekarang harus menggunakan cabang pasca-ditinggalkan setelah tanggal. Jika ada keadaan darurat, atau Anda tidak dapat memberikan hasil dalam waktu, Anda selalu dapat mengembalikan kepreDeprecated
, dan membuat perubahan yang diperlukan pada cabang itu.sumber