Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Советы по хорошему стилю, начинающим гурятам от матёрых гурей :) 
:(
    Опции темы
nornad
Дата 14.6.2007, 03:01 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Не нашёл здесь такой темы, но считаю, что она будет полезна многим. Возможно, даже многим из тех, кто уже давно считает себя не новичком в Java.
В общем, идея проста - все, кому есть, что сказать, предлагают свои советы по тому, как писать код в хорошем стиле.
Чтобы было понятно, приведу пару советов из тех, что в последние дни вычитал на форуме:

1. Если в метод были переданы некорректные данные, выкидываем исключение вместо тихого-мирного притягивания данных за уши к корректному виду.
Пример.
плохо:
Код

public void setWeight( float weight ) {
    if ( weight >= 0 )
        this.weight = weight;
}

лучше:
Код

public void setWeight( float weight ) {
    if ( weight >= 0 )
        this.weight = weight;
    else
        throw new IllegalArgumentException("Weight must be >= 0");
}


2. При переопределении метода equals() надо переопределять ещё и hashCode(). Причём хэшкод должен быть равен для объектов, если они эквивалентны (equals() == true).

P.S. Понятно, что многим подобные вещи известны и они пользуются ими не задумываясь. С другой стороны, всё знать нельзя и скорее всего каждый найдёт для себя что-то интересное в этой теме. Ну, или вспомнит хорошо забытое старое. smile 


--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
RebornCrusader
Дата 14.6.2007, 08:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 139
Регистрация: 18.1.2007
Где: Владивосток

Репутация: 2
Всего: 6



Сюда же: имя параметра в setter-методе желательно иметь соответствующим имени метода, также как имя поля.

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

И кстати: такое "исправление внутри" может быть удобным и вполне имеет право быть применимым если :
1) Это private метод (наши грабли)
2) Факт описан в javadoc (документированные грабли)
Иначе придётся писать как "культурный" метод, так и враппер к нему. Я не сильно разделяю такую точку зрения, просто привожу её как контрпример.
Прошу не принимать близко к сердцу ;)


Второй пунк описан в каждом учебнике по Java. А IDEA так парой и предлагает их генерить...

P.S. Хорошая тема, надо развивать. Только нужно структурирование.
Люди пишут программу, отмечают "тру-решение" или наоборот , постят сюда - только кто возьмётся за сортировку?

--------------------
"Fais se que dois, - adviegne que peut. C'est commande au chevalier"
PM   Вверх
val
Дата 14.6.2007, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: нет
Всего: 7



Цитата

Если в метод были переданы некорректные данные, выкидываем исключение вместо тихого-мирного притягивания данных за уши к корректному виду.


Не думаю, что это всегда так... Такой подход, конечно, весьма практичен, но засоряет код лишними try/catch блоками... Кроме того, exception зачастую подразумевает исключительную ситуацию, которая связана с принципиально непреодалимой ошибкой, ну а в примере ошибка более чем преодолима и может встречаться довольно-таки часто.


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
Maksym
Дата 14.6.2007, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 14
Всего: 62



Цитата(val @  14.6.2007,  09:47 Найти цитируемый пост)
Кроме того, exception зачастую подразумевает исключительную ситуацию, которая связана с принципиально непреодалимой ошибкой.

Исключения как раз придуманы для того, чтобы преодолевать некритические ошибки и незапланированное поведение системы. Я согласен с тем, как в своем примере этот механизм применил nornad.

PM MAIL   Вверх
w1nd
Дата 14.6.2007, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вертилятор
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 22.3.2006
Где: Москва

Репутация: 20
Всего: 54



Цитата(nornad @  14.6.2007,  03:01 Найти цитируемый пост)
2. При переопределении метода equals() надо переопределять ещё и hashCode(). Причём хэшкод должен быть равен для объектов, если они эквивалентны (equals() == true).

Дополню. Если создаётся наследник класса, в котором переопределёны equals() и hashCode(), в классе наследнике их следует переопределить обязательно.


