Новая LTS Java.
Я о Java 25.
Вышла не вчера, поэтому также вышла и хорошая статья с обзором нововведений https://habr.com/ru/companies/T1Holding/articles/946778/.
Там даже табличка включения новых фич от 21 до 25 версии есть. И примеры кода - было\стало.
И от меня как всегда пару комментариев)
Для начала бросаются в глаза две фичи со "странным" названием Quantum-Resistant ...
Почему бросаются - квантовые компьютеры ожидаются в промышленном использовании в течение 10+ лет, а устойчивые к взлому квантовым компьютером алгоритмы в Java появились уже сейчас.
С - стратегия.
Б - банковское ПО)
Три фичи со словами Ahead-of-Time, главная из них - Ahead-of-Time Class Loading & Linking.
Это дальнейшее развитие темы CDS https://t.me/javaKotlinDevOps/316
Т.е. ускорение старта приложения.
Если CDS убирает этап верификации классов сохраняя в архиве уже проверенные классы,
то Ahead-of-Time Class Loading & Linking как следует из названия сохраняет всю необходимую для работы с классами информацию. Так сказать в распакованном виде, поэтому ее сразу можно грузить в Metaspace.
Одно но: набор классов у всех разный, поэтому нужно запустить приложение в тестовом режиме и собрать данные по актуальным классам, которые и будут сохранены в архиве.
Заодно сохраняется и статистика их использования (Ahead-of-Time Method Profiling), что позволяет при старте JVM сразу запустить компиляцию часто используемых методов.
Последняя фича - это offline Profile-Guided Optimization https://t.me/javaKotlinDevOps/315, которая ранее была killer feature коммерческих JVM: Azul ReadyNow и GraalVM Enterprise Native Image.
Итоговое ускорение загрузки: 42% vs 33% у CDS https://www.happycoders.eu/java/ahead-of-time-class-loading-and-linking/
Есть еще две оптимизационные фичи: Compact Object Headers и Linking Run-Time Images without JMODs.
Первая уменьшает размер любого объекта в памяти, оптимизируя заголовки. Вторая - уменьшает объем JDK, убирая оттуда JMOD файлы. JMOD появились вместе с модулями Java как развитие jar.
И классы в jmod файлах уже есть в JDK, т.е. имеем дублирование. Сейчас его убрали, размер JDK стал меньше на 25%. Важно в облаках с тысячами микросервисов.
На самом деле технология модулей в Java до сих пор не прижилась в коммерческой разработке, но команда Java не сдается)
Module Import Declarations - можно разом импортировать все классы в модуле. С одной стороны загрязняется область видимости, с другой - удобно.
Markdown Documentation Comments: Markdown - стандарт документации в ИТ в целом, получаем больше возможностей в JavaDoc. Да, JavaDoc нужны не всегда, но пригодится.
Фичи с JFR в названии - допилен профайлер: меньше влияние на исполнение кода (JFR Cooperative Sampling), больше данных (JFR Method Timing & Tracing).
Unnamed Variables & Patterns: _ (подчеркивание) обозначает для компилятора и валидаторов неиспользуемую переменную. Java пополнила длинный список языков, где это уже есть)
Scoped Values - более безопасный вариант Thread Local.
Также дошли до prod ready версии фичи из моего поста про Java 22 https://t.me/javaKotlinDevOps/278
* Launch Multi-File Source-Code Programs
* Implicitly Declared Classes and Instance Main Methods
* Stream Gatherers
* Class-File API
* Statements before super
Итого - решаются проблемы с производительностью и объемом, допиливается функционал (стримы, модули, JFR, Thread Local, GC), стандартизируются API (Class-File API), немного синтаксического сахара (_).
А String templates https://t.me/javaKotlinDevOps/246 выкинули. Слишком отличается от мэйнстрима, я про идею процессора STR."xxx", обрабатывающего строки
#java #jdk #java_new_version
Я о Java 25.
Вышла не вчера, поэтому также вышла и хорошая статья с обзором нововведений https://habr.com/ru/companies/T1Holding/articles/946778/.
Там даже табличка включения новых фич от 21 до 25 версии есть. И примеры кода - было\стало.
И от меня как всегда пару комментариев)
Для начала бросаются в глаза две фичи со "странным" названием Quantum-Resistant ...
Почему бросаются - квантовые компьютеры ожидаются в промышленном использовании в течение 10+ лет, а устойчивые к взлому квантовым компьютером алгоритмы в Java появились уже сейчас.
С - стратегия.
Б - банковское ПО)
Три фичи со словами Ahead-of-Time, главная из них - Ahead-of-Time Class Loading & Linking.
Это дальнейшее развитие темы CDS https://t.me/javaKotlinDevOps/316
Т.е. ускорение старта приложения.
Если CDS убирает этап верификации классов сохраняя в архиве уже проверенные классы,
то Ahead-of-Time Class Loading & Linking как следует из названия сохраняет всю необходимую для работы с классами информацию. Так сказать в распакованном виде, поэтому ее сразу можно грузить в Metaspace.
Одно но: набор классов у всех разный, поэтому нужно запустить приложение в тестовом режиме и собрать данные по актуальным классам, которые и будут сохранены в архиве.
Заодно сохраняется и статистика их использования (Ahead-of-Time Method Profiling), что позволяет при старте JVM сразу запустить компиляцию часто используемых методов.
Последняя фича - это offline Profile-Guided Optimization https://t.me/javaKotlinDevOps/315, которая ранее была killer feature коммерческих JVM: Azul ReadyNow и GraalVM Enterprise Native Image.
Итоговое ускорение загрузки: 42% vs 33% у CDS https://www.happycoders.eu/java/ahead-of-time-class-loading-and-linking/
Есть еще две оптимизационные фичи: Compact Object Headers и Linking Run-Time Images without JMODs.
Первая уменьшает размер любого объекта в памяти, оптимизируя заголовки. Вторая - уменьшает объем JDK, убирая оттуда JMOD файлы. JMOD появились вместе с модулями Java как развитие jar.
И классы в jmod файлах уже есть в JDK, т.е. имеем дублирование. Сейчас его убрали, размер JDK стал меньше на 25%. Важно в облаках с тысячами микросервисов.
На самом деле технология модулей в Java до сих пор не прижилась в коммерческой разработке, но команда Java не сдается)
Module Import Declarations - можно разом импортировать все классы в модуле. С одной стороны загрязняется область видимости, с другой - удобно.
Markdown Documentation Comments: Markdown - стандарт документации в ИТ в целом, получаем больше возможностей в JavaDoc. Да, JavaDoc нужны не всегда, но пригодится.
Фичи с JFR в названии - допилен профайлер: меньше влияние на исполнение кода (JFR Cooperative Sampling), больше данных (JFR Method Timing & Tracing).
Unnamed Variables & Patterns: _ (подчеркивание) обозначает для компилятора и валидаторов неиспользуемую переменную. Java пополнила длинный список языков, где это уже есть)
Scoped Values - более безопасный вариант Thread Local.
Также дошли до prod ready версии фичи из моего поста про Java 22 https://t.me/javaKotlinDevOps/278
* Launch Multi-File Source-Code Programs
* Implicitly Declared Classes and Instance Main Methods
* Stream Gatherers
* Class-File API
* Statements before super
Итого - решаются проблемы с производительностью и объемом, допиливается функционал (стримы, модули, JFR, Thread Local, GC), стандартизируются API (Class-File API), немного синтаксического сахара (_).
А String templates https://t.me/javaKotlinDevOps/246 выкинули. Слишком отличается от мэйнстрима, я про идею процессора STR."xxx", обрабатывающего строки
#java #jdk #java_new_version
Хабр
Возвращение LTS: ты не пройдёшь… мимо новых фич Java 25
В одной из моих предыдущих статей я писал о фичах между LTS-версиями Java 17 и 21 . Сегодня, два года спустя ( Как?! Уже два года?! ), выходит новый LTS-релиз — Java 25 . Подавляющее большинство...
Серия "хозяйке на заметку", а точнее разработчику библиотек на заметку.
Разработка библиотек отличается от разработки приложения тем, что публичные API в них живут намного дольше, и об этом надо помнить.
Любое публичное API, т.е. все public классы и методы, должно быть обратно совместимым как минимум в текущей мажорной версии.
Но жизнь как всегда сложнее. И что же у нас есть?
Java
1) объявить метод устаревшим с какой-то версии - @Deprecated.
Причем эту аннотацию можно не просто повесить на метод, у нее есть два поля: forRemoval и since, см. https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Deprecated.html
2) указать на что заменяем метод. @Deprecated не предоставляет такого механизма.
Но есть на свете добрые люди: https://errorprone.info/docs/inlineme
Как это может быть использовано:
а) статический анализ, собственно errorprone плагин: https://errorprone.info/docs/installation
б) миграция: https://docs.openrewrite.org/recipes/java/logging/log4j/inlinemethods
3) скрыть метод для потребителей не удаляя его из кодовой базы библиотеки. Т.е. оставляя его для тулов или для внутреннего использования. Java - снова нет( И даже добрые не помогли(
4) указать степень зрелости API. Стандартно - опять нет, но есть такая библиотечка @API Guardian https://github.com/apiguardian-team/apiguardian, позволяющая пометить API примерно так:
Используется в JUnit, к слову.
Более простая альтернатива: @Beta из Guava, https://guava.dev/releases/23.4-jre/api/docs/com/google/common/annotations/Beta.html
5) потребовать у клиента явного подтверждения в коде, что он готов использовать бета-версию, а не просто warning компилятора - увы, нет.
Kotlin
1) @Deprecated
2) @Deprecated(replaceWith) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-replace-with/
3) @Deprecated(level) https://www.baeldung.com/kotlin/deprecation
4-5) Механизм Opt-In: https://kotlinlang.org/docs/opt-in-requirements.html#opt-in-to-inherit-from-a-class-or-interface
Все это, естественно, поддерживается в IDEA из коробки.
Плюс в Kotlin можно использовать @API Guardian
Получилась реклама Kotlin, что не удивительно, учитывая время его появления и назначение языка.
#api #java #kotlin
Разработка библиотек отличается от разработки приложения тем, что публичные API в них живут намного дольше, и об этом надо помнить.
Любое публичное API, т.е. все public классы и методы, должно быть обратно совместимым как минимум в текущей мажорной версии.
Но жизнь как всегда сложнее. И что же у нас есть?
Java
1) объявить метод устаревшим с какой-то версии - @Deprecated.
Причем эту аннотацию можно не просто повесить на метод, у нее есть два поля: forRemoval и since, см. https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Deprecated.html
2) указать на что заменяем метод. @Deprecated не предоставляет такого механизма.
Но есть на свете добрые люди: https://errorprone.info/docs/inlineme
Как это может быть использовано:
а) статический анализ, собственно errorprone плагин: https://errorprone.info/docs/installation
б) миграция: https://docs.openrewrite.org/recipes/java/logging/log4j/inlinemethods
3) скрыть метод для потребителей не удаляя его из кодовой базы библиотеки. Т.е. оставляя его для тулов или для внутреннего использования. Java - снова нет( И даже добрые не помогли(
4) указать степень зрелости API. Стандартно - опять нет, но есть такая библиотечка @API Guardian https://github.com/apiguardian-team/apiguardian, позволяющая пометить API примерно так:
@API(status = STABLE, since = "1.0")
public class StableService {
@API(status = EXPERIMENTAL)
public void experimentalMethod() {
}
@API(status = DEPRECATED, since = "2.0")
public void deprecatedMethod() {
}
@API(status = INTERNAL)
public void internalMethod() {
}
}
Используется в JUnit, к слову.
Более простая альтернатива: @Beta из Guava, https://guava.dev/releases/23.4-jre/api/docs/com/google/common/annotations/Beta.html
5) потребовать у клиента явного подтверждения в коде, что он готов использовать бета-версию, а не просто warning компилятора - увы, нет.
Kotlin
1) @Deprecated
2) @Deprecated(replaceWith) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-replace-with/
3) @Deprecated(level) https://www.baeldung.com/kotlin/deprecation
4-5) Механизм Opt-In: https://kotlinlang.org/docs/opt-in-requirements.html#opt-in-to-inherit-from-a-class-or-interface
// Library code
@RequiresOptIn(message = "This API is experimental. It could change in the future without notice.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class MyDateTime
@MyDateTime
// A class requiring opt-in
class DateProvider
// Client code
@OptIn(MyDateTime::class)
// Uses DateProvider
fun getDate(): Date {
val dateProvider: DateProvider
// ...
}
Все это, естественно, поддерживается в IDEA из коробки.
Плюс в Kotlin можно использовать @API Guardian
Получилась реклама Kotlin, что не удивительно, учитывая время его появления и назначение языка.
#api #java #kotlin
Oracle
Deprecated (Java SE 17 & JDK 17)
declaration: module: java.base, package: java.lang, annotation type: Deprecated
null safety в Java - счастье на горизонте?)
Я уже писал про проблему null safety в Java, особенно ярко видимую на фоне Kotlin.
https://t.me/javaKotlinDevOps/98
В посте по ссылке выше разработчики Kotlin собрали поддерживаемые ими виды аннотаций а-ля @NotNull https://kotlinlang.org/docs/java-interop.html#nullability-annotations
И их число говорит о многом, а точнее о состоянии разброда и шатания в Java мире.
Так вот - похоже в войне Nullable аннотаций наметился победитель, и это JSpecify https://jspecify.dev/docs/user-guide/.
С одной стороны это очередная внешняя библиотека:
Которую поддерживает IDEA при поиске проблем. Но она и другие библиотеки поддерживает.
Что же изменилось?
А то, что собрался ряд достаточно известных компаний: Google, Oracle, JetBrains, Uber, VMware/Broadcom (а значит и Spring), и они стандартизировали именно JSpecify.
Что это значит, ряд примеров:
1) Spring переводит свой фреймворк на JSpecify к Spring 7\Spring Boot 4
2) про JetBrains и IDEA c Kotlin я уже сказал
3) Google внедряет новые аннотации в Guava. И наверняка куда-то еще)
...
Две основные фишки нового подхода:
1) Uber доработала плагин компилятора NullAway на основе errorprone:
и warning в IDEA легким движением руки превращается в error компиляции.
Работает в JDK 17,21 и 22+ https://bugs.openjdk.org/browse/JDK-8225377
Аналогично можно сделать в Maven.
2) Другое важное изменение - возможность задавать значение null safety по умолчанию для пакета, модуля или класса.
Эти объявления означают, что все поля и переменные в классе или пакете должны быть not null.
А если null значение все же нужно - нужно явно пометить его аннотацией @Null
Чтобы заменить старые аннотации на новые есть правила OpenRewrite https://docs.openrewrite.org/recipes/java/jspecify/jspecifybestpractices
Пару ложек дегтя:
1) Oracle в JDK пока аннотации не внедряет. Зато JDK пропатчила начиная с 17-й, чтобы валидация на этапе компиляции заработала.
2) Hibernate присматривается https://github.com/hibernate/hibernate-orm/discussions/6220.
Что я могу сказать в итоге - удачи, дело нужное!
А в прикладе внедрять уже можно. Ситуация НЕ похожа на известную шутку: было 10 разных стандартов, люди решили это изменить и их стало одиннадцать)
Проблема есть, и массовому внедрению ее решения мешал по большому счету тот факт, что единого решения не было.
#null_safety #java
Я уже писал про проблему null safety в Java, особенно ярко видимую на фоне Kotlin.
https://t.me/javaKotlinDevOps/98
В посте по ссылке выше разработчики Kotlin собрали поддерживаемые ими виды аннотаций а-ля @NotNull https://kotlinlang.org/docs/java-interop.html#nullability-annotations
И их число говорит о многом, а точнее о состоянии разброда и шатания в Java мире.
Так вот - похоже в войне Nullable аннотаций наметился победитель, и это JSpecify https://jspecify.dev/docs/user-guide/.
С одной стороны это очередная внешняя библиотека:
dependencies {
implementation 'org.jspecify:jspecify:1.0.0'
....
}Которую поддерживает IDEA при поиске проблем. Но она и другие библиотеки поддерживает.
Что же изменилось?
А то, что собрался ряд достаточно известных компаний: Google, Oracle, JetBrains, Uber, VMware/Broadcom (а значит и Spring), и они стандартизировали именно JSpecify.
Что это значит, ряд примеров:
1) Spring переводит свой фреймворк на JSpecify к Spring 7\Spring Boot 4
2) про JetBrains и IDEA c Kotlin я уже сказал
3) Google внедряет новые аннотации в Guava. И наверняка куда-то еще)
...
Две основные фишки нового подхода:
1) Uber доработала плагин компилятора NullAway на основе errorprone:
tasks.withType(JavaCompile).configureEach {
options.errorprone {
disableAllChecks = true // Other error prone checks are disabled
option("NullAway:OnlyNullMarked", "true") // Enable nullness checks only in null-marked code
error("NullAway") // bump checks from warnings (default) to errors
option("NullAway:JSpecifyMode", "true") // https://github.com/uber/NullAway/wiki/JSpecify-Support
}
}и warning в IDEA легким движением руки превращается в error компиляции.
Работает в JDK 17,21 и 22+ https://bugs.openjdk.org/browse/JDK-8225377
Аналогично можно сделать в Maven.
2) Другое важное изменение - возможность задавать значение null safety по умолчанию для пакета, модуля или класса.
@NullMarked
package org.example;
@NullMarked
class MyClass {
Эти объявления означают, что все поля и переменные в классе или пакете должны быть not null.
А если null значение все же нужно - нужно явно пометить его аннотацией @Null
Чтобы заменить старые аннотации на новые есть правила OpenRewrite https://docs.openrewrite.org/recipes/java/jspecify/jspecifybestpractices
Пару ложек дегтя:
1) Oracle в JDK пока аннотации не внедряет. Зато JDK пропатчила начиная с 17-й, чтобы валидация на этапе компиляции заработала.
2) Hibernate присматривается https://github.com/hibernate/hibernate-orm/discussions/6220.
Что я могу сказать в итоге - удачи, дело нужное!
А в прикладе внедрять уже можно. Ситуация НЕ похожа на известную шутку: было 10 разных стандартов, люди решили это изменить и их стало одиннадцать)
Проблема есть, и массовому внедрению ее решения мешал по большому счету тот факт, что единого решения не было.
#null_safety #java
Telegram
(java || kotlin) && devOps
Всем привет!
Небольшое замечание. О важности проблемы null safety в Java говорит вот этот список различных видов @Null\@NotNull аннотаций Java, которые поддерживает Kotlin при проверке типов: https://kotlinlang.org/docs/java-interop.html#nullability-annotations…
Небольшое замечание. О важности проблемы null safety в Java говорит вот этот список различных видов @Null\@NotNull аннотаций Java, которые поддерживает Kotlin при проверке типов: https://kotlinlang.org/docs/java-interop.html#nullability-annotations…
🔥2
Концепция venv (virtualenv) в Python
Концепция крутая, как по мне ноутбуки и виртуальные окружения - две самые крутые фичи в Python.
Если вкратце о ее сути: ты создаешь для каждого проекта отдельную виртуальную среду, со своим интерпретатором Python (разные версии) и своим набором библиотек.
Это удобно, и решает проблему конфликта зависимостей. Небольшое уточнение: если бы все сервисы и библиотеки явно указывали версии зависимостей - конфликтов бы не было, но мы же говорим о реальном мире.
К слову, концепцию позаимствовала и Java, я про jenv - https://t.me/javaKotlinDevOps/442 - правда, ограничить можно только версию Java.
Но блин.
Почему утилит, реализующих виртуальные окружения столько:
- venv
- virtualenv
- uv
- Poetry
- PDM
- Hatch
- Rye
- Conda
- Mamba
- Micromamba
- Pixi
- Pipenv
- pyenv-virtualenv
- virtualenvwrapper
- Tox
- Nox
- Devbox
- Flox
- Devenv.sh
- Spack
- Vex
????
Явная иллюстрация анекдота про 10 стандартов)
Ясно, что они не идентичны по функционалу.
1) кто-то добавляет возможность менеджера пакетов (и это правильно),
2) кто-то позволяет формировать список зависимостей проекта requirements.txt (и это тоже правильно),
3) кто-то добавляет возможность делать lock зависимостей (спорная фича IMHO).
Кто-то просто устарел. Кто-то заточен для тестов, где нужна куча разных сред. Кто-то просто добавляет небольшие фишки в другой менеджер, типа убирает необходимость явно включать использование виртуального окружения в консоли (activate).
Но все же...
Причем 4 из них имеют официальный статус)
P.S. Самой крутой и современной считается uv. На данный момент.
#python #java #virtual_env
Концепция крутая, как по мне ноутбуки и виртуальные окружения - две самые крутые фичи в Python.
Если вкратце о ее сути: ты создаешь для каждого проекта отдельную виртуальную среду, со своим интерпретатором Python (разные версии) и своим набором библиотек.
Это удобно, и решает проблему конфликта зависимостей. Небольшое уточнение: если бы все сервисы и библиотеки явно указывали версии зависимостей - конфликтов бы не было, но мы же говорим о реальном мире.
К слову, концепцию позаимствовала и Java, я про jenv - https://t.me/javaKotlinDevOps/442 - правда, ограничить можно только версию Java.
Но блин.
Почему утилит, реализующих виртуальные окружения столько:
- venv
- virtualenv
- uv
- Poetry
- PDM
- Hatch
- Rye
- Conda
- Mamba
- Micromamba
- Pixi
- Pipenv
- pyenv-virtualenv
- virtualenvwrapper
- Tox
- Nox
- Devbox
- Flox
- Devenv.sh
- Spack
- Vex
????
Явная иллюстрация анекдота про 10 стандартов)
Ясно, что они не идентичны по функционалу.
1) кто-то добавляет возможность менеджера пакетов (и это правильно),
2) кто-то позволяет формировать список зависимостей проекта requirements.txt (и это тоже правильно),
3) кто-то добавляет возможность делать lock зависимостей (спорная фича IMHO).
Кто-то просто устарел. Кто-то заточен для тестов, где нужна куча разных сред. Кто-то просто добавляет небольшие фишки в другой менеджер, типа убирает необходимость явно включать использование виртуального окружения в консоли (activate).
Но все же...
Причем 4 из них имеют официальный статус)
P.S. Самой крутой и современной считается uv. На данный момент.
#python #java #virtual_env
Telegram
(java || kotlin) && devOps
Жонглирование JDK
Иногда нужно вести разработку нескольких сервисов, требующих разных версий JDK. Или нескольких релизов одного и того же сервиса. Или какое-то ПО на компьютере требует одной версии JDK, а разработка другой.
Все эти проблемы решает утилита…
Иногда нужно вести разработку нескольких сервисов, требующих разных версий JDK. Или нескольких релизов одного и того же сервиса. Или какое-то ПО на компьютере требует одной версии JDK, а разработка другой.
Все эти проблемы решает утилита…
Что не докрутили в record-ах?
Для начала кратко о том, что докрутили:
1) компактное объявление, типовые методы из коробки
2) иммутабельность
3) минимально необходимая расширяемость - дополнительные конструкторы, интерфейсы, обычные методы, статические поля, методы и внутренние классы.
Получаем аналог data class в Kotlin. Или структур из древних языков типа C.
Но с небольшим отличием - не хватает метода копирования "из коробки".
Почему так сделали? Есть же Cloneable интерфейс. И его даже можно добавить в record руками.
Думаю, причина в иммутабельности record и скажем так скомпрометированности clone().
Для иммутабельной сущности нет смысла в полной копии - можно использовать текущий объект.
С clone() основная проблема в том, что "из коробки" он делает поверхностную копию, но при переопределении может дать полную. И вообще полную копию автоматически сделать сложно. А это приводит к путанице - метод один, а поведение может отличаться.
В итоге приходим к тому, что иметь возможность быстро сделать поверхностную копию записи с изменением пары полей было бы неплохо. И такой JEP есть https://openjdk.org/jeps/468
Надеюсь внедрят.
#java #иммутабельность
Для начала кратко о том, что докрутили:
1) компактное объявление, типовые методы из коробки
2) иммутабельность
3) минимально необходимая расширяемость - дополнительные конструкторы, интерфейсы, обычные методы, статические поля, методы и внутренние классы.
Получаем аналог data class в Kotlin. Или структур из древних языков типа C.
Но с небольшим отличием - не хватает метода копирования "из коробки".
Почему так сделали? Есть же Cloneable интерфейс. И его даже можно добавить в record руками.
Думаю, причина в иммутабельности record и скажем так скомпрометированности clone().
Для иммутабельной сущности нет смысла в полной копии - можно использовать текущий объект.
С clone() основная проблема в том, что "из коробки" он делает поверхностную копию, но при переопределении может дать полную. И вообще полную копию автоматически сделать сложно. А это приводит к путанице - метод один, а поведение может отличаться.
В итоге приходим к тому, что иметь возможность быстро сделать поверхностную копию записи с изменением пары полей было бы неплохо. И такой JEP есть https://openjdk.org/jeps/468
Надеюсь внедрят.
#java #иммутабельность
Снова минутка цитат на канале:
Лично я вижу смысл в этом термине. И суть его в том, что в мире победившего ООП не стоит забывать об операциях (функциях) и о простоте.
Я уже писал про структурный дизайн - https://t.me/javaKotlinDevOps/400.
Напомню, там была речь о том, что не обязательно заводить кучу объектов и интерфейсов, если процесс простой и раскладывается на три части - подготовка данных, преобразования и запись.
Тогда его можно реализовать в виде сервиса, "чистой" модели и репозитория. К слову: ETL = Extract -> Transform -> Load - о том же.
Так вот - структурное программирование тоже раскладывает любой процесс на три части, только уже на уровне метода: последовательный код, условия и циклы.
Казалось бы - ну да, очевидно это так. Но есть нюанс - тут речь идет о проблеме множественных выходов из метода.
Структурное программирование появилось как ответ на широкое распространение оператора go to и призвано бороться с ним.
Опять вопрос - go to мы победили, тогда зачем эти "предания старины глубокой"?
Нет, не победили. Точнее победили, но не до конца.
Т.к. у нас есть множественный return и throw. А если копнуть глубже, и расширить проблему на любые прыжки по коду - break и continue.
Надо ли от них отказываться, учитывая что парадигма то вроде полезная?
На мой взгляд - нет.
Охранные выражения (guard pattern) - однозначно полезны.
throw для сигнализации об ошибке - тоже ок, они для этого создавались.
С рядом условий:
1) unchecked
2) не надо просто для передачи управления
3) должен быть определен слой\процесс перехвата исключений на уровне сервиса
break и continue - если без них код сложнее читать - тоже допустимы. Прыжки то небольшие, в рамках цикла. Хотя я ими пользуюсь редко, кейсов мало.
Т.е. снова приходим к искусству компромиссов.
Всякий раз, перед написанием такого оператора стоит подумать - нет ли других вариантов? Не усложняется ли он чтение и понимание кода?
Суть структурного программирования - код каждой операции должен просто читаться. Нет "спагетти-коду"!
#book_review #java #code #structure_programming #structure_xxx #principles
«Термин „структурное программирование“ был введён в 1969 году.
С тех пор термин „структурный“ применялся к любой деятельности в области ПО, включая структурный анализ, структурный дизайн и структурное валяние дурака».
Стив Макконнелл «Совершенный код».
Лично я вижу смысл в этом термине. И суть его в том, что в мире победившего ООП не стоит забывать об операциях (функциях) и о простоте.
Я уже писал про структурный дизайн - https://t.me/javaKotlinDevOps/400.
Напомню, там была речь о том, что не обязательно заводить кучу объектов и интерфейсов, если процесс простой и раскладывается на три части - подготовка данных, преобразования и запись.
Тогда его можно реализовать в виде сервиса, "чистой" модели и репозитория. К слову: ETL = Extract -> Transform -> Load - о том же.
Так вот - структурное программирование тоже раскладывает любой процесс на три части, только уже на уровне метода: последовательный код, условия и циклы.
Казалось бы - ну да, очевидно это так. Но есть нюанс - тут речь идет о проблеме множественных выходов из метода.
Структурное программирование появилось как ответ на широкое распространение оператора go to и призвано бороться с ним.
Опять вопрос - go to мы победили, тогда зачем эти "предания старины глубокой"?
Нет, не победили. Точнее победили, но не до конца.
Т.к. у нас есть множественный return и throw. А если копнуть глубже, и расширить проблему на любые прыжки по коду - break и continue.
Надо ли от них отказываться, учитывая что парадигма то вроде полезная?
На мой взгляд - нет.
Охранные выражения (guard pattern) - однозначно полезны.
throw для сигнализации об ошибке - тоже ок, они для этого создавались.
С рядом условий:
1) unchecked
2) не надо просто для передачи управления
3) должен быть определен слой\процесс перехвата исключений на уровне сервиса
break и continue - если без них код сложнее читать - тоже допустимы. Прыжки то небольшие, в рамках цикла. Хотя я ими пользуюсь редко, кейсов мало.
Т.е. снова приходим к искусству компромиссов.
Всякий раз, перед написанием такого оператора стоит подумать - нет ли других вариантов? Не усложняется ли он чтение и понимание кода?
Суть структурного программирования - код каждой операции должен просто читаться. Нет "спагетти-коду"!
#book_review #java #code #structure_programming #structure_xxx #principles
Telegram
(java || kotlin) && devOps
Всем привет!
Я уже писал про то, что не люблю код, в котором интерфейсы делаются ради интерфейсов. Самый яркий антипаттерн: интерфейс с единственной реализацией, лежащей рядом. Подозреваю, одной из причин такого проектирования является принцип Dependency…
Я уже писал про то, что не люблю код, в котором интерфейсы делаются ради интерфейсов. Самый яркий антипаттерн: интерфейс с единственной реализацией, лежащей рядом. Подозреваю, одной из причин такого проектирования является принцип Dependency…
Медленная загрузка сервиса - значит Java?)
Есть такая проблема у Java, в частности при использовании Spring Framework. А точнее когда поверх Spring-а накручиваются свои компоненты.
Загружается куча классов, много кода инициализации = много времени. Как с этим борются - см. по тэгу #java_start_boost
Но только ли это проблема Java?
Запускал небольшую AI модельку на Python. Один скрипт. Скрипт стартует более 20 секунд.
Ну, думаю, модель так долго грузится. Померил - нет, модель порядка 3 секунд. Она уже в виде кэша скачана на локальный компьютер, да и не LLM это.
Антивирус? Интерпретатор Python?
Нет, всего лишь библиотека sentence-transformers.
На самом деле конечно не всего лишь. Она под капотом грузит движок для инференса - PyTorch. Плюс другие зависимости.
Но за 20 секунд старта ответственна именно строчка c импортом:
Тут еще видится "выстрелил" высокий уровень абстракции, принятый в Python.
Пишешь пару строк - у тебя все работает. Удобно? Да. Но есть нюансы)
Вывод - высокий уровень может превратится в айсберг. Ты видишь вершину, а под ней еще...
#python #java
Есть такая проблема у Java, в частности при использовании Spring Framework. А точнее когда поверх Spring-а накручиваются свои компоненты.
Загружается куча классов, много кода инициализации = много времени. Как с этим борются - см. по тэгу #java_start_boost
Но только ли это проблема Java?
Запускал небольшую AI модельку на Python. Один скрипт. Скрипт стартует более 20 секунд.
Ну, думаю, модель так долго грузится. Померил - нет, модель порядка 3 секунд. Она уже в виде кэша скачана на локальный компьютер, да и не LLM это.
Антивирус? Интерпретатор Python?
Нет, всего лишь библиотека sentence-transformers.
На самом деле конечно не всего лишь. Она под капотом грузит движок для инференса - PyTorch. Плюс другие зависимости.
Но за 20 секунд старта ответственна именно строчка c импортом:
from sentence_transformers import SentenceTransformer
Тут еще видится "выстрелил" высокий уровень абстракции, принятый в Python.
Пишешь пару строк - у тебя все работает. Удобно? Да. Но есть нюансы)
Вывод - высокий уровень может превратится в айсберг. Ты видишь вершину, а под ней еще...
#python #java
Сложно не заметить, что последние пару месяцев у меня основная тема блока - "жемчужины" из книги Совершенный код.
Сегодня еще один пост, пост-"мысль вслух".
Самое удивительное в этой книжке - это два факта:
1) на английском она издана в 2004 году
2) она актуальна.
Я пытаюсь вспомнить, что же там устарело и вспоминаю лишь следующее:
а) в Java появились Enum (на тот момент еще нет)
б) Visual Basic умер (там есть примеры в числе прочего на VB)
в) IDE стали сильно лучше, считать открывающие и закрывающие скобки самому уже не надо
г) кажется все языки получили свой аналог xUnit, "костылить" свой подобный фреймворк тоже не надо
д) у нас есть git и история изменений в IDEA, "прихранивать" копию исходников перед изменением не нужно
е) на способы проверки повреждения данных в памяти из-за кривых указателей смотришь с ужасом, но все такие главы подписаны - для C\C++ и при желании их можно пропускать. Да и скорее всего большая часть этой информации актуальна до сих пор.
И пожалуй это все! За 20+ лет.
Даже обсуждение go to и глобальных переменных лишь на первый взгляд кажется не актуальным для Java...
Вот как надо книжки писать!
Вспоминается: "Новые песни сочиняет тот, у кого старые плохие". И это тот редкий случай, когда фраза справедлива)
#book_review #java
Сегодня еще один пост, пост-"мысль вслух".
Самое удивительное в этой книжке - это два факта:
1) на английском она издана в 2004 году
2) она актуальна.
Я пытаюсь вспомнить, что же там устарело и вспоминаю лишь следующее:
а) в Java появились Enum (на тот момент еще нет)
б) Visual Basic умер (там есть примеры в числе прочего на VB)
в) IDE стали сильно лучше, считать открывающие и закрывающие скобки самому уже не надо
г) кажется все языки получили свой аналог xUnit, "костылить" свой подобный фреймворк тоже не надо
д) у нас есть git и история изменений в IDEA, "прихранивать" копию исходников перед изменением не нужно
е) на способы проверки повреждения данных в памяти из-за кривых указателей смотришь с ужасом, но все такие главы подписаны - для C\C++ и при желании их можно пропускать. Да и скорее всего большая часть этой информации актуальна до сих пор.
И пожалуй это все! За 20+ лет.
Даже обсуждение go to и глобальных переменных лишь на первый взгляд кажется не актуальным для Java...
Вот как надо книжки писать!
Вспоминается: "Новые песни сочиняет тот, у кого старые плохие". И это тот редкий случай, когда фраза справедлива)
#book_review #java
💯5
Магические 80% покрытия кода тестами.
Часто возникает вопрос - почему 80?
Краткий ответ - почему бы и нет)
А если серьезно: оценка может быть числовой (процент покрытия) или бинарной (достаточно или нет).
Бинарная плоха тем, что не документирована и зависит от мнения эксперта. Это может привести к проблемам на код-ревью.
А тут умные люди из SonarQube придумали метрику покрытия https://docs.sonarsource.com/sonarqube-server/user-guide/code-metrics/metrics-definition#coverage
и дали её рекомендуемое значение. И это не 100%, т.е. запас есть.
Считаю, что от этой рекомендации стоит отталкиваться.
К тому же JaCoCo, обычно используемый для расчета покрытия, позволяет гибко настраивать сам процесс.
Следующий вопрос, который может возникнуть: "Почему ради достижения 80% я должен писать тесты на элементарный код?" Я про getter, setter и все, все, все https://t.me/javaKotlinDevOps/34
Ответ: "Нет, не нужны эти тесты".
Лишний код можно исключить из покрытия:
1) generated код исключается по умолчанию начиная с JaCoCo 0.8.2
2) generated код Lombok - через lombok.addLombokGeneratedAnnotation = true (жаль, что только для Lombok это можно сделать, но есть еще альтернатива - см. следующий абзац.)
3) тривиальный код - явно исключая классы или пакеты по маске через настройки JaCoCo. Если какой-то код не получается исключить таким образом - это повод задуматься о рефакторинге.
Еще вопрос: "Зачем писать модульные (unit) тесты ради покрытия на интеграционный код: сервисные классы или классы контроллеров, которые представляют линейную цепочку вызовов методов?"
Ответ: "Не обязательно писать unit тесты".
Для простых микросервисов является нормальной перевернутая пирамида тестирования - когда интеграционных тестов разработки больше, чем модульных.
Простой код можно покрыть интеграционными тестами, включив их в общее покрытие. JaCoCo позволяет это настроить. Единственная проблема может быть, если тесты находятся в одном модуле, а код для покрытия - в другом, но и она решается.
И тут может возникнуть самый главный вопрос - а это не читерство? Чем это лучше отсутствия цели по покрытию?
Ответ: лучше тем, что мы четко задаем - вот это код не нужно покрывать тестами, а остальной - нужно.
И смотря на паттерны исключения - на их состав и количество - можно их быстро оценить и при необходимости скорректировать.
Ну и если ничего не помогло - тогда уже стоит задуматься о новом Quality Gate в SonarQube с меньшим процентом покрытия.
Никакой магии нет - https://t.me/javaKotlinDevOps/403.
Но числовой показатель (80% по умолчанию), задокументированные исключения и цель покрыть максимум кода, в котором возможны ошибки, быть должны.
P.S. Еще AI можно попросить тесты написать, у него это неплохо получается)
#unittests #integration_tests #java
Часто возникает вопрос - почему 80?
Краткий ответ - почему бы и нет)
А если серьезно: оценка может быть числовой (процент покрытия) или бинарной (достаточно или нет).
Бинарная плоха тем, что не документирована и зависит от мнения эксперта. Это может привести к проблемам на код-ревью.
А тут умные люди из SonarQube придумали метрику покрытия https://docs.sonarsource.com/sonarqube-server/user-guide/code-metrics/metrics-definition#coverage
и дали её рекомендуемое значение. И это не 100%, т.е. запас есть.
Считаю, что от этой рекомендации стоит отталкиваться.
К тому же JaCoCo, обычно используемый для расчета покрытия, позволяет гибко настраивать сам процесс.
Следующий вопрос, который может возникнуть: "Почему ради достижения 80% я должен писать тесты на элементарный код?" Я про getter, setter и все, все, все https://t.me/javaKotlinDevOps/34
Ответ: "Нет, не нужны эти тесты".
Лишний код можно исключить из покрытия:
1) generated код исключается по умолчанию начиная с JaCoCo 0.8.2
2) generated код Lombok - через lombok.addLombokGeneratedAnnotation = true (жаль, что только для Lombok это можно сделать, но есть еще альтернатива - см. следующий абзац.)
3) тривиальный код - явно исключая классы или пакеты по маске через настройки JaCoCo. Если какой-то код не получается исключить таким образом - это повод задуматься о рефакторинге.
Еще вопрос: "Зачем писать модульные (unit) тесты ради покрытия на интеграционный код: сервисные классы или классы контроллеров, которые представляют линейную цепочку вызовов методов?"
Ответ: "Не обязательно писать unit тесты".
Для простых микросервисов является нормальной перевернутая пирамида тестирования - когда интеграционных тестов разработки больше, чем модульных.
Простой код можно покрыть интеграционными тестами, включив их в общее покрытие. JaCoCo позволяет это настроить. Единственная проблема может быть, если тесты находятся в одном модуле, а код для покрытия - в другом, но и она решается.
И тут может возникнуть самый главный вопрос - а это не читерство? Чем это лучше отсутствия цели по покрытию?
Ответ: лучше тем, что мы четко задаем - вот это код не нужно покрывать тестами, а остальной - нужно.
И смотря на паттерны исключения - на их состав и количество - можно их быстро оценить и при необходимости скорректировать.
Ну и если ничего не помогло - тогда уже стоит задуматься о новом Quality Gate в SonarQube с меньшим процентом покрытия.
Никакой магии нет - https://t.me/javaKotlinDevOps/403.
Но числовой показатель (80% по умолчанию), задокументированные исключения и цель покрыть максимум кода, в котором возможны ошибки, быть должны.
P.S. Еще AI можно попросить тесты написать, у него это неплохо получается)
#unittests #integration_tests #java
Sonarsource
Understanding measures and metrics | SonarQube Server | Sonar Documentation
Measures and metrics used in SonarQube to evaluate your code.
Почему победил компактный стиль форматирования кода?
Я про сталь Oracle\Sun и очень похожий на него стиль Google:
vs
Базовый ответ - потому что он компактнее)
Но я бы накинул еще один аргумент. Рассуждение:
- стиль форматирования нужен человеку, и не нужен машине
- человеку важно понимать, где начало и конец логического блока кода или управляющей конструкции
- "железобетонный" способ это понять - четкие маркеры, хороший пример: begin-end в Delphi, If-End If в VB
- хороший, но не идеальный, т.к. слишком много символов - 8 вместо минимально возможных 2
- скобки на той же строке, что и управляющая конструкция, у Google\Sun - это по сути компактная эмуляция begin-end. Эмуляция потому что они не обязательны. Скобки как бы становятся частью управляющей конструкции - if, for, while, switch, try.
- а вот альтернативный вариант - это что-то странное, т.к. скобки по отступам находятся на уровне управляющей конструкции, но зачем тогда перенос на новую строку?
Тогда логичнее вот так:
Но это еще страннее смотрится.
Ну и напоследок каких целей должно достичь хорошее форматирование кода:
1) разделение логических блоков кода: пробелы, отступы, скобки
2) единообразие
3) улучшение читаемости
4) облегчение правок - возможность быстро понять, какой блок кода нужно перенести или удалить целиком
5) компактность. Причем как раз компактность с увеличением размера монитора становится менее
важна
P.S. Спонсор выпуска - Совершенный код, Стив Макконнелл)
#java #formating
Я про сталь Oracle\Sun и очень похожий на него стиль Google:
public class OrderService {
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority) {
if (order == null) {
...vs
public class OrderService
{
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority)
{
if (order == null)
{
...
Базовый ответ - потому что он компактнее)
Но я бы накинул еще один аргумент. Рассуждение:
- стиль форматирования нужен человеку, и не нужен машине
- человеку важно понимать, где начало и конец логического блока кода или управляющей конструкции
- "железобетонный" способ это понять - четкие маркеры, хороший пример: begin-end в Delphi, If-End If в VB
- хороший, но не идеальный, т.к. слишком много символов - 8 вместо минимально возможных 2
- скобки на той же строке, что и управляющая конструкция, у Google\Sun - это по сути компактная эмуляция begin-end. Эмуляция потому что они не обязательны. Скобки как бы становятся частью управляющей конструкции - if, for, while, switch, try.
- а вот альтернативный вариант - это что-то странное, т.к. скобки по отступам находятся на уровне управляющей конструкции, но зачем тогда перенос на новую строку?
Тогда логичнее вот так:
public class OrderService
{
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority)
{
if (order == null)
{
...
Но это еще страннее смотрится.
Ну и напоследок каких целей должно достичь хорошее форматирование кода:
1) разделение логических блоков кода: пробелы, отступы, скобки
2) единообразие
3) улучшение читаемости
4) облегчение правок - возможность быстро понять, какой блок кода нужно перенести или удалить целиком
5) компактность. Причем как раз компактность с увеличением размера монитора становится менее
важна
P.S. Спонсор выпуска - Совершенный код, Стив Макконнелл)
#java #formating
👍1
Что C++ унаследовал от Java?
Внимательный читатель должен сказать - стой, автор, ты ничего не перепутал? Может Java от C++?
Не перепутал)
Да, Java был создан как безопасная и легко портируемая альтернатива C++.
Но кое-что он вернул прародителю.
Как ни странно - это стандарт документирования кода. C++ изначально шел без стандарта документирования. Используйте что хотите. А JavaDoc с Java был изначально. По факту стандартной тулой для документации С++ стал Doxygen. А Doxigen взял за основу JavaDoc.
Такие дела)
#java #c++
Внимательный читатель должен сказать - стой, автор, ты ничего не перепутал? Может Java от C++?
Не перепутал)
Да, Java был создан как безопасная и легко портируемая альтернатива C++.
Но кое-что он вернул прародителю.
Такие дела)
#java #c++
Снова нападки на Scala)
Я уже немного писал про Scala когда говорил о выборе новых языков программирования https://t.me/javaKotlinDevOps/251
Но осталось чувство недосказанности. Сложный - да, о ведь функционально крутой. Может стоит набрать команду "спецназа" от разработки, пусть на Scala пишут ядро системы?
Я бы не стал. Сложность это полбеды. Сложность не там, где ей стоит быть - вот проблема.
Большиство предметных областей дают нам бизнесовую сложность. Если бы это было не так - вместо разработки стоило бы купить готовое решение. Или взять готовую библиотеку.
Сложность должна быть в бизнес-логике. А не в конструкциях языка.
Второй момент - основная задача разработчика (чего-то сложнее hello world) - борьба со сложностью. SOLID, DRY. переиспользование кода, микросервисы, уровни приложения, говорящие имена, читаемость кода, DDD, итеративная разработка... - все это помогает уменьшить сложность. А тут язык провоцирует ее увеличение.
И ещё пример. Google. Компания может позволить себе нанять наверное любого программиста. Популяризовать любой язык.
Но что она делает?
Видит проблему на backend.
C++ быстр, но не безопасен и сложен.
Java безопасная, попроще, но не идеал.
И придумывает Go: быстрый и простой. Ещё заточенный на многопоточность, но простую - goroutines.
Мобильная разработка - есть завязка на JDK. Почему так - тема отдельная. Базовый язык для JDK - Java, про Java см. выше. Тут появляется более простой Kotlin - и Google делает его стандартом Android разработки.
Итого - в обоих случаях Google сделал разработку проще. production подход. Хотя где-то у них используется Scala.
#java #kotlin #scala
Я уже немного писал про Scala когда говорил о выборе новых языков программирования https://t.me/javaKotlinDevOps/251
Но осталось чувство недосказанности. Сложный - да, о ведь функционально крутой. Может стоит набрать команду "спецназа" от разработки, пусть на Scala пишут ядро системы?
Я бы не стал. Сложность это полбеды. Сложность не там, где ей стоит быть - вот проблема.
Большиство предметных областей дают нам бизнесовую сложность. Если бы это было не так - вместо разработки стоило бы купить готовое решение. Или взять готовую библиотеку.
Сложность должна быть в бизнес-логике. А не в конструкциях языка.
Второй момент - основная задача разработчика (чего-то сложнее hello world) - борьба со сложностью. SOLID, DRY. переиспользование кода, микросервисы, уровни приложения, говорящие имена, читаемость кода, DDD, итеративная разработка... - все это помогает уменьшить сложность. А тут язык провоцирует ее увеличение.
И ещё пример. Google. Компания может позволить себе нанять наверное любого программиста. Популяризовать любой язык.
Но что она делает?
Видит проблему на backend.
C++ быстр, но не безопасен и сложен.
Java безопасная, попроще, но не идеал.
И придумывает Go: быстрый и простой. Ещё заточенный на многопоточность, но простую - goroutines.
Мобильная разработка - есть завязка на JDK. Почему так - тема отдельная. Базовый язык для JDK - Java, про Java см. выше. Тут появляется более простой Kotlin - и Google делает его стандартом Android разработки.
Итого - в обоих случаях Google сделал разработку проще. production подход. Хотя где-то у них используется Scala.
#java #kotlin #scala
Telegram
(java || kotlin) && devOps
Всем привет!
В развитие прошлого поста предлагаю поговорить про большие компании и новые языки программирования.
Вопросы, на который я постараюсь дать исчерпывающий ответ:
1) какие риски несет внедрение нового языка в enterprise?
2) нужно ли согласовывать…
В развитие прошлого поста предлагаю поговорить про большие компании и новые языки программирования.
Вопросы, на который я постараюсь дать исчерпывающий ответ:
1) какие риски несет внедрение нового языка в enterprise?
2) нужно ли согласовывать…
👍1
Почему в Python "неправильная" документация.
Если посмотреть библиотечный Python код, то там можно увидеть вот такое:
Или такое:
Что-то к так с документацией, да?)
Зачем питонисты решили сделать все наоборот - комменты после кода???
До кода же логичнее - вначале читаешь доки, потом если надо смотришь код?
Не от балды, нет.
Интерпретатор при загрузке модуля читает первое выражение в теле класса/функции/метода и, если это строковый литерал, помещает его в атрибут ___doc___ соответствующего объекта. Работает принцип convention over configuration.
Также документация выводится с помощью метода help(obj) - если надо прямо в коде. Или через рефлексию - inspect. Или с помощью CLI утилиты pydoc.
Описывается формат документации стандартом PEP 257. Т.е. все продумано.
Причём поля класса документируются точно также для единообразия. Хотя на них стройная система, описанная выше рушится.
И появляется интересный нюанс - если по привычке писать документацию к полям в JavaDoc стиле, то она сопоставится с другим полем)
Мне конечно привычнее JavaDoc стиль, но признаю красоту идеи с автоматическим обогащением метаданных сущности документацией, причём средствами языка.
P. S. Как я обратил на это внимание? Один агент написал документацию в формате JavaDoc, другой на ревью заметил, что это не по стандарту Python)
#lang #python #java #conv_over_conf
Если посмотреть библиотечный Python код, то там можно увидеть вот такое:
class IntervalArray(IntervalMixin, ExtensionArray):
"""
Pandas array for interval data that are closed on the same side.
Или такое:
@classmethod
def _validate(cls, left, right, dtype: IntervalDtype) -> None:
"""
Verify that the IntervalArray is valid.
Что-то к так с документацией, да?)
Зачем питонисты решили сделать все наоборот - комменты после кода???
До кода же логичнее - вначале читаешь доки, потом если надо смотришь код?
Не от балды, нет.
Интерпретатор при загрузке модуля читает первое выражение в теле класса/функции/метода и, если это строковый литерал, помещает его в атрибут ___doc___ соответствующего объекта. Работает принцип convention over configuration.
Также документация выводится с помощью метода help(obj) - если надо прямо в коде. Или через рефлексию - inspect. Или с помощью CLI утилиты pydoc.
Описывается формат документации стандартом PEP 257. Т.е. все продумано.
Причём поля класса документируются точно также для единообразия. Хотя на них стройная система, описанная выше рушится.
И появляется интересный нюанс - если по привычке писать документацию к полям в JavaDoc стиле, то она сопоставится с другим полем)
Мне конечно привычнее JavaDoc стиль, но признаю красоту идеи с автоматическим обогащением метаданных сущности документацией, причём средствами языка.
P. S. Как я обратил на это внимание? Один агент написал документацию в формате JavaDoc, другой на ревью заметил, что это не по стандарту Python)
#lang #python #java #conv_over_conf