Три самых сложных проблемы в разработке ПО – это именование переменных, инвалидация кешей, и… порядок объявления полей, методов и параметров. Третье особенно болезненно в Java, потому что в ней нет никаких ограничений по порядку. Например, можно объявить поле в классе, потом десяток методов, а потом опять поле. Когда я вижу такое в коде, у меня сильно бомбит. Считаю, что Java не должна вообще такое позволять. Но с другой стороны, в далёких 90-х не было понятно, какой должен быть строгий порядок, поэтому решили не ограничивать вообще. Например, люди, пришедшие из C++ (а это основная целевая группа в то время), привыкли группировать по области видимости:
Далее я поделюсь моим личным предпочтением относительно порядка.
Порядок объявления членов класса должен быть таким, по моему мнению:
Порядок параметров конструкторов, очевидно, должен соответствовать порядку полей. Если конструкторов несколько, то они должны быть отсортированы по принципу «кто кого дёргает». Если конструктор A вызывает конструктор B, то конструктор A должен быть объявлен выше. Если конструкторы не связаны друг с другом, то выше лучше объявить тот конструктор, у которого поменьше параметров (он более простой и, скорее всего, будет вызываться чаще, поэтому лучше, чтобы он находился читателем кода пораньше).
С методами то же самое: тот, который вызывает, должен быть выше того, кого вызывают. То есть чем ниже мы скроллим класс, тем всё глубже в детали реализации мы погружаемся. Чем ниже, тем более низкоуровневые методы мы видим. Бывает, что методы вызывают друг друга, тогда непонятно, что должно быть выше. Но взаимная рекурсия довольно редкая штука, на самом деле. Сложнее, если методы не связаны друг с другом. В этом случае уже надо подключать здравый смысл и логику: я предпочитаю группировать по функциональности. Связанные вещи должны быть рядом:
Ещё принцип: стабильные параметры должны быть раньше нестабильных. Это не так уж и просто объяснить, что стабильно, а что нет, но попытаюсь опять привести пример:
Также я всегда объявляю лямбды последними. Например:
В общем, как-то так. Такой вот набор правил и принципов я применяю.
Вопросы? Замечания?
class C {
private:
// поля, методы
public:
// поля, методы
}
Я же считаю, что надо группировать по типу членов: поля отдельно, методы отдельно.Далее я поделюсь моим личным предпочтением относительно порядка.
Порядок объявления членов класса должен быть таким, по моему мнению:
class C {
// статические константы (static final)
// статические поля (static)
// final поля
// поля
// конструкторы
// геттеры/сеттеры
// методы
// вложенные классы
}
Порядок самих полей – вещь сложная, надо решать в каждом индивидуальном случае. Строгого правила нет, но можно исходить из здравого смысла: если, например, есть Text inputText и Button okButton, и поле ввода в окошке находится выше кнопки ОК, то и поле inputText должно быть объявлено выше okButton.Порядок параметров конструкторов, очевидно, должен соответствовать порядку полей. Если конструкторов несколько, то они должны быть отсортированы по принципу «кто кого дёргает». Если конструктор A вызывает конструктор B, то конструктор A должен быть объявлен выше. Если конструкторы не связаны друг с другом, то выше лучше объявить тот конструктор, у которого поменьше параметров (он более простой и, скорее всего, будет вызываться чаще, поэтому лучше, чтобы он находился читателем кода пораньше).
С методами то же самое: тот, который вызывает, должен быть выше того, кого вызывают. То есть чем ниже мы скроллим класс, тем всё глубже в детали реализации мы погружаемся. Чем ниже, тем более низкоуровневые методы мы видим. Бывает, что методы вызывают друг друга, тогда непонятно, что должно быть выше. Но взаимная рекурсия довольно редкая штука, на самом деле. Сложнее, если методы не связаны друг с другом. В этом случае уже надо подключать здравый смысл и логику: я предпочитаю группировать по функциональности. Связанные вещи должны быть рядом:
// Функциональность aС порядком параметров методов посложнее – здесь я ещё не до конца выработал правила. Есть только несколько не очень чётких принципов. Один из них: in-параметры, очевидно, должны быть раньше, чем out-параметры. Что такое in- и out-параметры? Суть должна стать понятна на примере:
a() {
aImpl1()
aImpl2()
}
aImpl1() {}
aImpl2() {}
// Функциональность b
b() {
bImpl1()
bImpl2()
}
bImpl1() {}
bImpl2() {}
public void copy(Path from, Path to) {}
Думаю, не стоит пояснять, что in, а что out. Всё очевидно. Что in, а что out, должно вытекать из здравого смысла.Ещё принцип: стабильные параметры должны быть раньше нестабильных. Это не так уж и просто объяснить, что стабильно, а что нет, но попытаюсь опять привести пример:
public void drawPoint(GC gc, int x, int y) {}
public void drawCircle(GC gc, int x, int y, int r) {}
GC – это graphics context. Он более стабилен, чем координаты, потому что создаётся один раз, а рисуется туда много всего и приходит много разных иксов и игреков. Другими словами, если что-то более постоянное и долгоживущее, тем оно более стабильно и должно идти раньше.Также я всегда объявляю лямбды последними. Например:
public void addEvent(EventType type, Runnable r);Иначе будет вот так:
addEvent(() -> {
// 100500 строк кода
}, EventType.MOUSE_CLICK);
Лучше, чтобы MOUSE_CLICK был первым, а после длинной лямбды не шло ничего.В общем, как-то так. Такой вот набор правил и принципов я применяю.
Вопросы? Замечания?
Какой оператор используете для XOR по boolean?
Anonymous Poll
40%
x ^ y
23%
x != y
36%
Никогда не задумывался
Ну что, как вам реклама в Телеграме? Спасибо хоть, что не казино Три Топора 🤣
Как подросла производительность сборщиков мусора с JDK 8 по JDK 17. Увеличилась пропускная способность, уменьшились паузы и уменьшилось потребление памяти (кроме ZGC). Поэтому, если вы тупо перейдёте на Java 17, даже без перекомпиляции, то автоматом всё станет быстрее.
Ссылка.
Ссылка.
В Java 18 появился коммит, который убирает неявную ссылку из анонимного класса в соответствующий внешний класс, если внутренний класс его не использует. Это то, из-за чего раньше настоятельно рекомендовалось использовать лямбды вместо анонимных классов, потому что в лямбдах как раз эти ненужные ссылки не добавляются и объекты внешних классов очищаются вовремя. Теперь же анонимные классы и лямбды будут вести себя одинаково в этом плане. Правда пишут, что это изменение сломало некие тесты в JCK, но это пообещали исследовать и возможно коммит откатывать не придётся.
#java18
#java18
Что вы используете в продакшене? (для тех, кто всё ещё на Java 8, проголосуйте за 4-й вариант)
Final Results
48%
Готовый JDK
18%
Готовый JRE
1%
Собираем свой образ через jlink с нужными модулями
33%
Мы всё ещё на Java 8 (или старее)
YouTube-канал Java преодолел планку в 100 тысяч подписчиков. А вы подписаны?
microJUG
В Java 18 появился коммит, который убирает неявную ссылку из анонимного класса в соответствующий внешний класс, если внутренний класс его не использует. Это то, из-за чего раньше настоятельно рекомендовалось использовать лямбды вместо анонимных классов, потому…
Выбрасывание неявной ссылки на внешний класс уже попало в последнюю сборку JDK 18-ea+26. Откатывать, слава богу, ничего не будут. Я проверил, this$0 действительно исчезает, если анонимный класс не использует ссылку. Но есть один нюанс: если класс является Serializable и нету поля serialVersionUID, то ссылка остаётся :(. Например, в таком анонимном классе this$0 будет всё равно присутствовать:
Так что новая оптимизация вылечит далеко не все случаи. А любителям double brace initialization придётся писать вот так, чтобы избежать ссылки:
new ArrayList<>() {
...
}
Сериализуемых классов в JDK весьма много. Например, практически все коллекции.Так что новая оптимизация вылечит далеко не все случаи. А любителям double brace initialization придётся писать вот так, чтобы избежать ссылки:
var list = new ArrayList<>() {public static final long serialVersionUID = 1L;{
add(1); }};
#java18👍1
"Java не столь популярна у современных разработчиков"
Всё, пацаны, расходимся 🤷♂️
https://zona.media/news/2021/12/11/log4fun
Всё, пацаны, расходимся 🤷♂️
https://zona.media/news/2021/12/11/log4fun
Медиазона
Уязвимость в распространенной библиотеке Log4j для Java поставила под угрозу безопасность крупнейших сервисов и приложений
Уязвимость в широко используемой библиотеке логирования Apache Log4j для программной платформы Java поставила под угроз...
👍1🔥1