--------------------
user posted imageuser posted image
PM MAIL ICQ   Вверх
nornad
Дата 14.6.2007, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Цитата(Maksym @  14.6.2007,  15:30 Найти цитируемый пост)
Я согласен с тем, как в своем примере этот механизм применил nornad.

На всякий случай поясню: я согласен с приведённым мною примером, но авторство не моё - в одной из тем именно этот пример дал LSD.
Мне, конечно, приятно собирать лавры, но в данном случае они не мои.
Первый пример тоже не мой, но автора я уже не помню (пример взят из темы "Маленький тест").

По поводу засорения кода блоками try-catch.
Имхо, лучше засорить код такими блоками и получить взамен более простой и удобный способ обнаружения и устранения ошибок.

Цитата(RebornCrusader @  14.6.2007,  11:19 Найти цитируемый пост)
Второй пунк описан в каждом учебнике по Java.

К своему стыду должен признать, что не читал таких учебников. Даже TIJ до сих пор только издалека видел.

Цитата(w1nd @  14.6.2007,  16:01 Найти цитируемый пост)
Дополню. Если создаётся наследник класса, в котором переопределёны equals() и hashCode(), в классе наследнике их следует переопределить обязательно.

Если я правильно понял, то это звучит так:
Если мы в классе А переопределили equals+hashCode, то и в классе Б (наследнике от А) их тоже надо переопределить.

Думмаю, так чуток яснее.

Цитата(RebornCrusader @  14.6.2007,  11:19 Найти цитируемый пост)
И пара придирок к вашему коду: на мой взгляд, охватывающие скобки "{}" в if следует ставить всегда, когда условие тривиально и не входит в единственную строчку.

Предпочитаю не захламлять код лишними блоками и пользуюсь следующим правилом:
1. если условие динное (из нескольких частей, либо просто больше 20-30 символов), переносим оператор (то, что надо выполнить) на следующую строку. Замечу, что это верно только для if с одним оператором - блоки всегда структурирую в отдельных строках, не считая самих скобок.
2. если в коде идёт сложная структура из операторов if, то в каждом обязательно обрамляем оператор скобками блока (даже если оператор один). Это позволяет избежать неверной работы, когда мы используем if-else. Пример:
Код

if ( 1 )
  if ( 2 )
    if ( 3 )
      // do 1
  else
    // do 2

Это плохо, т.к. выглядит и работает по-разному. Чтобы работа соответствовала виду, надо сделать хотя бы так:
Код

if ( 1 )
  if ( 2 ) {
    if ( 3 )
      // do 1
  } else
    // do 2

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

Цитата(RebornCrusader @  14.6.2007,  11:19 Найти цитируемый пост)
P.S. Хорошая тема, надо развивать. Только нужно структурирование.
Люди пишут программу, отмечают "тру-решение" или наоборот , постят сюда - только кто возьмётся за сортировку?

Если честно, не понял. Опиши шире, что ты имеешь в виду.


--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
powerOn
Дата 14.6.2007, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Если у вас в коде есть константа и переменная типа String, которые нужно сравнить, то всегда вызывайте метод equails на константе:

плохо:
Код

    private final static String SOME_STRING = "SOME_STRING";
    public boolean myCompare(String s)
    {
        return s.equals(SOME_STRING);
    }


хорошо:
Код

    private final static String SOME_STRING = "SOME_STRING";
    public boolean myCompare(String s)
    {
        return SOME_STRING.equals(s);
    }



--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
nornad
Дата 14.6.2007, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Цитата(powerOn @  14.6.2007,  23:49 Найти цитируемый пост)
Если у вас в коде есть константа и переменная типа String, которые нужно сравнить, то всегда вызывайте метод equails на константе

Небольшое дополнение.
Иногда нет необходимости выделять константу в собственное поле (по-хорошему, всё же лучше выделить), но совет всё равно стоит использовать:
Код

    public boolean myCompare(String s)
    {
        return "SOME_STRING".equals(s);
    }


