Как еще можно оптимизировать этот код для защитного программирования?
-
04-10-2019 - |
Вопрос
Для моих проектов структур данных цель состоит в том, чтобы прочитать в предоставленном файле, содержащем более 10000 песен с художником, заголовком и лирикой, четко обозначенными, и каждая песня разделена строкой с одной двойной цитатой. Я написал этот код для анализа текстового файла, и он работает, с течением работы чуть менее 3 секунд до
Прочитайте 422K линейки текста
Создать объект песни
Добавьте сказанную песню для арайлиста
Анаторский код, который я написал:
if (songSource.canRead()) { //checks to see if file is valid to read
readIn= new Scanner(songSource);
while (readIn.hasNextLine()) {
do {
readToken= readIn.nextLine();
if (readToken.startsWith("ARTIST=\"")) {
artist= readToken.split("\"")[1];
}
if (readToken.startsWith("TITLE=\"")) {
title= readToken.split("\"")[1];
}
if (readToken.startsWith("LYRICS=\"")) {
lyrics= readToken.split("\"")[1];
} else {
lyrics+= "\n"+readToken;
}//end individual song if block
} while (!readToken.startsWith("\"")); //end inner while loop
songList.add(new Song(artist, title, lyrics));
}//end while not EOF
} //end if file can be read
Я разговаривал с моим вступлением к профессору алгоритз о Кодексе этого проекта, и он заявил, что я должен пытаться быть более защитным в моем коде, чтобы обеспечить несоответствия в данных, предоставляемых другими людьми. Первоначально я использовал, если / else блоки между полями художника, заголовка и лирики, а по его предложению я изменился на последовательные, если заявления. Хотя я вижу его точку зрения, используя этот пример этого кода, как я могу быть более защитным о разрешении несоответствий ввода?
Решение
Вы предполагаете, что вход идеально. Если вы посмотрите на то, как ваше приложение в настоящее время настроен на основе быстрого чтения вашего алгоритма, которые будут выглядеть так
ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
Но рассмотрим дело
ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
ARTIST="Peter"
LYRICS="Sing Song All night long"
"
На основании вашего алгоритма у вас сейчас есть 2 песни, характеризующиеся как
songList = { Song("JOHN", "HELLO WORLD", "Sing Song All night long"),
Song("Peter", "HELLO WORLD", "Sing Song All night long") }
С текущим алгоритмом художник и название подвергаются воздействию и будут отображаться во 2-й песне, даже если они не были определены. Вам нужно сбросить ваши три переменных.
В вашем другом вы просто сбрасываете полную линию в лирику. Что, если вы уже вытащили лирику, вы сейчас переоцениваете это. Прецедент
ARTIST="John"
LYRICS="Sing Song All night long"
TILET="HELLO WORLD"
"
Рассмотрите возможность отправки этой записи состоянию ошибки. Таким образом, когда завершен партия, завершен, отчет об ошибке может быть сгенерирован и исправлен.
Также вы считаете, что EOF после того, как художник был прочитан. Что, если EOF возникает во время чтения художника, и файл не заканчивается ». Вы собираетесь получить исключение там. В вашем Do / пока добавить еще один чек на hasnextline ()
Другие советы
Я бы заменил, например:
artist= readToken.split("\"")[1];
с участием
String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;
Другие модификации будут включать в себя:
- Сбросить локальные переменные (так что вы не случайно не получаете неправильный артист для песни, если для какой-то песни не поставляется артист.
- Решите, что делать, если бы некоторые данные отсутствуют - вы все еще хотите добавить песню в список песен?
В реальном мире есть некоторые гарантии, касающиеся целостности данных. В случае борьбы с пользовательским входом (будь то из stdin или файла) есть определенная парадигма проекта для уведомления пользователя проблемы, которая требует внимания.
Например, когда код компилятора, компилятор или оболочкой, выполняющий скрипт, сталкивается с несоответствием, он может остановить и распечатать строку, содержащую несоответствие со второй строкой ниже, что использует символ «^», чтобы указать местоположение проблемы.
Так вот какой-то основной вопрос, чтобы спросить себя:
1. Каждая ли линия гарантирована, чтобы содержать каждое поле?
2. Является ли заказы полей, гарантированных?
Если это условия входного договора и нарушены, вы должны игнорировать / сообщать об этом. Если они не являются условиями ввода, то вам нужно справиться с этим .. который вы в настоящее время не делаете.
Я вижу пару вещей, которые не хватает здесь, Джейсон.
Я думаю, что если / else было хорошо, и это не изменит логику. Однако вы должны ограничивать объем ваших переменных как можно больше. Объявляя художника, название и т. Д. Внутри цикл While, они будут инициализированы на NULL (или что-то), поэтому, если запись отсутствует, что артистка не будет получать значение последней записи.
Кроме того, что происходит, если название, артист и т. Д. У вас есть цитата? Как это обработано? Как насчет лирики, которые, кажется, имеют несколько строк, верно?
Что произойдет, если есть неизвестное поле - может быть, ошибка? Он будет добавлен к концу лирики, которые не кажутся правильными. Только после того, как место лирики было найдено, если вы должны добавить к нему. Если лирика - это значение null, то она начнется с "null".
Вот некоторые проблемы, которые могут быть адресованы:
Ваш код предполагает, что нет пробелов до (например) «Художника», ни один из «=» знак и так далее.
Ваш код предполагает, что ключевые слова находятся на всех шагах. Кто-то мог использовать строчные или смешанные случаи.
Ваш код предполагает, что строка, которая не начинается с
keyword=\"
это продолжение лирики песни. Но что, если введен пользовательARTOST="Sting"
? Или что, если пользователь попытался использовать две строки для имени художника?
Наконец, я не убежден, что замена «иначе, если« с «если» в этом случае имеет сделали любую разницу к надежности кода.
Сделка с исключениями (я думаю, сканер может бросить IgrismismatchException для неверного символа).
Похоже, do { } while (...)
Может ли не работать бесконечно, если файл плохо сформирован, а конец файла достигнут.
Ничто не мешает artist
или title
от пустые.