Proyek dan path

Mengelola berkas proyek MATLAB dan jalur pencarian path agar kode tetap terorganisasi.

Daftar isi

Program yang tumbuh akan berubah dari satu berkas menjadi belasan berkas, dan pada titik itu letak berkas menentukan apakah kode dapat ditemukan oleh MATLAB. Topik ini membahas jalur pencarian path yang menentukan urutan pencarian berkas serta pengelolaan path dengan addpath, rmpath, savepath, dan genpath. Bagian lain membahas bahaya bayangan nama ketika dua fungsi bernama sama, struktur direktori proyek yang rapi, serta gambaran ringkas fitur proyek MATLAB. Seluruh contoh membangun struktur folder kecil yang bersifat sementara lalu membersihkannya sendiri, sehingga dapat dijalankan tanpa menyisakan apa pun di disk.

Jalur pencarian path#

Path adalah daftar folder yang ditelusuri MATLAB ketika sebuah nama fungsi dipanggil. Pencarian berlangsung berurutan: folder kerja saat ini lebih dahulu, lalu folder-folder pada path sesuai urutannya. Berkas .m pertama yang bernama sama dengan fungsi yang dipanggil menjadi yang dieksekusi. Fungsi which melaporkan berkas mana yang terpilih, sehingga perilaku program yang memanggil fungsi milik proyek selalu dapat diperiksa ke sumbernya.

matlab addpath, which, dan rmpath pada folder sementara
direktoriUji = 'folderUjiPath';
mkdir(direktoriUji);
fid = fopen(fullfile(direktoriUji, 'konversiSuhu.m'), 'w');
fprintf(fid, 'function c = konversiSuhu(f)\nc = (f - 32) * 5 / 9;\nend\n');
fclose(fid);
fprintf('sebelum addpath: %d\n', isempty(which('konversiSuhu')));
addpath(direktoriUji);
lokasiDitemukan = which('konversiSuhu');
fprintf('ditemukan di folder uji: %d\n', strcmpi(lokasiDitemukan, fullfile(pwd, direktoriUji, 'konversiSuhu.m')));
rmpath(direktoriUji);
fprintf('setelah rmpath: %d\n', isempty(which('konversiSuhu')));
rmdir(direktoriUji, 's');
text Keluaran
sebelum addpath: 1
ditemukan di folder uji: 1
setelah rmpath: 1

Sebelum addpath, which tidak menemukan apa pun sehingga uji kekosongannya bernilai satu. Setelah folder didaftarkan, berkas ditemukan tepat di folder uji itu, dan setelah rmpath nama tersebut hilang kembali dari jangkauan pencarian. Perintah addpath menempatkan folder di depan daftar, dan rmpath mengeluarkannya tanpa menyentuh folder lain.

Path yang diatur dengan addpath hanya hidup selama sesi berjalan. Perintah savepath menuliskan isi path saat ini ke sebuah berkas sehingga pengaturan itu dipakai kembali pada sesi berikutnya. Demonstrasi berikut menyimpan path ke berkas di dalam folder sementara, bukan ke berkas konfigurasi pengguna, lalu membersihkan foldernya.

matlab savepath menuliskan path ke berkas
direktoriUji = 'folderUjiPath';
mkdir(direktoriUji);
statusSimpan = savepath(fullfile(direktoriUji, 'pathCadangan.m'));
fprintf('status simpan: %d\n', statusSimpan);
fprintf('berkas path tersimpan: %d\n', exist(fullfile(direktoriUji, 'pathCadangan.m'), 'file'));
rmdir(direktoriUji, 's');
text Keluaran
status simpan: 0
berkas path tersimpan: 2

Nilai balik savepath adalah nol ketika penyimpanan berhasil, dan pemeriksaan exist dengan jenis 'file' bernilai dua karena berkas cadangan itu benar-benar tercipta sebelum foldernya dibersihkan. Dalam pemakaian sehari-hari, savepath cukup dipanggil sekali setelah struktur folder proyek didaftarkan, dan pemanggilan tanpa argumen menuliskan konfigurasi pengguna sehingga path proyek otomatis siap setiap MATLAB dijalankan.

genpath untuk seluruh subdirektori#

Proyek jarang berbentuk satu folder datar, dan mendaftarkan tiap subfolder satu per satu menjadi pekerjaan yang menjemukan. Fungsi genpath merangkai satu folder beserta seluruh subfoldernya menjadi satu daftar path yang dapat diserahkan langsung ke addpath, sehingga satu perintah cukup untuk mendaftarkan seluruh pohon proyek.

