JavaRush /Курсы /Java Syntax Pro /Правильная работа программы

Правильная работа программы

Java Syntax Pro
14 уровень , 0 лекция
Открыта

1. Задачи программиста

Очень часто начинающие программисты представляют себе суть работы программиста совсем не так, как опытные программисты.

От новичка часто можно услышать «Программа работает, что вам еще нужно?». Опытный же программист знает, что «работает правильно» — это только одно из требований к программе, причем даже не самое главное!

Читабельность кода

Самое главное — это чтобы код программы был понятен другим программистам. Это важнее, чем правильно работающая программа. Гораздо важнее.

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

Просто возьмите любую скомпилированную программу, например, notepad (блокнот) и поменяйте у него цвет фона на красный. Работающая программа у вас есть, понятного кода программы у вас нет: в такую программу невозможно вносить изменения.

Хрестоматийный пример — когда разработчики Microsoft убрали из Windows игру Pinball, потому что не смогли портировать ее на 64-х разрядную архитектуру. Причем у них даже были ее исходники. Просто они не могли понять, как работает написанный код.

Учет всех сценариев использования

Второе по важности требование к программе — это учет всех сценариев ее работы. Зачастую все оказывается немного сложнее, чем кажется.

Как программист-новичок видит отправку СМС в своей программе:

Правильная работа программы

Как это видит-программист-профессионал:

Правильная работа программы

А «работа правильно» — это обычно только один из множества сценариев. И именно поэтому многие новички жалуются на валидатор задач в JavaRush: один сценарий из 10 работает, и программист-новичок думает, что этого достаточно.


2. Нештатные ситуации

Нештатные ситуации

При работе любой программы могут возникать нештатные ситуации.

Например, вы решили сохранить файл, а на диске нет места. Или программа пытается записать данные в память, а памяти мало. Или вы скачиваете картинку из интернета, а в процессе скачивания пропала связь.

Программист (автор программы) должен каждую нештатную ситуацию а) предугадать, б) решить, как именно программа должна работать в этой ситуации, в) запрограммировать решение, максимально близкое к желаемому.

Поэтому довольно долго у программ было очень простое поведение: если в программе происходила ошибка, программа закрывалась. И это был достаточно хороший подход.

Допустим, вы хотите сохранить документ на диск, и в процессе сохранения выясняется, что места на диске не хватает. Какой вариант поведения программы вам бы понравился больше всего:

  • Программа закрылась
  • Программа продолжила работать, но файл не сохранила.

Программисту-новичку может показаться, что второй вариант лучше, ведь программа-то работает. Но на самом деле это не так.

Представьте, что вы 3 часа набирали документ в Word’е, хотя еще на второй минуте работы стало ясно, что программа не может сохранить документ на диск. Что лучше — потерять две минуты работы или три часа?

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


3. Предыстория возникновения исключений

Нештатные ситуации бывают не только у программ, но и внутри программы — у методов. Например:

  • Метод хочет записать файл на диск, а места нет.
  • Метод хочет вызвать функцию у переменной, а переменная == null.
  • В методе возникло деление на 0.

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

Если мы пытаемся сохранить файл на диск и такой файл уже существует, можно просто попросить у пользователя подтверждение для перезаписи файла. Если на диске нет места, можно вывести пользователю уведомление и предложить выбрать другой диск. А если у программы закончилась память — аварийно завершится.

Когда-то давно программисты думали над этим вопросом и придумали такое решение: все методы/функции должны возвращать код ошибки в качестве результата своей работы. Если функция отработала отлично, она возвращала 0, если нет — возвращала код ошибки (не ноль).

При таком подходе к ошибкам программисту после вызова практически каждой функции нужно было добавлять проверку, не завершилась ли функция с ошибкой. Код программ значительно увеличился и стал похож на такое:

Код без обработки ошибок Код с обработкой ошибок
File file = new File("ca:\\note.txt");
file.writeLine("Текст");
file.close();
File file = new File("ca:\\note.txt");
int status = file.writeLine("Текст");
if (status == 1)
{
   ...
}
else if (status == 2)
{
   ...
}
status = file.close();
if (status == 3)
{
   ...
}

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

В большой программе цепочка из десятков вызовов функций — это норма: иногда даже можно встретить глубину вызова в сотни функций. И вот нужно передать код ошибки с самого низа на самый верх. И если где-то на этом пути какая-то функция не обработает код завершения, ошибка потеряется.

Еще один минус такого подхода в том, что если функции возвращали код ошибки, они больше не могли возвращать значения своей работы. Приходилось передавать результат вычислений через параметры-ссылки. Это делало код еще более громоздким и еще больше увеличивало количество ошибок.


Комментарии (261)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
HXTSUKX6E Уровень 24
28 августа 2025
По ошибке (не знаю назвать ли это ошибкой) дописал к методу для поиска модификатор private (убил 3 часа дебажа и смотря, И НЕ ПОНИМАЯ почему не проходит)
Руслан Уровень 48
19 августа 2025
Задачка и впрямь не сложная, главное разобраться как и что работает
Anonymous #3585174 Уровень 33
7 июля 2025
like
Sergey T Уровень 12
1 июля 2025
Делал задачу - потом внезапно TASK_UNKNOWN. Перезагрузил страницу - блок с задачей пропал🤣
Виктор Уровень 25
27 июня 2025
Страшно от else if-ов в правильном решении, они имеют смысл? )
Danya Уровень 17
20 апреля 2025
объясните а зачем мы используем users.indexOf(user); ?
Олег Сычев Уровень 29
30 апреля 2025
ArrayList - это коллекция, в ней есть метод indexOf, который ищет пользователя по коллекции и возвращает его index. Почитай про этот метод. В целом, полезная фишка делать задачи в idea, в ней зажимаешь ctrl (в Windows) и кликаешь мышью по методу о котором хочешь узнать больше - откроется класс с кодом метода и зачастую его описанием, что он делает, что он возвращает.
Пётр Уровень 92
18 апреля 2025
/* Комментарий удален */
Eternal Fire Уровень 30
29 мая 2025
users.contains(user) - это boolean, users.indexOf(user) - это int. Они не равнозначны. Один метод проверяет, есть ли пользователь в списке, другой возвращает индекс пользователя.
lusya 1 Уровень 32
3 апреля 2025
Наконец-то долгожданные исключения!
Victor Уровень 39
28 января 2025
Я всё-таки дописал в класс Users вывод toString - хоть посмотреть что там происходит: @Override public String toString() { return "Имя " + getName() + "; " + "Bозраст " + getAge(); } а на консоль вывел через это: for (User myUser : users) System.out.println(myUser.toString());
Vladislav Уровень 15
28 января 2025
какое балдженое чувство, когда с первого раза получилось