Добавлено через 4 минуты и 35 секунд
Кстати, а вот и ещё один совет. Просто, обозначу его явно:

Все строковые константы желательно выделять в поля. Это относится к дефолтовым значениям строковых полей, названиям кнопок, страниц и панелей. Единственное исключение - пустая строка.

И немного расширим:

Все константы (любого типа) желательно выделять в поля. Исключения - пустая строка, 0 и т.п.


--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
y3u
Дата 14.6.2007, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 440
Регистрация: 9.9.2006
Где: Москва

Репутация: 5
Всего: 13



Цитата

 private final static String SOME_STRING = "SOME_STRING";


missorted modifiers, private string constant...

я бы сделал так

Цитата

 public static final String SOME_STRING = "SOME_STRING";



--------------------
В нашей стране настаивать на кореньях, черной смородине, лимонных корках - гораздо эффективнее, чем на правах
PM MAIL   Вверх
powerOn
Дата 14.6.2007, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(nornad @  14.6.2007,  21:58 Найти цитируемый пост)
Иногда нет необходимости выделять константу в собственное поле (по-хорошему, всё же лучше выделить), но совет всё равно стоит использовать:

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

Цитата(nornad @  14.6.2007,  21:58 Найти цитируемый пост)
Все строковые константы желательно выделять в поля. Это относится к дефолтовым значениям строковых полей, названиям кнопок, страниц и панелей.

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

Добавлено через 41 секунду
Цитата(y3u @  14.6.2007,  22:47 Найти цитируемый пост)
я бы сделал так

очень может быть smile


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
Maksym
Дата 14.6.2007, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 14
Всего: 62



nornad
Цитата(nornad @  14.6.2007,  20:58 Найти цитируемый пост)
Все константы (любого типа) желательно выделять в поля. Исключения - пустая строка, 0 и т.п. 

А чем 0 лучше других чисел?
Цитата(nornad @  14.6.2007,  20:58 Найти цитируемый пост)
Это относится к дефолтовым значениям строковых полей, названиям кнопок, страниц и панелей.

Думаю, эти вещи нужно не выделять в поля, а хранить в properties файле и доставать через ResourceBundle.

PM MAIL   Вверх
nornad
Дата 14.6.2007, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Цитата(Maksym @  15.6.2007,  01:05 Найти цитируемый пост)
А чем 0 лучше других чисел?

Тем же, чем и пустая строка "лучше" остальных строк.
Кстати, к "исключительным" магическим числам, имхо, стоит отнести и -1 - очень часто это означает "неверный индекс/вариант".
То есть, если 0 используется для проверки на пустоту списка (по количеству элементов), то не стоит его выносить в отдельное поле.
Также и -1, если она используется, скажем, для определения, есть ли выделение в таблице (JTable.getSelectedRow(), например).


--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
Maksym
Дата 14.6.2007, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 14
Всего: 62



Цитата(nornad @  14.6.2007,  22:25 Найти цитируемый пост)
Тем же, чем и пустая строка "лучше" остальных строк.

Пустую строку не использую как константу, просто потому что это не читабельно (непонятно, что она должна означать), а строковая константа своим значением как правило несет какой-то смысл тому, кто читает код.
Цитата(nornad @  14.6.2007,  22:25 Найти цитируемый пост)
То есть, если 0 используется для проверки на пустоту списка (по количеству элементов), то не стоит его выносить в отдельное поле.

Это я и имел в виду. Ноль в группе других числовых констант ничем не выделяется. В то же время, он как количество элементов списка -- очевиден. А как результат выполнения операции -- почти очевиден..



PM MAIL   Вверх
RebornCrusader
Дата 15.6.2007, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 139
Регистрация: 18.1.2007
Где: Владивосток

Репутация: 2
Всего: 6



