Proyek yang berjalan baik belum tentu nyaman dipakai, karena pengguna baru menghadapi pertanyaan yang tidak terjawab oleh kode saja: berkas mana yang dijalankan, parameter apa yang boleh diganti, dan bagaimana membaca hasilnya. Topik ini membahas prinsip logika di fungsi murni dengan antarmuka yang tipis, fungsi prediksi ulang prediksi_suhu dengan parameter bebas, serta fungsi laporan_termal yang mencetak ringkasan terformat. Pembungkus GUI uifigure dibangun sebagai lapisan tipis, dan dokumentasi proyek berupa teks help serta README melengkapi aplikasi. Setelah membaca topik ini, proyek menjadi aplikasi ringkas yang dapat dioperasikan dan dipahami tanpa membaca isi fungsinya.
Logika di fungsi murni, antarmuka tipis#
Aplikasi yang tertata menempatkan logika pada fungsi murni dan menjadikan antarmuka lapisan yang setipis mungkin. Fungsi murni menerima nilai, menghitung, lalu mengembalikan nilai tanpa membaca atau menulis keadaan di luar argumennya, sehingga dapat diuji dengan panggilan biasa dari Command Window. Antarmuka, baik berupa laporan teks maupun GUI, hanya membaca masukan, memanggil fungsi inti, lalu menampilkan keluarannya. Konsekuensinya ketat: antarmuka tidak memuat satu rumus pun, sebab setiap rumus yang berpindah ke antarmuka menjadi salinan kedua yang lambat laun berlainan dengan aslinya.
Fungsi inti proyek ini telah tersedia sejak tahap implementasi. Blok berikut memuat kembali data pengukuran lalu menjalankan fit_termal untuk memastikan seluruh angkanya masih sama sebelum pembungkus dibangun di atasnya.
% muat data dan sesuaikan model seperti pada tahap implementasi
M = csvread('data-suhu.csv');
t = M(:, 1);
T = M(:, 2);
hasil = fit_termal(t, T);
fprintf('T_aset : %.2f derajat\n', hasil.T_aset);
fprintf('T_awal : %.2f derajat\n', hasil.T_awal);
fprintf('tau : %.2f detik\n', hasil.tau);
fprintf('RMS : %.4f derajat\n', hasil.rms);T_aset : 85.00 derajat
T_awal : 25.40 derajat
tau : 30.10 detik
RMS : 0.1888 derajatKeempat angka itu sama dengan hasil skrip utama pada tahap implementasi, yang berarti fungsi inti tidak disentuh ketika antarmuka ditambahkan. Seluruh penyempurnaan pada topik ini hanya menambahkan lapisan baru di atas fungsi yang telah teruji. Setiap lapisan baru dapat diperiksa dengan membandingkan angkanya terhadap lapisan yang sudah ada.
Fungsi prediksi ulang dengan parameter#
Skrip utama menghitung waktu ambang dengan rumus yang ditulis langsung di dalamnya. Sekarang rumus itu diangkat menjadi fungsi tersendiri agar prediksi dapat diulang dengan parameter apa pun, termasuk parameter yang bukan hasil fit. Penurunannya satu langkah: samakan bentuk model dengan suhu ambang, lalu ambil logaritma alami kedua ruasnya,
sehingga waktu menjadi fungsi eksplisit dari keempat parameter tanpa perulangan dan tanpa pemecah numerik.
function t_ambang = prediksi_suhu(tau, T_aset, T_awal, ambang)
% PREDIKSI_SUHU menghitung waktu model mencapai suhu ambang.
% t_ambang = PREDIKSI_SUHU(tau, T_aset, T_awal, ambang) menyelesaikan
% T_aset - (T_aset - T_awal) * exp(-t/tau) = ambang
% secara eksplisit menjadi
% t_ambang = tau * log((T_aset - T_awal) / (T_aset - ambang)).
% Nilai NaN dikembalikan bila ambang berada di luar jangkauan
% T_awal sampai T_aset karena model tidak pernah menyentuhnya.
% Tanpa argumen, parameter contoh model dipakai.
if nargin < 4
tau = 30;
T_aset = 85;
T_awal = 25;
ambang = 80;
end
if ambang >= T_aset || ambang <= T_awal
t_ambang = NaN;
else
t_ambang = tau * log((T_aset - T_awal) / (T_aset - ambang));
end
endFungsi ini memeriksa jangkauan ambang sebelum menghitung. Ambang yang berada di atas tidak pernah dicapai model, dan ambang yang berada di bawah telah terlewati sejak awal, sehingga keduanya dikembalikan sebagai NaN alih-alih angka karangan. Pemanggilan berikut menguji fungsi itu dengan parameter hasil fit, satu skenario parameter lain, dan satu ambang yang di luar jangkauan.
% siapkan kembali hasil fit dari data pengukuran
M = csvread('data-suhu.csv');
hasil = fit_termal(M(:, 1), M(:, 2));
% prediksi ulang memakai parameter hasil fit
fprintf('waktu ke 80 derajat : %.2f detik\n', ...
prediksi_suhu(hasil.tau, hasil.T_aset, hasil.T_awal, 80));
fprintf('waktu ke 82 derajat : %.2f detik\n', ...
prediksi_suhu(hasil.tau, hasil.T_aset, hasil.T_awal, 82));
% skenario ulang: pemanas dengan konstanta waktu lebih besar
fprintf('waktu ke 80 derajat (tau 60) : %.2f detik\n', prediksi_suhu(60, 85, 25, 80));
% ambang di luar jangkauan model dikembalikan sebagai NaN
fprintf('waktu ke 90 derajat : %.2f\n', ...
prediksi_suhu(hasil.tau, hasil.T_aset, hasil.T_awal, 90));waktu ke 80 derajat : 74.58 detik
waktu ke 82 derajat : 89.96 detik
waktu ke 80 derajat (tau 60) : 149.09 detik
waktu ke 90 derajat : NaNWaktu ke 80 derajat bernilai 74.58 detik, sama dengan hasil rumus pada skrip utama, sehingga pengangkatan rumus ke fungsi tidak mengubah satu angka pun. Skenario dengan detik menghasilkan 149.09 detik dan menegaskan bahwa parameternya benar-benar bebas dipakai untuk alat pemanas lain yang lebih lambat. Ambang 90 derajat menghasilkan NaN karena berada di atas sebesar 85 derajat, dan fungsi memilih menolak daripada menghasilkan waktu yang seolah meyakinkan.
Laporan terformat ke layar#
Antarmuka pertama yang tereksekusi pada lingkungan verifikasi jalur ini adalah laporan teks. Fungsi laporan_termal menerima struktur hasil fit_termal, mencetak parameter beserta error RMS, lalu menambahkan waktu mencapai ambang dengan memanggil prediksi_suhu. Laporan tidak menghitung ulang apa pun dari data, sehingga seluruh angkanya berasal dari satu sumber yang sama.
function laporan_termal(hasil, ambang)
% LAPORAN_TERMAL mencetak ringkasan analisis respon termal.
% LAPORAN_TERMAL(hasil) menampilkan parameter model, error RMS, dan
% waktu mencapai ambang 80 derajat dari struktur hasil FIT_TERMAL.
% LAPORAN_TERMAL(hasil, ambang) memakai ambang sendiri.
% Struktur hasil minimal memuat bidang T_aset, T_awal, tau, dan rms.
% Tanpa argumen, struktur contoh model dipakai.
if nargin < 2
ambang = 80;
end
if nargin < 1
hasil.T_aset = 85;
hasil.T_awal = 25;
hasil.tau = 30;
hasil.rms = 0.19;
end
t_ambang = prediksi_suhu(hasil.tau, hasil.T_aset, hasil.T_awal, ambang);
fprintf('== laporan analisis respon termal ==\n');
fprintf('T_aset : %6.2f derajat\n', hasil.T_aset);
fprintf('T_awal : %6.2f derajat\n', hasil.T_awal);
fprintf('tau : %6.2f detik\n', hasil.tau);
fprintf('RMS : %6.4f derajat\n', hasil.rms);
fprintf('waktu mencapai %.1f derajat : %.2f detik\n', ambang, t_ambang);
endFormat %6.2f memberi setiap kolom lebar tetap sehingga angka sejajar rapi pada laporan yang lebih panjang. Judul bagian diberi penanda == agar ringkasan mudah ditemukan di antara keluaran lain. Pemanggilan berikut menyusun laporan dari hasil fit yang sama seperti sebelumnya.
% susun laporan dari hasil fit yang sama
M = csvread('data-suhu.csv');
hasil = fit_termal(M(:, 1), M(:, 2));
laporan_termal(hasil);== laporan analisis respon termal ==
T_aset : 85.00 derajat
T_awal : 25.40 derajat
tau : 30.10 detik
RMS : 0.1888 derajat
waktu mencapai 80.0 derajat : 74.58 detikKelima baris laporan itu merangkum seluruh hasil proyek bagi pengguna yang tidak membuka figur. Seluruh angkanya konsisten dengan kedua topik sebelumnya karena bersumber dari fungsi yang sama. Ambang laporan dapat diganti melalui argumen kedua, misalnya laporan_termal(hasil, 82), karena nilainya hanya diteruskan ke prediksi_suhu.
Pembungkus GUI sebagai lapisan tipis#
Antarmuka kedua adalah GUI programatik yang memakai uifigure beserta komponennya. Empat kolom isian memuat parameter model dan ambang, satu tombol memicu perhitungan, dan satu label menampilkan hasilnya. Strukturnya mengikuti pola GUI programatik: seluruh komponen dibuat dari kode, handle disimpan pada struktur h, dan callback dipasang pada properti ButtonPushedFcn.
% tidak-dijalankan
% pembungkus GUI: antarmuka tipis di atas fungsi inti prediksi_suhu
h.Jendela = uifigure('Name', 'Prediksi respon termal', ...
'Position', [100 100 360 300]);
h.LabelTau = uilabel(h.Jendela);
h.LabelTau.Text = 'tau (detik)';
h.LabelTau.Position = [40 250 130 22];
h.Tau = uieditfield(h.Jendela, 'text');
h.Tau.Position = [180 250 120 24];
h.Tau.Value = '30.10';
h.LabelTaset = uilabel(h.Jendela);
h.LabelTaset.Text = 'T_aset (derajat)';
h.LabelTaset.Position = [40 210 130 22];
h.Taset = uieditfield(h.Jendela, 'text');
h.Taset.Position = [180 210 120 24];
h.Taset.Value = '85';
h.LabelTawal = uilabel(h.Jendela);
h.LabelTawal.Text = 'T_awal (derajat)';
h.LabelTawal.Position = [40 170 130 22];
h.Tawal = uieditfield(h.Jendela, 'text');
h.Tawal.Position = [180 170 120 24];
h.Tawal.Value = '25.40';
h.LabelAmbang = uilabel(h.Jendela);
h.LabelAmbang.Text = 'ambang (derajat)';
h.LabelAmbang.Position = [40 130 130 22];
h.Ambang = uieditfield(h.Jendela, 'text');
h.Ambang.Position = [180 130 120 24];
h.Ambang.Value = '80';
h.Tombol = uibutton(h.Jendela, 'push');
h.Tombol.Text = 'Hitung waktu';
h.Tombol.Position = [180 90 120 26];
h.Tombol.ButtonPushedFcn = @(sumber, peristiwa) tombol_ditekan(sumber, peristiwa, h);
h.LabelHasil = uilabel(h.Jendela);
h.LabelHasil.Text = 'hasil tampil di sini';
h.LabelHasil.Position = [40 40 280 22];
function tombol_ditekan(sumber, peristiwa, h)
tau = str2double(h.Tau.Value);
T_aset = str2double(h.Taset.Value);
T_awal = str2double(h.Tawal.Value);
ambang = str2double(h.Ambang.Value);
if any(isnan([tau, T_aset, T_awal, ambang]))
h.LabelHasil.Text = 'masukan tidak terbaca sebagai bilangan';
return;
end
t_ambang = prediksi_suhu(tau, T_aset, T_awal, ambang);
if isnan(t_ambang)
h.LabelHasil.Text = 'ambang di luar jangkauan model';
else
h.LabelHasil.Text = sprintf('waktu : %.2f detik', t_ambang);
end
endCallback tombol_ditekan memperlihatkan batas kerja antarmuka. Ia membaca empat kolom isian, mengubah teksnya dengan str2double, menolak NaN yang lahir dari teks yang gagal terbaca, memanggil prediksi_suhu, lalu menulis hasilnya ke label. Tidak ada satu rumus model di dalamnya, sehingga perubahan model hanya terjadi di fungsi inti dan GUI otomatis mengikuti tanpa disunting. Nilai awal kolom isian diisi parameter hasil fit agar pengguna yang hanya menekan tombol tetap memperoleh hasil yang bermakna.
Dokumentasi: teks help dan README#
Setiap fungsi proyek membawa teks help-nya sendiri pada blok komentar pertama berkasnya, dan baris pertama blok itu menjadi ringkasan satu baris yang ditampilkan perintah lookfor. Teks help ditulis untuk dibaca dari Command Window tanpa membuka berkasnya, memuat bentuk pemanggilan, makna tiap argumen, dan isi struktur yang dikembalikan. Perintah berikut menampilkan teks help fungsi fit_termal langsung dari folder proyek.
# tampilkan teks help fungsi fit_termal dari folder proyek
octave --quiet --eval "help fit_termal" 2>/dev/null'fit_termal' is a function from the file /home/kal/my-project/content/matlab/pengerjaan-proyek/penyempurnaan-aplikasi/fit_termal.m
FIT_TERMAL menyesuaikan model pemanasan orde satu pada data suhu.
hasil = FIT_TERMAL(t, T) mencari parameter model
T(t) = T_aset - (T_aset - T_awal) * exp(-t/tau)
dengan menguji daftar kandidat T_aset tetap lalu regresi linear
pada ln(T_aset - T) terhadap t memakai operator backslash.
Kandidat dengan error RMS terkecil dipilih.
hasil = FIT_TERMAL(t, T, kandidat) memakai daftar kandidat sendiri.
Struktur hasil memuat bidang T_aset, T_awal, tau, rms, T_model,
kandidat, tau_kandidat, dan rms_kandidat.
Tanpa argumen, data contoh pemanasan logam dipakai.
Additional help for built-in functions and operators is
available in the online version of the manual. Use the command
'doc <topic>' to search the manual index.
Help and information about Octave is also available on the WWW
at https://www.octave.org and via the [email protected]
mailing list.Selain teks help, folder proyek dilengkapi README yang ditulis untuk pengguna yang belum membaca kode. Isi README terdiri atas tiga bagian: cara menjalankan, daftar berkas beserta perannya, serta kriteria mutu yang telah dipenuhi beserta angkanya. Bagian cara menjalankan memuat dua langkah: menjalankan analisis_termal.m dari folder proyek untuk analisis lengkap, lalu memanggil laporan_termal(hasil) bila ringkasan diperlukan. Urutan bagian mengikuti urutan pertanyaan pengguna baru, sehingga orang yang baru menerima folder proyek dapat menghasilkan angka pertamanya tanpa membuka satu fungsi pun. Susunan lengkap folder proyek tampak pada diagram berikut.
Folder yang lengkap seperti itu dapat disalin ke komputer lain dan langsung berjalan, karena seluruh kebergantungannya adalah berkas .m dan berkas data yang berada satu folder. Pemisahan peran pada diagram juga menjadi peta pemeliharaan: pertanyaan tentang data menuju data-suhu.csv, pertanyaan tentang rumus menuju tiga fungsi, dan pertanyaan tentang alur menuju satu skrip.
Kesalahan umum#
- Menyalin rumus ke dalam callback atau laporan. Penyebabnya rumus terasa pendek sehingga terasa ringan untuk ditulis ulang. Akibatnya terdapat dua salinan rumus yang berlainan antara fungsi inti dan antarmuka, dan hasil GUI meleset dari hasil skrip tanpa error. Perbaikannya memanggil fungsi inti dari antarmuka, seperti
laporan_termalyang memanggilprediksi_suhu. - Membiarkan teks help menyimpang dari perilaku fungsi. Penyebabnya argumen atau bidang struktur berubah tanpa menyunting komentar. Akibatnya pengguna baru mengikuti dokumentasi yang keliru dan menyalahkan fungsinya. Perbaikannya menyunting teks help pada saat yang sama dengan mengubah daftar argumen, karena keduanya berada pada satu berkas.
- Membiarkan NaN dari kolom isian mengalir ke fungsi inti. Penyebabnya
str2doublemengubah teks yang gagal menjadi NaN secara diam-diam. Akibatnya laporan GUI menampilkan waktu NaN atau error yang tidak menjelaskan kolom mana yang salah. Perbaikannya memeriksaisnanpada seluruh masukan sebelum memanggil fungsi inti, seperti pada callback di atas.
Ringkasan#
- Aplikasi yang tertata menempatkan logika pada fungsi murni dan menjadikan antarmuka lapisan tipis yang hanya membaca masukan, memanggil fungsi inti, lalu menampilkan keluaran.
prediksi_suhumenghitung waktu ambang secara eksplisit dari empat parameter dan mengembalikan NaN untuk ambang yang berada di luar jangkauan model.laporan_termalmencetak ringkasan terformat dari struktur hasil tanpa menghitung ulang, dan pembungkus GUIuifigurememanggil fungsi inti yang sama tanpa memuat rumus.- Dokumentasi proyek terdiri atas teks help pada tiap fungsi yang tampil lewat perintah
help, README untuk pengguna baru, serta struktur folder yang perannya terpisah.
Referensi#
- help — MathWorks — Rujukan resmi perintah help beserta penulisan teks help pada berkas fungsi.
- uifigure — MathWorks — Rujukan resmi pembuatan jendela aplikasi untuk pembungkus GUI.
- uieditfield — MathWorks — Rujukan resmi komponen kolom isian yang dipakai pembungkus GUI.