matlab genpath merangkai folder beserta subfoldernya
folderUji = 'proyekSuhu';
mkdir(fullfile(folderUji, 'data'));
mkdir(fullfile(folderUji, 'fungsi'));
mkdir(fullfile(folderUji, 'skrip'));
daftarFolder = strsplit(genpath(folderUji), pathsep);
fprintf('folder di genpath: %d\n', numel(daftarFolder));
for k = 1:numel(daftarFolder)
  [~, namaFolder] = fileparts(daftarFolder{k});
  fprintf('entri %d: %s\n', k, namaFolder);
end
rmdir(fullfile(folderUji, 'data'), 's');
rmdir(fullfile(folderUji, 'fungsi'), 's');
rmdir(fullfile(folderUji, 'skrip'), 's');
rmdir(folderUji, 's');
text Keluaran
folder di genpath: 4
entri 1: proyekSuhu
entri 2: data
entri 3: fungsi
entri 4: skrip

Satu folder induk dengan tiga subfolder menghasilkan empat entri path, dan pemisah antar entri diambil dari konstanta pathsep agar kode tetap benar di sistem operasi mana pun. Keluaran genpath berupa satu teks yang memuat seluruh folder, sehingga contoh menggunakan strsplit untuk memisahkannya menjadi daftar entri. Dalam pemakaian nyata, bentuk lengkapnya adalah addpath(genpath('proyekSuhu')) pada awal skrip utama, dan pencabutannya rmpath(genpath('proyekSuhu')). Subfolder yang tidak perlu didaftarkan, misalnya folder hasil sementara, cukup dilewati dengan mendaftarkan folder pilihan satu per satu. Cakupan seluas itu juga membawa seluruh nama fungsi ke path sekaligus, sehingga dua fungsi bernama sama pada pohon proyek dapat terdaftar bersama tanpa sengaja.

Bayangan nama dan urutan pencarian#

Dua fungsi bernama sama pada dua folder yang sama-sama terdaftar di path saling menindih, dan yang menang adalah folder dengan posisi lebih depan. Kondisi ini disebut bayangan nama (shadowing), dan bahayanya bukan error melainkan hasil yang salah tanpa peringatan, karena fungsi yang kalah tidak pernah dipanggil sama sekali.

matlab Bayangan nama: dua fungsi bernama sama
folderA = 'folderAlat';
folderB = 'folderAlatLain';
mkdir(folderA);
mkdir(folderB);
fid = fopen(fullfile(folderA, 'hitungRata.m'), 'w');
fprintf(fid, 'function y = hitungRata(x)\ny = sum(x) / numel(x);\nend\n');
fclose(fid);
fid = fopen(fullfile(folderB, 'hitungRata.m'), 'w');
fprintf(fid, 'function y = hitungRata(x)\ny = median(x);\nend\n');
fclose(fid);
addpath(folderA);
addpath(folderB);
lokasiBerganda = which('hitungRata');
fprintf('yang terpilih folderB: %d\n', strcmpi(lokasiBerganda, fullfile(pwd, folderB, 'hitungRata.m')));
rmpath(folderB);
lokasiSetelah = which('hitungRata');
fprintf('setelah rmpath, folderA: %d\n', strcmpi(lokasiSetelah, fullfile(pwd, folderA, 'hitungRata.m')));
rmpath(folderA);
rmdir(folderA, 's');
rmdir(folderB, 's');
text Keluaran
yang terpilih folderB: 1
setelah rmpath, folderA: 1

Kedua berkas memuat fungsi hitungRata yang berbeda isiannya, satu menghitung rerata aritmetik dan satu menghitung median. Karena addpath menempatkan folder di depan, folder yang didaftarkan terakhir menang, dan begitu folder itu dikeluarkan, giliran folder pertama yang terpilih tanpa satu baris kode pun berubah pada pemanggilnya. Perintah which hitungRata -all pada MATLAB mencantumkan seluruh kandidat sekaligus sehingga bayangan nama terungkap sebelum menimbulkan salah hitung.

Struktur direktori proyek yang rapi#

Struktur yang rapi memisahkan berkas menurut perannya: data mentah pada data/, fungsi pada fungsi/, dan skrip pemanggil pada skrip/. Pemisahan ini bukan urusan selera, karena ketiganya berubah dengan ritme yang berbeda: data bertambah setiap pencatatan, fungsi bertambah ketika analisis baru dirancang, dan skrip berganti ketika pertanyaan terhadap data berganti. Diagram berikut memperlihatkan bentuk lengkapnya.

