Как еще этот код может быть оптимизирован для защитного программирования? - PullRequest
0 голосов
/ 21 сентября 2010

Для моего проекта структур данных цель состоит в том, чтобы прочитать в предоставленном файле, содержащем более 10000 песен, с четко обозначенным исполнителем, заголовком и текстами песен, и каждая песня разделена строкой с одной двойной кавычкой.Я написал этот код для разбора текстового файла, и он работает со временем выполнения чуть менее 3 секунд, чтобыпрочитайте 422K строк текстасоздать объект Songдобавить сказанную песню в ArrayList

Код синтаксического анализа, который я написал:

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 

Я говорил с моим преподавателем Intro to Algorithms о коде для этого проекта, и он заявил, что я должен попытаться быть более защищенным вмой код, чтобы учесть несоответствия в данных, предоставленных другими людьми.Первоначально я использовал блоки if / else между полями Artist, Title и Lyrics, и по его предложению я изменил на последовательные выражения if.Несмотря на то, что я могу понять его точку зрения, используя этот пример кода, как я могу быть более осторожным при учете несоответствий ввода?

Ответы [ 6 ]

4 голосов
/ 21 сентября 2010

Я бы заменил, например:

artist= readToken.split("\"")[1];

на

String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;

Другие модификации будут включать:

  1. сброс локальных переменных (так что вы неСлучайно выбрать неподходящего исполнителя для песни, если для какой-либо песни после первой не указан ни один исполнитель)
  2. решить, что делать, если отсутствуют какие-либо данные - хотите ли вы добавить песню в список песен??
2 голосов
/ 21 сентября 2010

Вы предполагаете, что ввод идеален. Если вы посмотрите, как настроено ваше приложение, на основании быстрого чтения вашего алгоритма, данные будут выглядеть так:

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 / while добавьте другое проверка для hasNextLine ()

2 голосов
/ 21 сентября 2010

В реальном мире существуют некоторые гарантии в отношении целостности данных. В случае работы с пользовательским вводом (будь то из стандартного ввода или из файла) существует определенная парадигма проекта для уведомления пользователя о проблеме, требующей внимания.

Например, когда компилятор кода или оболочка, выполняющая скрипт, обнаруживают несоответствие, он может остановить и распечатать строку, содержащую несоответствие, со второй строкой под ним, которая использует символ «^», чтобы указать местоположение проблемы .

Итак, вот несколько основных вопросов, которые вы должны себе задать:
1. Гарантируется ли каждая строка каждого поля?
2. Гарантирован ли порядок полей?

Если это условия входного контракта и они нарушены, вам следует игнорировать / сообщать о строке. Если они не являются условиями ввода, то вам нужно обработать это .. что вы в настоящее время не делаете.

1 голос
/ 21 сентября 2010

Я вижу пару вещей, которые здесь отсутствуют, Джейсон.

Я думаю, что если / еще было хорошо, и это не изменит логику. Тем не менее, вы должны максимально ограничить область действия ваших переменных. Объявляя Artist, Title и т. Д. Внутри цикла while, они будут инициализированы нулем (или чем-то еще), поэтому, если в записи отсутствует артист, она не получит значение последней записи.

Кроме того, что произойдет, если в названии, исполнителе и т. Д. Есть цитата? Как это обрабатывается? Как насчет текстов, которые кажутся правильными?

Что происходит, если есть неизвестное поле - возможно, орфографическая ошибка? Это будет добавлено в конец Лирики, которая кажется неправильной. Только после того, как поле LYRICS было найдено, вы можете добавить к нему. Если текст песни равен нулю, он начинается с «нуля».

0 голосов
/ 21 сентября 2010

Работа с исключениями (я полагаю, сканер может выдать InputMismatchException для недопустимого символа).

Похоже, что do { } while (...) может бесконечно зацикливаться, если файл неверно сформирован и конец файла достигнут.

Ничто не мешает artist или title быть пустыми.

0 голосов
/ 21 сентября 2010

Вот некоторые проблемы, которые можно решить:

  • В вашем коде предполагается, что до (например) "ARTIST" нет пробелов, нет знака "=" и т. Д.

  • В вашем коде предполагается, что ключевые слова указаны заглавными буквами. Кто-то может использовать строчные или смешанные буквы.

  • Ваш код предполагает, что строка, которая начинается не с keyword=\", является продолжением текста песни. Но что, если пользователь ввел ARTOST="Sting"? Или что, если пользователь попытался использовать две строки для имени исполнителя?

Наконец, я не уверен, что замена «else if» на «if» в этом случае имеет , что повлияло на надежность кода.

...