Saya mengerjakan proyek dalam delphi dan saya membuat installer untuk aplikasi, ada Tiga bagian utama.
- Instalasi / penghapusan instalasi PostgreSQL
- myapplication (setup myapplication dibuat menggunakan instalasi / uninstall nsi).
- Membuat tabel di Postgres melalui skrip (file batch).
Setiap hal berjalan dengan baik dan lancar, tetapi jika sesuatu gagal saya telah membuat LogToFileger yang akan LogToFile setiap langkah proses,
seperti ini
LogToFileToFile.LogToFile('[DatabaseInstallation] : [ACTION]:Postgres installation started');
Fungsi LogToFileToFile.LogToFile()
Ini akan menulis konten ke file. Ini berfungsi dengan baik, tetapi masalahnya adalah ini telah mengacaukan kode karena di dalamnya menjadi sulit untuk membaca kode karena satu ca hanya melihat LogToFileToFile.LogToFile()
fungsi panggilan di mana-mana dalam kode
sebuah contoh
if Not FileExists(SystemDrive+'\FileName.txt') then
begin
if CopyFile(PChar(FilePathBase+'FileName.txt'), PChar(SystemDrive+'\FileName.txt'), False) then
LogToFileToFile.LogToFile('[DatabaseInstallation] : copying FileName.txt to '+SystemDrive+'\ done')
else
LogToFileToFile.LogToFile('[DatabaseInstallation] : copying FileName.txt to '+SystemDrive+'\ Failed');
end;
if Not FileExists(SystemDrive+'\SecondFileName.txt') then
begin
if CopyFile(PChar(FilePathBase+'SecondFileName.txt'), PChar('c:\SecondFileName.txt'), False) then
LogToFileToFile.LogToFile('[DatabaseInstallation] : copying SecondFileName.txt to '+SystemDrive+'\ done')
else
LogToFileToFile.LogToFile('[DatabaseInstallation] : copying SecondFileName.txt to '+SystemDrive+'\ Failed');
end;
seperti yang Anda lihat ada banyak LogToFileToFile.LogToFile()
panggilan,
sebelum itu
if Not FileExists(SystemDrive+'\FileName.txt') then
CopyFile(PChar(FilePathBase+'FileName.txt'), PChar(SystemDrive+'\FileName.txt'), False)
if Not FileExists(SystemDrive+'\SecondFileName.txt') then
CopyFile(PChar(FilePathBase+'SecondFileName.txt'), PChar('c:\SecondFileName.txt'), False)
ini adalah kasus di seluruh kode saya sekarang.
sulit dibaca.
adakah yang bisa menyarankan saya cara yang bagus untuk mengacaukan panggilan ke LogToFile?
Suka
Mengindentifikasi panggilan 'LogToFileToFile.LogToFile () `
seperti iniif Not FileExists(SystemDrive+'\FileName.txt') then begin if CopyFile(PChar(FilePathBase+'FileName.txt'), PChar(SystemDrive+'\FileName.txt'), False) then {Far away--->>} LogToFileToFile.LogToFile(2,'[DatabaseInstallation] : [ACTION]:copying FileName.txt to '+SystemDrive+'\ sucessful') else {Far away--->>} LogToFileToFile.LogToFile(2,'[DatabaseInstallation] : [ACTION]:copying FileName.txt to '+SystemDrive+'\ Failed'); end;
Unit terpisah seperti Unit
LogToFileger
ini akan memiliki semua pesan LogToFile dalam bentukswitch case
seperti iniFunction LogToFilegingMyMessage(LogToFilegMessage : integer) begin case LogToFilegMessage of 1 : LogToFileToFile.LogToFile(2,'[DatabaseInstallation] : [ACTION]:copying FileName.txt to '+SystemDrive+'\ sucessful'); 2 : LogToFileToFile.LogToFile(2,'[DatabaseInstallation] : [ACTION]:copying FileName.txt to '+SystemDrive+'\ Failed'); 150 : LogToFileToFile.LogToFile(2,'[somthing] : [ACTION]: somthing important); end;
jadi saya bisa memanggil LogToFilegingMyMessage (1) di mana pun diperlukan.
Adakah yang bisa memberi tahu saya mana yang merupakan pendekatan yang lebih baik dan lebih bersih untuk LogToFileging dengan cara ini?
sumber
logBook.log()
ditemui.Jawaban:
Ketika Anda menambahkan logging, Anda memperkenalkan dua hal:
Masing-masing memiliki masalah memiliki sendiri, solusi yang relatif sederhana:
Pecahkan kode menjadi fungsi yang lebih kecil. Alih-alih memiliki satu fungsi raksasa yang berisi semua salinan Anda serta pesan log untuk kesalahan / kesuksesan, Anda bisa memperkenalkan fungsi "CopyFile", yang akan menyalin tepat satu file dan mencatat hasilnya sendiri. Dengan begitu kode utama Anda hanya terdiri dari panggilan CopyFile dan akan tetap mudah dibaca.
Anda bisa membuat logger Anda lebih pintar. Alih-alih mengirimkan string raksasa yang memiliki banyak informasi berulang, Anda bisa memberikan nilai penghitungan yang akan membuat segalanya lebih jelas. Atau Anda dapat mendefinisikan fungsi Log () yang lebih khusus, yaitu LogFileCopy, LogDbInsert ... Apa pun yang Anda ulangi banyak, pertimbangkan untuk memasukkannya ke dalam fungsinya sendiri.
Jika Anda mengikuti (1), Anda dapat memiliki kode yang terlihat seperti ini:
Kemudian CopyFile Anda () hanya perlu beberapa baris kode untuk melakukan tindakan dan mencatat hasilnya, sehingga semua kode Anda tetap ringkas dan mudah dibaca.
Saya akan menjauh dari pendekatan Anda # 2 karena Anda memisahkan informasi yang harus tetap bersama menjadi modul yang berbeda. Anda hanya meminta kode utama Anda agar tidak sinkron dengan pernyataan log Anda. Tetapi melihat LogMyMessage (5), Anda tidak akan pernah tahu itu.
UPDATE (menanggapi komentar): Saya tidak terbiasa dengan bahasa yang Anda gunakan, jadi bagian ini mungkin harus sedikit diadaptasi. Tampaknya semua pesan log Anda mengidentifikasi 3 hal: komponen, tindakan, hasil.
Saya pikir inilah yang disarankan MainMa. Alih-alih meneruskan string aktual, tetapkan konstanta (dalam C / C ++ / C #, mereka akan menjadi bagian dari tipe enum enum). Jadi misalnya untuk komponen, Anda mungkin memiliki: DbInstall, AppFiles, Registry, Shortcuts ... Apa pun yang membuat kode lebih kecil akan membuatnya mudah dibaca.
Ini juga akan membantu jika bahasa Anda mendukung lewat parameter variabel, tidak yakin apakah itu mungkin. Jadi misalnya jika tindakan adalah "FileCopy", Anda bisa menentukan tindakan itu untuk memiliki dua parameter pengguna tambahan: nama file dan direktori tujuan.
Jadi baris penyalinan file Anda akan terlihat seperti ini:
* catatan, tidak ada alasan untuk menyalin / menempel baris log dua kali jika Anda dapat menyimpan hasil operasi dalam variabel lokal yang terpisah dan hanya meneruskan variabel itu ke dalam Log ().
Anda melihat temanya di sini, kan? Kurang kode berulang -> kode lebih mudah dibaca.
sumber
you could pass in enumerations values
ini?Sepertinya Anda perlu mencabut konsep "LoggableAction". Saya melihat pola dalam contoh Anda di mana semua panggilan mengembalikan bool untuk menunjukkan keberhasilan atau kegagalan dan satu-satunya perbedaan adalah pesan log.
Sudah bertahun-tahun sejak saya menulis delphi jadi ini cukup banyak c # terinspirasi kode semu tapi saya akan berpikir Anda menginginkan sesuatu seperti
Kemudian kode panggilan Anda menjadi
Saya tidak dapat mengingat sintaks Delphi untuk pointer fungsi tetapi apapun detail implementasi, semacam abstraksi di sekitar log rutin tampaknya menjadi apa yang Anda cari.
sumber
LoggableAction()
ini bagus, saya bisa langsung menulis nilai yang dikembalikan daripada memeriksa dan menulis.Salah satu pendekatan yang mungkin adalah mengurangi kode dengan menggunakan konstanta.
akan menjadi:
yang memiliki kode log / rasio kode lain yang lebih baik saat menghitung jumlah karakter di layar.
Ini dekat dengan apa yang Anda sarankan dalam poin 2 dari pertanyaan Anda, kecuali bahwa saya tidak akan melangkah sejauh ini:
Log(9257)
jelas lebih pendek daripadaLog(2, SqlInstal, Action, CopyMapSuccess, sOSdrive)
, tetapi juga cukup sulit untuk dibaca. Apa itu 9257? Apakah ini sukses? Sebuah aksi? Apakah ini terkait dengan SQL? Jika Anda mengerjakan basis kode ini selama sepuluh tahun terakhir, Anda akan belajar angka-angka itu dengan hati (jika ada logika, yaitu 9xxx adalah kode sukses, x2xx terkait dengan SQL, dll.), Tetapi untuk pengembang baru yang menemukan basis kode, kode pendek akan menjadi mimpi buruk.Anda dapat melangkah lebih jauh dengan mencampurkan kedua pendekatan: gunakan konstanta tunggal. Secara pribadi, saya tidak akan melakukan itu. Ukuran konstanta Anda akan bertambah:
atau konstanta akan tetap pendek, tetapi tidak terlalu eksplisit:
Ini juga memiliki dua kelemahan. Anda harus:
Simpan daftar terpisah yang mengaitkan info log dengan konstanta masing-masing. Dengan satu konstanta, ia akan tumbuh cepat.
Temukan cara untuk menegakkan satu format dalam tim Anda. Misalnya, bagaimana jika alih-alih
T2SSQ
, seseorang akan memutuskan untuk menulisST2SQL
?sumber
log
panggilan bersih , tetapi bisakah Anda menjelaskan kepada saya lebih banyak hal yang tidak dimengertiLog(2, SqlInstal, Action, CopyMapFailure, sOSdrive)
, maksud Anda mengatakanSqlInstal
akan seperti variabel yang saya tetapkanSqlInstal:=[POSTGRESQL INSTALLATION]
?SqlInstal
bisa berupa apa saja, misalnya nilai3
. Kemudian, dalamLog()
, nilai ini akan diterjemahkan secara efektif[POSTGRESQL INSTALLATION]
sebelum digabungkan dengan bagian lain dari pesan log.single format in your team
adalah pilihan yang baik / bagusCobalah mengekstrak serangkaian fungsi kecil untuk menangani semua hal yang tampak berantakan. Ada banyak kode berulang yang bisa dengan mudah dilakukan di satu tempat. Sebagai contoh:
Caranya adalah dengan melihat duplikasi apa pun dalam kode Anda, dan menemukan cara untuk menghapusnya. Gunakan banyak spasi putih, dan gunakan awal / akhir untuk keuntungan Anda (spasi lebih banyak, dan mudah ditemukan / lipat blok kode). Seharusnya tidak terlalu sulit. Metode-metode ini bisa menjadi bagian dari logger Anda ... terserah Anda. Tapi itu sepertinya tempat yang bagus untuk memulai.
sumber
success := CopyFile()
terima kasih untuk idenya, ini akan mengurangi beberapa baris kode yang tidak perlu dalam kasus sayaLogIfFileDoesNotExist
menyalin file?Saya akan mengatakan bahwa ide di balik opsi 2 adalah yang terbaik. Namun, saya pikir arah yang Anda ambil membuatnya semakin buruk. Bilangan bulat tidak berarti apa-apa. Ketika Anda melihat kode, Anda akan melihat sesuatu sedang dicatat, tetapi Anda tidak tahu apa.
Sebaliknya saya akan melakukan sesuatu seperti ini:
Ini mempertahankan struktur pesan tetapi memungkinkan kode Anda menjadi fleksibel. Anda dapat mendefinisikan string konstan sesuai kebutuhan untuk fase dan hanya menggunakan itu sebagai parameter fase. Ini memungkinkan Anda untuk dapat mengubah teks aktual di satu tempat dan mempengaruhi semuanya. Manfaat lain untuk fungsi helper adalah bahwa teks yang penting adalah dengan kode (seperti itu adalah komentar), tetapi teks yang hanya penting untuk file log diabstraksi.
Ini bukan sesuatu yang Anda sebutkan dalam pertanyaan Anda, tetapi saya perhatikan tentang kode Anda. Lekukan Anda tidak konsisten. Pertama kali Anda menggunakannya
begin
bukan indentasi, tetapi yang kedua adalah. Anda melakukan hal serupa denganelse
. Saya akan mengatakan ini jauh lebih penting daripada baris log. Ketika lekukan tidak konsisten, itu membuatnya sulit untuk memindai kode dan mengikuti alurnya. Banyak garis log berulang yang mudah disaring saat memindai.sumber
Bagaimana dengan sesuatu di sepanjang baris ini:
Metode NewEntry () akan membangun baris teks (termasuk menambahkan [&] di sekitar entri yang tepat) dan berpendapat bahwa menunggu hingga metode sukses () atau kegagalan () dipanggil, yang menambahkan baris dengan 'sukses' atau 'kegagalan', dan kemudian mengeluarkan baris ke log. Anda juga bisa membuat metode lain, seperti info () untuk saat entri log untuk sesuatu selain keberhasilan / kegagalan.
sumber