Mesin status urutan
Saya mencoba mengurai argumen baris perintah. Program ini membutuhkan empat argumen. Saya mengulangi argumen. Jika argumennya adalah opsi, saya memproses opsi tersebut. Jika tidak, argumen tersebut adalah salah satu argumen yang diperlukan. Untuk membaca argumen yang diperlukan, saya membutuhkan semacam mesin negara. Dalam kasus pertama, argumen pertama harus dibaca. Dalam kasus kedua, argumen kedua dan seterusnya.
Saya menulis Prockelas hanya dengan satu metode, yang mengembalikan lagi Prockelas.
static abstract class Proc {
abstract Proc exec (String arg);
}
Dengan ini saya dapat melakukan beberapa tindakan dan menentukan apa yang harus dilakukan selanjutnya.
- simpan db host dan kemudian baca nama
- simpan nama db dan kemudian baca pengguna
- simpan db pengguna dan kemudian baca file xml
- simpan file xml dan kemudian tidak ada
Tetapi karena semua biaya overhead kelas sulit untuk dibaca.
Proc proc = new Proc () {
Proc exec (String arg) {
db_host = arg;
return new Proc () {
Proc exec (String arg) {
db_name = arg;
return new Proc () {
Proc exec (String arg) {
db_user = arg;
return new Proc () {
Proc exec (String arg) {
xml_file = arg;
return null;
}
};
}
};
}
};
}
};
Apakah ada cara untuk menyederhanakan kode? Saya mencoba Lambdas, tetapi menurut saya Lambdas hanya dapat menggunakan variabel final, yang agak tidak berguna, ketika saya ingin menyimpan nilai.
Contoh lengkapnya:
public class Import
{
static String db_host = null;
static String db_port = "5432";
static String db_name = null;
static String db_user = null;
static String xml_file = null;
static void usage ()
{
System.err.println ("Usage: Import [-p PORT] HOST DATABASE USER FILE");
}
static abstract class Proc {
abstract Proc exec (String arg);
}
static void parse_args (String[] args)
{
Proc proc = new Proc () {
Proc exec (String arg) {
db_host = arg;
return new Proc () {
Proc exec (String arg) {
db_name = arg;
return new Proc () {
Proc exec (String arg) {
db_user = arg;
return new Proc () {
Proc exec (String arg) {
xml_file = arg;
return null;
}
};
}
};
}
};
}
};
try {
for (int i = 0; i < args.length; i++)
switch (args[i]) {
case "-p":
db_port = args[++i];
break;
case "-h":
usage ();
break;
default:
proc = proc.exec (args[i]);
}
}
catch (Exception ex) {
throw new Error ("Can not parse args!", ex);
}
}
public static void main (String[] args)
{
parse_args (args);
System.err.println ("db_host: " + db_host);
System.err.println ("db_port: " + db_port);
System.err.println ("db_name: " + db_name);
System.err.println ("db_user: " + db_user);
System.err.println ("xml_file: " + xml_file);
}
}
Jawaban
Pertama, Anda harus mengikuti konvensi penamaan Java .
Kedua, jangan mempersingkat nama hanya karena Anda bisa. Contoh, apa kepanjangan dari "Proc"? Prosedur? Prosesor? Bahkan jika nama menjadi lebih panjang, keterbacaan itu sangat berharga!
static String db_host = null;
Anggota Anda tidak boleh static, dan idealnya harus memiliki kualifikasi dengan sesuatu selain package-private, suka protectedatau privateuntuk menunjukkan maksud dengan jelas.
Untuk membaca argumen yang diperlukan, saya membutuhkan semacam mesin negara.
Apakah itu persyaratan yang telah Anda berikan atau apakah itu asumsi yang Anda miliki? Karena itu sama sekali tidak benar. Secara keseluruhan, sistem Anda benar-benar rumit tanpa alasan atau manfaat yang jelas. Juga tidak tampak seperti mesin negara, itu hanya rantai panggilan fungsi yang terlalu kompleks.
Mesin negara untuk penguraian argumen perintah Anda akan menjadi seperti ini:
for (int index = 0; index < args.length; index++) {
String arg = args[index];
if (arg.equals("-p") && databaseHost == null) {
arg = args[++index];
databasePort = arg;
} else if (databaseHost == null) {
databaseHost = arg;
} else if (databaseUsername == null) {
databaseUsername = arg;
} else if (databasePassword == null) {
databasePassword = arg;
} else if (inputFile == null) {
inputFile = arg;
}
}
Dan bahkan itu sangat rumit.
Yang Anda inginkan adalah solusi paling sederhana yang berhasil, dan itu akan menjadi ekstraksi argumen dengan hardcode:
if (args[0].equals("-h")) {
printHelp();
return;
}
int portProvidedOffset = 0;
if (args[0].equals("-p")) {
databasePort = args[1];
portProvidedOffset = 2;
}
databaseHost = args[portProvidedOffset + 0];
databaseUsername = args[portProvidedOffset + 1];
databasePassword = args[portProvidedOffset + 2];
inputFile = args[portProvidedOffset + 3];
Yang, tentu saja, tidak cantik, tetapi solusi paling sederhana yang dapat Anda lakukan. Tentu saja, panjang array harus diperiksa terlebih dahulu, apakah terdiri dari 4 elemen atau lebih. Setelah itu Anda akan memeriksa apakah semua parameter diatur, jika tidak, keluar dengan kesalahan.
Jika Anda menginginkan solusi yang lebih canggih, Anda perlu menulis sendiri pengurai argumen lengkap, latihan yang tidak terlalu sepele.