proyekSuhu/data/fungsi/skrip/catatanSuhu.csvkalibrasi.matkonversiSuhu.mrerataBergerak.manalisisHarian.mujiKonversi.m
Struktur direktori proyek dengan tiga kelompok berkas

Dengan struktur itu, satu perintah addpath(genpath('proyekSuhu')) di bagian atas skrip utama menyiapkan seluruh fungsi, dan folder data/ tetap bersih dari berkas kode sehingga pencadangan cukup menyalin satu folder. Skrip pada skrip/ menjadi pintu masuk yang tipis: skrip menyiapkan data, memanggil fungsi, lalu menampilkan hasil, sementara seluruh perhitungan hidup di fungsi/ dan dapat diuji terpisah. Berkas uji seperti ujiKonversi.m ikut berada pada skrip/ sebagai pintu masuk ringan untuk memeriksa satu fungsi sebelum dipakai analisis penuh. Nama folder yang singkat menjaga perintah addpath tetap pendek, dan penamaan berkas di dalamnya mengikuti nama fungsi yang dibawanya.

Proyek MATLAB sebagai konsep#

MATLAB menyediakan fitur proyek yang membungkus pengelolaan ini menjadi satu kesatuan. Berkas ber-ekstensi .prj menyimpan daftar berkas milik proyek, panel Project menampilkan pohonnya, dan analisis kebergantungan melacak fungsi mana yang dipanggil oleh skrip mana. Karena kebergantungan terlacak, pemindahan berkas tidak memutus rujukan. Proyek juga menyediakan berkas jalankan-awal yang menyiapkan path secara otomatis, dan label kategori untuk menandai status tiap berkas.

matlab MATLAB: API proyek untuk mendaftar berkas
% tidak-dijalankan
% API matlab.project hanya tersedia di MATLAB, tidak di GNU Octave.
proyek = matlab.project.loadProject('analisisSuhu');
fprintf('banyak berkas di proyek: %d\n', numel(proyek.Files));

Fitur proyek menambah kenyamanan, bukan mekanisme baru: yang dikelolanya tetap daftar berkas dan path. Proyek juga dapat dihubungkan dengan alat kontrol versi seperti Git sehingga perubahan berkas terlacak bersama kodenya. Proyek kecil hingga menengah berjalan baik dengan struktur folder polos dan satu addpath(genpath(...)). Fitur proyek menjadi berharga ketika berkas bertambah ratusan, beberapa versi kode hidup bersamaan, atau berkas harus dibagi dengan tim. Kedua pilihan itu dapat digunakan tanpa mengubah isi fungsi maupun skrip yang sudah ditulis.

Kesalahan umum#

  • Membiarkan dua fungsi bernama sama pada dua folder terdaftar. Fungsi yang kalah tidak pernah dipanggil dan tidak ada error yang menyertainya, sehingga gejalanya hanya hasil yang salah. Periksa dengan which setiap kali folder baru masuk path, dan hapus salah satu berkas atau ganti namanya.
  • Menyebarkan addpath di banyak skrip. Ketika tiap skrip mendaftarkan foldernya sendiri, urutan path bergantung pada skrip yang terakhir dijalankan, dan pemanggilan fungsi menjadi tidak menentu. Kumpulkan pendaftaran path pada satu tempat, misalnya awal skrip utama atau berkas jalankan-awal.
  • Menyimpan path absolut lintas mesin. Nama seperti /home/nama/proyek/fungsi hanya berlaku pada satu komputer, sehingga kode gagal menemukan fungsinya saat dipindah. Gunakan path relatif yang dihitung dari lokasi skrip itu sendiri, misalnya lewat fileparts(mfilename('fullpath')) sebagai folder dasar addpath.

Ringkasan#

  • Path adalah daftar folder yang dicari berurutan, folder kerja lebih dahulu, dan which melaporkan berkas yang terpilih.
  • addpath, rmpath, savepath, dan genpath mengelola pendaftaran folder, dengan genpath merangkai satu folder beserta seluruh subfoldernya.
  • Bayangan nama membuat fungsi yang kalah tidak pernah dipanggil tanpa memunculkan error, sehingga pemeriksaan which menjadi kebiasaan wajib.
  • Struktur data/, fungsi/, dan skrip/ memisahkan berkas menurut ritme perubahannya, dan fitur proyek MATLAB mengelola hal yang sama pada skala lebih besar.

Referensi#