Статьи

Посмотрите на это внимательно, и вы найдете что-то для улучшения

Я предлагаю вам упражнение: когда вы вернетесь на работу завтра утром, просмотрите исходный код вашего проекта и попытайтесь найти возможности рефакторинга. Сделайте это, даже если ваш начальник не просил об этом. Делайте это, потому что вы хотите провести захватывающее время на работе.

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

Речь идет не о том, чтобы быть милым с компанией или с начальником, а с самим собой. Почему? Поскольку проблемы имеют тенденцию накапливаться, и в какой-то момент вы потеряете контроль над своим кодом. Вы столкнетесь с трудными временами для достижения результатов, и это разрушит вашу карьеру

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

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

Речь шла о конкатенации строк в Java: классическая проблема, подчеркиваемая многими специалистами на протяжении многих лет и, вероятно, игнорируемая в настоящее время. До JDK 1.5, несмотря на свою читабельность и простоту, конкатенация строк с использованием оператора «+» могла привести к очень неэффективному коду. За кулисами этот оператор был заменен на байт-код, эквивалентный
StringBuffer , который фактически реализовал конкатенацию. Чем больше вы используете оператор «+», тем больше экземпляров String и StringBuffer у вас будет в памяти, а также будет иметь достаточно времени для обработки всех этих объектов. Из-за этого разработчики были вынуждены сразу использовать StringBuffer и игнорировать оператор «+». Посмотрите на следующий пример:

1
2
3
4
5
6
String title = "Mr.";
String name = "John";
String familyName = "Smith";
 
String message = "Dear " + title + " " +
                 name + " " + familyName + ",";

Разработчики привыкли так писать, но вместо этого их заставляли писать:

1
2
3
4
5
6
7
8
StringBuffer sb = new StringBuffer();
sb.append("Dear ");
sb.append(title);
sb.append(" ");
sb.append(name);
sb.append(" ");
sb.append(familyName);
sb.append(",");

Вы можете согласиться со мной, что первый пример более читабелен, чем второй. Для разработчиков вполне естественно использовать оператор «+» при конкатенации строк, поэтому было несправедливо отказаться от этого синтаксиса. К счастью, ребята из компилятора сделали что-то с этим, убедившись, что JDK 1.5 оптимизирует конкатенации. Вместо того чтобы использовать StringBuffer, потокобезопасный класс, они создали новый класс с именем StringBuilder (не потокобезопасный, следовательно, более быстрый), и они убедились, что один его экземпляр будет обрабатывать все объединения, как показано в первом примере. Это важный шаг, потому что они предпочитали элегантность вместо технических деталей. Первый пример автоматически преобразуется во время компиляции во что-то вроде этого:

1
2
3
4
StringBuilder sb = new StringBuilder();
sb.append("Dear ").append(title).append(" ")
  .append(name).append(" ").append(familyName)
  .append(",");

Однако, конкатенации в нетривиальной логике все еще требуют от вас написания StringBuilder в вашем коде, потому что компилятор еще не настолько умен. Например:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
List<Student> students = studentBean.findStudents();
String intro = "The following students were approved:\n";
String listedNames = "";
String separator = "";
for(Student student: students) {
  if(student.approved()) {
    if(!listedNames.isEmpty()) {
      separator = ", ";
    }
    listedNames += separator + student.getName();
  }
}
String msg = intro + listedNames;
messengerBean.sendMessage(msg);

будет более эффективным, если написано так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
List<Student> students = studentBean.findStudents();
String intro = "The following students were approved:\n";
StringBuilder listedNames = new StringBuilder();
String separator = "";
for(Student student: students) {
  if(student.approved()) {
    if(!listedNames.length() > 0) {
      separator = ", ";
    }
    listedNames.append(separator)
               .append(student.getName());
  }
}
String msg = intro + listedNames.toString();
messengerBean.sendMessage(msg);

UPS! Вы заметили что-нибудь странное там? Это может быть неочевидно с первого взгляда, но посмотрите, как они проверяют, является ли переменная перечисленные в именах пустыми перед определением разделителя. Класс String имеет хороший читаемый метод isEmpty (), представленный в JDK 1.6, но StringBuilder все еще использует этот довольно старый способ сравнения. Почему они не сделали это для StringBuilder и StringBuffer?

Обсуждая проблему в списке рассылки core-lib-dev , выясняется, что нет никаких очевидных причин, почему они этого не делали раньше. Возможно, они просто забыли это. Благодаря большому рефакторингу, пытаясь улучшить неэффективное использование конкатенации строк, удалось обнаружить такую ​​несогласованность . Я полагаю, что у них еще есть время исправить это в Java 8, которая выйдет в следующем году. И они исправят это, добавив метод isEmpty () в интерфейс CharSequence, чтобы убедиться, что любая другая реализация будет одинаково элегантной.

Это может быть простой вещью, но каждая деталь имеет значение, когда Java подвергается резкой критике за такой многословный язык. Итак, займитесь рефакторингом и найдите возможности улучшить свой код, а также язык, который вы используете для его написания! Давайте двигаться вперед Java!