Saya menemukan file header berguna ketika menelusuri file sumber C ++, karena mereka memberikan "ringkasan" dari semua fungsi dan anggota data dalam suatu kelas. Mengapa banyak bahasa lain (seperti Ruby, Python, Java, dll.) Tidak memiliki fitur seperti ini? Apakah ini area di mana V ++ sangat berguna?
20
Jawaban:
Tujuan asli dari file header adalah untuk memungkinkan kompilasi single-pass dan modularitas dalam C. Dengan mendeklarasikan metode sebelum digunakan, itu hanya diperbolehkan untuk satu kompilasi pass. Usia ini sudah lama berlalu berkat komputer kami yang kuat mampu melakukan kompilasi multi-pass tanpa masalah, dan kadang-kadang bahkan lebih cepat daripada kompiler C ++.
C ++ yang kompatibel dengan C diperlukan untuk menjaga file header, tetapi menambahkan banyak di atasnya, yang menghasilkan desain yang cukup bermasalah. Lebih banyak di FQA .
Untuk modularitas, file header diperlukan sebagai metadata tentang kode dalam modul. Misalnya. metode apa (dan di kelas C ++) tersedia di perpustakaan apa. Jelas ada pengembang yang menulis ini, karena waktu kompilasi mahal. Saat ini, tidak ada masalah untuk memiliki kompiler menghasilkan metadata ini dari kode itu sendiri. Bahasa Java dan .NET melakukan ini secara normal.
Jadi tidak. File header tidak bagus. Itu ketika kita masih harus memiliki kompiler dan linker pada disket terpisah dan kompilasi memakan waktu 30 menit. Saat ini, mereka hanya menghalangi dan merupakan tanda dari desain yang buruk.
sumber
Meskipun mereka mungkin berguna bagi Anda sebagai bentuk dokumentasi, sistem yang mengelilingi file header sangat tidak efisien.
C dirancang sehingga setiap pass kompilasi membangun satu modul tunggal; setiap file sumber dikompilasi dalam menjalankan terpisah dari kompiler. File header, di sisi lain, disuntikkan ke langkah kompilasi untuk masing-masing file sumber yang mereferensikannya.
Ini berarti bahwa jika file header Anda termasuk dalam 300 file sumber, maka file tersebut akan diuraikan dan dikompilasi berulang-ulang, 300 kali terpisah saat program Anda dibuat. Hal yang persis sama dengan hasil yang sama persis, berulang-ulang.Ini sangat membuang waktu, dan merupakan salah satu alasan utama mengapa program C dan C ++ membutuhkan waktu lama untuk dibangun.
Semua bahasa modern sengaja menghindari inefisiensi kecil yang absurd ini. Alih-alih, biasanya dalam bahasa yang dikompilasi, metadata yang diperlukan disimpan dalam output build, memungkinkan file yang dikompilasi untuk bertindak sebagai semacam referensi pencarian cepat yang menjelaskan apa yang terkandung dalam file yang dikompilasi. Semua manfaat file header, secara otomatis dibuat tanpa ada pekerjaan tambahan di pihak Anda.
Bergantian dalam bahasa yang ditafsirkan, setiap modul yang dimuat akan tetap tersimpan dalam memori. Merujuk atau memasukkan atau membutuhkan pustaka akan membaca dan menyusun kode sumber terkait, yang tetap penduduk sampai program berakhir. Jika Anda juga memerlukannya di tempat lain, tidak ada pekerjaan tambahan karena sudah dimuat.
Dalam kedua kasus tersebut, Anda dapat "menelusuri" data yang dibuat oleh langkah ini menggunakan alat bahasa. Biasanya IDE akan memiliki semacam browser kelas. Dan jika bahasa tersebut memiliki REPL, itu juga dapat sering digunakan untuk menghasilkan ringkasan dokumentasi dari setiap objek yang dimuat.
sumber
Tidak jelas, apa yang Anda maksud dengan menelusuri file untuk fungsi dan anggota data. Namun, sebagian besar IDE menyediakan Alat untuk menjelajah kelas dan melihat anggota data kelas.
Misalnya: Visual Studio telah
Class View
danObject browser
dengan baik menyediakan fungsionalitas yang Anda minta. Seperti di cuplikan layar berikut.sumber
Kerugian tambahan dari file header adalah bahwa program tergantung pada urutan penyertaannya, dan programmer harus mengambil langkah-langkah tambahan untuk memastikan kebenaran.
Itu, ditambah dengan sistem makro C (diwarisi oleh C ++), menyebabkan banyak jebakan dan situasi membingungkan.
Sebagai ilustrasi, jika satu tajuk mendefinisikan beberapa simbol menggunakan makro untuk penggunaannya, dan tajuk lainnya menggunakan simbol dengan cara lain seperti nama untuk suatu fungsi, maka urutan inklusi akan sangat mempengaruhi hasil akhir. Ada banyak contoh seperti itu.
sumber
Saya selalu menyukai file header karena mereka menyediakan bentuk antarmuka untuk implementasi, bersama dengan beberapa informasi tambahan seperti variabel kelas, semua dalam satu file yang mudah dilihat.
Saya melihat banyak kode C # (yang tidak perlu 2 file per kelas) ditulis menggunakan 2 file per kelas - satu implementasi kelas aktual, dan satu lagi dengan antarmuka di dalamnya. Desain ini baik untuk mengejek (penting dalam beberapa sistem) dan membantu untuk mendefinisikan dokumentasi kelas tanpa harus menggunakan IDE untuk melihat metadata yang dikompilasi. Sejauh ini saya akan mengatakan praktik yang baik.
Jadi C / C ++ mandat setara (dari macam) antarmuka dalam file header adalah hal yang baik.
Saya tahu ada pendukung sistem lain yang tidak menyukai mereka karena alasan termasuk 'lebih sulit untuk hanya meretas kode jika Anda harus meletakkan sesuatu dalam 2 file', tetapi sikap saya adalah bahwa hanya meretas kode bukan praktik yang baik pula , dan begitu Anda mulai menulis / mendesain kode dengan sedikit lebih banyak pemikiran, maka Anda akan mendefinisikan header / antarmuka sebagai hal yang biasa.
sumber
Saya benar-benar akan mengatakan bahwa file header tidak bagus karena mereka memperkeruh antarmuka dan implementasi. Maksud dengan pemrograman pada umumnya, dan terutama OOP adalah untuk memiliki antarmuka yang ditentukan dan menyembunyikan detail implementasi, tetapi file header C ++ menunjukkan kepada Anda metode, warisan, dan anggota publik (antarmuka) serta metode pribadi dan anggota pribadi (beberapa bagian dari implementasi). Belum lagi dalam beberapa kasus Anda pada akhirnya memasukkan kode atau konstruktor dalam file header, dan beberapa perpustakaan menyertakan kode template dalam header, yang benar-benar memadukan implementasi dengan antarmuka.
Maksud asli, saya percaya, adalah untuk memungkinkan kode menggunakan perpustakaan lain, objek, dll tanpa harus mengimpor seluruh isi skrip. Yang Anda butuhkan adalah tajuk untuk dikompilasi dan ditautkan. Menghemat waktu dan siklus dengan cara itu. Dalam hal itu, itu ide yang baik, tetapi itu hanya satu cara untuk menyelesaikan masalah ini.
Adapun untuk menelusuri struktur program, sebagian besar IDE menyediakan kemampuan itu, dan ada banyak alat yang akan menendang keluar antarmuka, melakukan analisis kode, dekompilasi, dll sehingga Anda dapat melihat apa yang terjadi di bawah selimut.
Adapun mengapa bahasa lain tidak menerapkan fitur yang sama? Ya, karena bahasa lain berasal dari orang lain, dan para desainer / pencipta tersebut memiliki visi yang berbeda tentang bagaimana segala sesuatu harus bekerja.
Jawaban terbaik adalah tetap dengan apa pekerjaan yang perlu Anda lakukan, dan membuat Anda bahagia.
sumber
Dalam banyak bahasa pemrograman, ketika suatu program dibagi lagi menjadi beberapa unit kompilasi, kode dalam satu unit hanya akan dapat menggunakan hal-hal yang didefinisikan dalam unit lain jika kompiler memiliki beberapa cara untuk mengetahui apa saja itu. Daripada mengharuskan kompilator memproses satu unit kompilasi memeriksa seluruh teks dari setiap unit kompilasi yang mendefinisikan apa pun yang digunakan dalam unit ini, yang terbaik adalah menerima kompiler, sambil memproses setiap unit, teks lengkap dari unit yang akan dikompilasi bersama dengan sedikit informasi dari yang lain.
Di C, programmer bertanggung jawab untuk membuat dua file untuk setiap unit - satu berisi informasi yang hanya akan diperlukan ketika mengkompilasi unit itu, dan satu berisi informasi yang juga akan diperlukan ketika menyusun unit lainnya. Ini adalah desain yang agak jahat, hacky, tapi itu menghindari kebutuhan untuk memiliki standar bahasa menentukan apa pun tentang bagaimana kompiler harus menghasilkan dan memproses file perantara. Banyak bahasa lain menggunakan pendekatan yang berbeda, di mana kompiler akan menghasilkan dari masing-masing file sumber file perantara yang menggambarkan segala sesuatu dalam file sumber yang seharusnya dapat diakses oleh kode luar. Pendekatan ini menghindari perlunya memiliki informasi duplikat dalam dua file sumber, tetapi mengharuskan platform kompilasi telah mendefinisikan semantik file dengan cara yang tidak diperlukan untuk C.
sumber