Цитата(nornad @  15.6.2007,  03:24 Найти цитируемый пост)
Если честно, не понял. Опиши шире, что ты имеешь в виду.

Создать что-то типа справочника "как надо" и "как не надо" - набор практических советов. Люди постят идеи в форуме, определённый человек их отфильтровывает и подкладывает в какой-нибудь FAQ. Строго по пунктам, со всеми "за" и "против", но лаконично. Для начала можно просто в начале темы. Можно выделить такие тематики как "косметическое оформление", "часто используемые конструкции" и т. д. в ширь и вглубь - по мере накопления материала.
И вообще я согласен с тезисом, что даже на глубоко тривиальные иногда нужно указать - не всегда они приходят легко и сразу.

Цитата(nornad @  15.6.2007,  03:24 Найти цитируемый пост)
Но я в таких случаях предпочитаю везде поставить блоки (иногда через пару дней лезешь в код и видишь, что надо добавить ещё один if - тогда-то блоки и спасают от вероятности приделать новый if не к месту).

Я как-то для себя решил не усложнять такие вещи. Либо if в одну строчку (обычно с break, return или throw), либо if полноценный - потенциально многострочный. Вколотить туда отладку какую-нибудь или логи опять же удобней...

Цитата(Maksym @  15.6.2007,  06:05 Найти цитируемый пост)
Думаю, эти вещи нужно не выделять в поля, а хранить в properties файле и доставать через ResourceBundle.

Не совсем согласен. Если данная строка текста используется в нескольких местах (в классе), в поле её загнать прямой резон. Но и из бандла читать:
Код

private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("my.cool.project.MegaClass");
private static final String BUTTON_ADD = RESOURCE_BUNDLE.getString("button.add");

На первый взгляд громоздко, зато ошибиться потом просто невозможно. 
Строки, используемые в GUI однократно, имеет смысл загружать на ходу (всё равно они там где-то кэшируются). Незачем засорять класс лишними константами, если они нужны только в одном методе и один раз. Только если уверен, что завтра они не понадобятся ;)

И на счёт ResourceBundle. Даже если не думать об интернализации, редактировать строки в ресурсном файле всё равно в разы удобнее, чем в исходнике, где они раскиданы по всем тексту.

К слову о константах. Читая книжки, натыкаешься чуть ли не на холивары на тему - должны быть они public или private. Хотя на самом деле всё просто - как и остальные члены класса, они должны иметь тот модификатор, который соответствует их необходимости для наследников или внешних классов.

Это сообщение отредактировал(а) RebornCrusader - 15.6.2007, 08:03
--------------------
"Fais se que dois, - adviegne que peut. C'est commande au chevalier"
PM   Вверх
nornad
Дата 15.6.2007, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Цитата(RebornCrusader @  15.6.2007,  10:44 Найти цитируемый пост)
Для начала можно просто в начале темы.

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

Цитата(RebornCrusader @  15.6.2007,  10:44 Найти цитируемый пост)
И вообще я согласен с тезисом, что даже на глубоко тривиальные иногда нужно указать - не всегда они приходят легко и сразу.

Согласен. Я понимаю, что equals+hashCode - тривиально, но лично я этого не читал раньше (ну, не люблю ходить к сану на сайт, а в книжках нормального описания не было).

Цитата(RebornCrusader @  15.6.2007,  10:44 Найти цитируемый пост)
Только если уверен, что завтра они не понадобятся ;)

Даже при такой уверенности они могут понядобиться завтра или послезавтра. Но тут уже можно либо сразу всё подозрительное выделять в поля, либо выделять в поле как только потребуется во втором месте.

Цитата(RebornCrusader @  15.6.2007,  10:44 Найти цитируемый пост)
К слову о константах. Читая книжки, натыкаешься чуть ли не на холивары на тему - должны быть они public или private. Хотя на самом деле всё просто - как и остальные члены класса, они должны иметь тот модификатор, который соответствует их необходимости для наследников или внешних классов.

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


--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1174 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.