Tagged: java

Как определить ставить ли новую Windows или любую другую программу

Эволюция Корзины

Среди IT-специалистов распространено мистическое убеждение:

Считается, что каждая четная версия Windows выходит у Microsoft неудачной, а каждая нечетная, наоборот, хороша. Здесь стоит вспомнить критику Windows Millenuim, Windows Vista и Windows 8, которые были четными, а также успех Windows XP и Windows 7. Microsoft пропустила цифру «девять», сделав Windows 10 нечетной в этом списке. Впрочем, некоторые специалисты «девяткой» считают Windows 8.1, что переводит «десятку» в совсем другую категорию.

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

Вспоминаем: после XP люди ждут очень перспективной ОС с ещё более красивой графикой, гиберацией, повышенной безопасностью и возможностью не перезагружать комп после установки программ или драйверов. Появилась Vista. Люди негодуют — глюки, производительность никакая и т.п.
Разработчики чешут репу, многое отключают в системе чтобы не мешало, исправляют баги, что-то добавляют и выпускают семёрку.
Пользователи смотрят — производительность лучше чем у висты, радуются и забывают, что XP работала быстрее (момент немного спорный) и требовала намного меньше ресурсов для компьютера.
microsoft начинают воевать со старушкой XP, так как она остаётся неплохим конкурентом семёрке и активно используется в Китае вместе с IE 6

Сейчас повторяется то же самое: обещают поддержку ARM процессоров и телефонов, совместимость со старыми приложениями и возможность играть в игры для Xbox, революционный интерфейс и т.п.
Когда восьмёрку выпустят внезапно поймут что погнались за двумя зайцами, есть много багов, на телефонах тормозит и т.п. и т.д.
Разработчики почитают гневные реплики пользователей и к следующей (наверно, девятой) версии всё исправят. Судя по всему, ещё лет пять-десять как минимум семёрка будет оставаться одной из используемых ОС для компьютеров.

Впрочем, неудачная (если вдруг) Windows 8 не понравится некоторым пользователям, и они перейдут на linux или продукцию компании Apple, которая в последнее время имеет свободных денег больше чем microsoft. Не будем забывать и про Google, которые, в принципе, тоже могут что-то выпустить.
(с) http://forum.boolean.name/showthread.php?t=15523

ИЧСХ и всё прямо так и случилось!

Молоток как эволюция Виндовс

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

И это касается не только Виндовс но и других крупных продуктов с длинным релизным циклом, обычно у «коробочных» типа Microsoft Office. Но есть интересный пример версии Java:
1.0 Её даже не публиковали, так что скипнем
1.1 Первая опубликованная, ажиотажа не вызвала. Помещалась на дискету. Можно считать релиз неуспешным.
1.2 Появились коллекции, JIT, Swing, Java plugin и аплеты (а тогда это был крутяяяк) — количество кода библиотек выросло в три раза и уже на дискету не влезало. Успех!
1.3 Вообще ниочём, багфикс. Неуспех.
1.4 Регекспы, уродский логинг АПИ, но зато NIO, криптография, XML парсинг. Вроде ничего такого особого, но Успех. Началось активное использование для веба, сформировались библиотеки и фреймворки, появились первые JVM языки Groovy и Scala.
1.5 Синтаксический сахар (статик импорты, аннотации, for each, enum, varargs) но главное что появился внятная Java Memory Model и Concurrency. Внезапно успех, хотя почти на всех старых джава проектах этот на этот сахар ещё не переписали. Но грамотно заложенная и чётко специфицировання JMM сыграла
1.6 Последний релиз Sun’а ничем не интересный кроме внятных процессоров аннотаций. Всё замерло на этом релизе надолго и все только и любая магия так и делалась на аннотациях пока по ночам мы плакали в подушку мечтая о лябдах. Тем не менее релиз оказался довольно стабильным и всё работало много лет, так что всё таки успех.
1.7 Первый релиз Оракла. Ничего интересного, просто промежуточный перед восьмой джавой. Неуспех.
1.8 Ляяямбдыыыыы! И наконец-то внятный Date API. Все перешли на восьмую почти мгновенно. Успех!
1.9 Уже на выходе, по сути будет только улучшена модульность что конечно тоже сверхважно для древних энтерпрайзных монолитных проектов, но хипстеры уже всё говнокодят на микросервисах где всё проще переписать и не нужно сильно запариваться архитектурой. Так что особо ажиотажа особого не будет.

Итак, тут закономерность чётности версий прослеживается ну только при очень большом старании. Но если посмотреть не каждую вторую, а каждую третью версию то можно заметить что 1.2, 1.5 и 1.8 то эти релизы были особенно успешными. Причём даже не так, они наделали шума. В основном из-за того что в них появлялись новые «Вау» фичи. И это принципиальное дело кстати.
Представьте себя менеджером продукта. У вас есть некие срочные задачи — например секьюрити уязвимости, есть задачи по долгосрочному плану улучшения архитектуры проекта, но периодически вам нужно добавлять в продукт что-то такое что снова привлечёт внимание пользователей и даже те кто пользовался древней версией и довольны захотели бы купить новую версию. Например в случае с Джавой это новые возможности языка.
Т.е. есть разные задачи с разными характеристиками по важности и срокам и при грамотном менеджменте ты их учитываешь. Если их граммотно разложить и расписать на графике то можно найти множество таких закономерностей и предсказывать свойства следующей версии.
Поэтому можно смело предсказывать что например в десятую версию Джавы будут внесены какие-то вау фичи.

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

Но не всегда четно-нечётная схема усложняется, многие как раз наоборот стараются перейти к более частым и но последовательным и плавным rolling releases и continuous delivery:

Между сериями 1.0 и 2.6.x ядро Linux использовало нечётные номера для бета-версий, и чётные — для стабильных. Например, Linux 2.3 был серией в разработке, а Linux 2.4 — серией стабильных релизов, в которую перерос Linux 2.3. В номере релиза Linux kernel сначала писался номер второстепенной версии, а затем номер релиза в возрастающем порядке. Например Linux 2.4.0 → Linux 2.4.22. После релиза 2.6 в 2004 году Linux больше не использует эту систему, теперь цикл релиза намного короче. Сейчас они просто увеличивают третье число, используя при необходимости четвёртое.

Тоже самое кстати происходит и с броузером Chrome а позже и с Firefox’ом. Какая версия Хрома уже никто не знает (у меня например уже 16.3.0.6796). Для обеспечения надёжности они просто создали отдельную «вечную бету» которую могут себе поставить и протестировать все желающие и Feature toggling.

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

Скринкаст: Пишем калькулятор на Java, JavaFX, Groovy, Spock, Kotlin

Несколько вечеров за которые я написал калькулятор на Джаве с тестами на Груви а потом переписал на Котлин. Интересно будет только для Stong Junior’ов

Это не туториал! В обычных туториалах всё хорошо и сразу получается, но как только начинающий программист сталкивается с ошибкой то не знает как дальше двигаться. Здесь все по настоящему — часть я знаю, часть изучаю сразу же. На ваших глазах появляются и фиксятся баги, гуглится и копипастится с СтекОверфлоу. Это может быть вам полезно для того чтобы ощутить эвристики которые помогают мне.
Скучно, занудно — но именно так примерно мы и программируем целыми днями. Если вы думаете связать свою жизнь с этим ремеслом, можете прочувствовать себя в моей шкуре 😉

Исходный код:
https://github.com/stokito/javafx-calculator

P.S. Да, я знаю звук отвратительный, винда неудачно обнволялась и с драйвером звука какая-то ерунда.

JAR Hell

[LinkSet] Dependency duplicates in Maven and Jar Hell with Java Classloader

Theoretical part:
Java Classloader

Maven: Introduction to the Dependency Mechanism

What is JAR hell? (Or is it classpath hell? Or dependency hell?)

Jar Hell made Easy — Demystifying the classpath with jHades
See JHades documentation, it very useful to find overlapping jars.

Another tool for dealing with Jar Hell is Weblogic Classloader Analysis Tool.

One of the most problematic dependency is Xeres Xerces Hell. It’s a good example how not to do library.

This presentation is a great resource about Jar Hell and the different type of classpath related exceptions:

But little bit boring.

Maven Dependency Wrangling

dealing with dependency chain issues in maven

Maven Enforcer plugin has extra rule
Ban Duplicate Classes
Also it should be very useful if you have legacy project that still runs under Java 6 or 7 you should avoid dependencies compiled with never Java 8.
You can use enforceBytecodeVersion

Please also make sure that you also specified requireJavaVersion (to compile), requireUpperBoundDeps, requireReleaseDeps, requirePluginVersions and other useful standard rules .

Also if you have a submodules in project it will be also useful ono-extra-enforcer-rules

So, your enforcer rules may looks like:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.4.1</version>
    <executions>
        <execution>
            <id>enforce</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedPlugins>
                        <!-- will only display a warning but does not fail the build. -->
                        <level>WARN</level>
                        <excludes>
                            <exclude>org.apache.maven.plugins:maven-verifier-plugin</exclude>
                        </excludes>
                        <message>Please consider using the maven-invoker-plugin (http://maven.apache.org/plugins/maven-invoker-plugin/)!</message>
                    </bannedPlugins>
                    <requireMavenVersion>
                        <version>3.0.5</version>
                    </requireMavenVersion>
                    <requireJavaVersion>
                        <version>1.8</version>
                    </requireJavaVersion>
                    <requireReleaseDeps>
                        <onlyWhenRelease>true</onlyWhenRelease>
                        <message>No Snapshots Allowed!</message>
                    </requireReleaseDeps>
                    <requireUpperBoundDeps>
                        <!-- 'uniqueVersions' (default:false) can be set to true if you want to compare the timestamped SNAPSHOTs  -->
                        <!-- <uniqueVersions>true</uniqueVersions> -->
                    </requireUpperBoundDeps>
                    <reactorModuleConvergence>
                        <message>The reactor is not valid</message>
                        <ignoreModuleDependencies>true</ignoreModuleDependencies>
                    </reactorModuleConvergence>
                    <requirePluginVersions>
                        <message>Best Practice is to always define plugin versions!</message>
                        <banLatest>true</banLatest>
                        <banRelease>true</banRelease>
                        <banSnapshots>true</banSnapshots>
                        <phases>clean,deploy,site</phases>
                        <additionalPlugins>
                            <additionalPlugin>org.apache.maven.plugins:maven-eclipse-plugin</additionalPlugin>
                            <additionalPlugin>org.apache.maven.plugins:maven-reactor-plugin</additionalPlugin>
                        </additionalPlugins>
                        <unCheckedPluginList>org.apache.maven.plugins:maven-enforcer-plugin,org.apache.maven.plugins:maven-idea-plugin</unCheckedPluginList>
                    </requirePluginVersions>
                    <enforceBytecodeVersion>
                        <maxJdkVersion>1.6</maxJdkVersion>
                        <excludes>
                            <exclude>org.mindrot:jbcrypt</exclude>
                        </excludes>
                    </enforceBytecodeVersion>
                    <banDuplicateClasses>
                        <ignoreClasses>
                            <!-- example of ignoring one specific class -->
                            <ignoreClass>com.xyz.i18n.Messages</ignoreClass>

                            <!-- example of ignoring with wildcards -->
                            <ignoreClass>org.apache.commons.logging.*</ignoreClass>
                        </ignoreClasses>
                        <findAllDuplicates>true</findAllDuplicates>
                    </banDuplicateClasses>
                    <banCircularDependencies/>
                    <ForbidOverridingManagedDependenciesRule>
                        <excludes>
                            <!-- guava in parent is too old, so allow to override it -->
                            <exclude>com.google.guava:guava</exclude>
                        </excludes>
                    </ForbidOverridingManagedDependenciesRule>
                    <ForbidOverridingManagedPluginsRule/>
                    <ForbidDependencyManagementInSubModulesRule/>
                    <ManageAllModulesRule/>
                </rules>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>extra-enforcer-rules</artifactId>
            <version>1.0-beta-3</version>
        </dependency>
        <dependency>
            <groupId>net.oneandone.maven</groupId>
            <artifactId>ono-extra-enforcer-rules</artifactId>
            <version>0.1.1</version>
        </dependency>
    </dependencies>
</plugin>

Two attempts to find duplicated classes with Maven
Remove duplicate classes the agile way: Maven Duplicate Finder Plugin

Finding Duplicate Class Definitions Using Maven

Both of this plugins are discussed here:
Figuring out duplicate class definitions using the Analyze goal

Also maven-shade-plugin does check for overlapping classes during packaging of uber-jar.

Resolving conflicts using the dependency:tree -Dverbose
It shows which dependencies are duplicated (omitted for duplicate), with are evicted with newer version (version managed from 1.6) but it doesn’t show which dependencies was excluded.

Another one good thing that worst to do is enable Failing the build on dependency analysis warnings. Note: it binded to verify phase that runed after package.

JDEPS Java Dependency Analysis Tool from JDK 8

Also some related articles

Versions compitable

For example changelog of Joda-Time v2.9

Compatibility with 2.8

Build system — Yes
Binary compatible — Yes
Source compatible — Yes
Serialization compatible — Yes
Data compatible — Yes
— DateTimeZone data updated to version 2015g
Semantic compatible — Yes

See another [Linkset] Compatibility

Jigsaw

It is possible a situation when some two libraries wanting to use the same dependency but of different versions. Unfortunately, in this cases we can’t manage this and should use -nodep versions.
Finally this problem will be resolved in JDK 9 Jigsaw: a jar can be declared as a module and it will run in it’s own isolated class loader, that reads class files from other similar module class loaders in an OSGI sort of way.
This will allow multiple versions of the same Jar to coexist in the same application if needed.

Working with deprecation

Upgrading of dependncies may require to remove some old codebase that depends on them.
This is also should be done in right way, so here some links that may helps:
* JEP 277
* Dr. Deprecator Prescriptions: important things that you should know about obsolete Java API

Speed up maven build

It’s also related topic. The main reason why I decided to add it here is because usually during speeding up build you will find a lot of problems with dependency graph.
It will helps you to make yoir project more modulized. Also for example paralell build may fails if your tests are in conflict (shares same resources, for example integration tests may use the same port).

Dependency analyzers

Also useful

* jApiCmp japicmp is a tool to compare two versions of a jar archive
* Java API Compliance Checker: A Perl script that uses javap to compare two jar archives. This approach cannot compare annotations and you need to have Perl installed.
* Clirr: A tool written in Java that compares two libraries for binary compatibility. Tracking of API changes is implemented only partially, tracking of annotations is not supported. Development has stopped around 2005.
* JDiff: A Javadoc doclet that generates an HTML report of all API changes. The source code for both versions has to be available, the differences are not distinguished between binary incompatible or not. Comparison of annotations is not supported.
* revapi: An API analysis and change tracking tool that was started about the same time as japicmp. It ships with a maven plugin and an Ant task, but the maven plugin currently (version 0.4.1) only reports changes on the command line.

[LinkSet] Avoiding NullPointerException in Java

Dr. Deprecator Prescriptions: important things that you should know about obsolete Java API (JEP 277)

Did you ever asked yourself why Cloneable or, for example, Serializable interfaces are not deprecated?
OpenJDK team has a special man Stuart Marks who call himself as Dr. Deprecator. He is «Software Deconstructionist» and few days ago he made a great talk about API evolution and upcoming removing of some obsolete code in Java 9.
Doctor Deprecator
Thanks to Yoshio Terada for a photo.

The most important idea from presentation is that «Deprecated» code may be separated into four categories:
“Condemned” – will be removed or disabled in a future release (no moral connota, on). For example, from Java 9 already removed java.util.logging.LogManager.addPropertyChangeListener()
“Dangerous” – using this may introduce bugs or data loss. For example, String.getBytes() may loss for anything other than ASCII
“Superseded” – not dangerous, not going away, but new code should use something different. For example Vector, Date classes.
“Unimplemented” – some things unconditionally throw an exception at runtime (e.g. UnsupportedOperatioonException). This enables warnings at compile time. For example: class ImmutableList implements List, so should implement mutator methods add() and remove()

See this presentation

UPD
Yesterday was created JEP 277: Enhanced Deprecation

Discussion on Redit

What Might a New @Deprecated Look Like?

Annotation Library

RFC: #[deprecated] for Rust that was inspired by this JEP

JEP 277 “Enhanced Deprecation” is Nice. But Here’s a Much Better Alternative

Deprecation service in code

For example, Tapestry uses a special DeprecationWarning service which tracking usage of deprecated API. See usage example.
You may create something similar yourself.

In Python

https://wiki.python.org/moin/PythonDecoratorLibrary#Generating_Deprecation_Warnings
https://wiki.python.org/moin/PythonDecoratorLibrary#Smart_deprecation_warnings_.28with_valid_filenames.2C_line_numbers.2C_etc..29
Example
https://bitbucket.org/ecollins/passlib/src/070364a99ca7d4a0588a40485957d9a579a2d191/passlib/utils/init.py?at=default&fileviewer=file-view-default

Example of usage
https://bitbucket.org/ecollins/passlib/src/070364a99ca7d4a0588a40485957d9a579a2d191/passlib/apache.py?at=default&fileviewer=file-view-default

    @deprecated_method(deprecated="1.6", removed="1.8",
                       replacement="check_password")
    def verify(self, user, realm, password):
        """verify password for user"""
        return self.check_password(user, realm, password)

Python или Java? Хм… а может Groovy?

На DOU новый холивар Что выбрать бывшему учёному — Python или Java?

Хочу оставить позицию младшего научного сотрудника и переквалифицироваться в разработчика. Всё высшее образование было профильным — информатика. Коммерческого опыта в программировании нет, только эксперименты и учебные проекты. В последнее время предпочитаю писать их на Python, для него есть хорошие научные библиотеки.
Цель — найти позицию разработчика, которая могла бы мне дать начальный опыт. В перспективе — вывести на более наукоёмкие позиции (анализ данных, машинное обучение, обработка естественных языков).
Город большого значения не имеет, особых требований по начальной зарплате нет — лишь бы хватало на съёмную квартиру и проживание.
Работу начну искать где-то с весны, поэтому остаётся время на подготовку. Осталось решить, в каком направлении мне развиваться.
Некоторые соображения (рынок я знаю плохо, поэтому можете смело поправлять):
1) По Java вакансий намного больше, чем по Python. Кроме того, можно официально подтвердить знания Java, сдав какой-нибудь начальный экзамен Oracle — это может привлечь внимание HR.
2) С другой стороны, в Java есть множество неизвестных мне корпоративных технологий и фреймворков, в которых можно надолго утонуть. В Python с этим проще — если я освою базовый Django (может, Flask, Bottle) и сделаю на них несколько личных проектов, то это должно покрыть начальные требования.
3) Java — это в основном аутсорс, Python — это в основном продуктовые компании (или у меня сложилось такое впечатление).
Что будет лучшим стартом, если мне хочется дорасти до профессиональной работы с анализом данных, прогнозированием, построением рекомендательных систем и т.п.?

Как и следовало ожидать разгорелся сильный холивар, но почему-то не упомянули Groovy — язык который как раз ииногда и называют помесью Питона и Джавы.
Я решил ответить:

Пока единственный известный мне настоящий специалист по Data Science поработавший в Германии на суперкомпьютере, работал таки на Java, и я вообще сомневаюсь как что-то действительно большее Hello world можно написать на Python.
Хотя, конечно, хорошие программисты могут писать на чём угодно.

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

И всё таки лучше не забывать что Питон обманчиво кажется простым: он довольно своебразен и уводит в свою вселеную.

Мне кажется, что пока лучше выбирать JVM, как платформу. Если не будет хватать возможностей Java то можно попробовать другие JVM языки: тот же JPython, Scala или Groovy.

Scala это отличный язык который довольно гармонично совместил в себе главные достижения других языков программирования. Но Scala статически компилируемый язык и это затрудняет использовании магии.

В случае, если захочется большей выразительности, DSL или динамики то есть Groovy — великолепный язык программирования, обратно совместимый с Java и обладающий наверное всеми теми качествами за которые тут так сильно хвалят Питон.

На Groovy кстати есть даже всякий научный софт, например GroovyLab:

GroovyLab is a MATLAB-like scientific programming environment based on Groovy with extensive plotting support, default access to the best Java scientific libraries, user-friendly interface, easy installation of toolboxes, Computer Algebra support and many other features.

Вообщем, могу сказать точно что выбрав джаву не прогадаешь
joseph-ducreux-meme-disregard-python-acquire-java-080b2b


Не поленитесь, и почитайте ещё несколько очень важных моих статей для начинающих программистов, студентов и джуниоров.
Также не забудьте вступить в группу IT Juniors куда я пытаюсь собирать ссылки на другие полезные статьи для вас и анонсы курсов и интернатуры в компаниях.

toString() contract

Today I read great article of Fabian Kessler Java toString(): the Program Logic vs. Debug Dilemma.

In short, it is not obvious how to override method and what exactly means «string representation of object»:

Hrm. So there are mainly 2 uses:
String representation: toString() returns the object’s value «as string» as close as possible.
It is absolutely required to override toString(), and to do it in this way.

Debug information: the object’s values for the human.
For example IntelliJ IDEA’s default toString() template generates this kind.
It’s just nice to have.

JavaDoc says:

Returns a string representation of the object. In general, the
toString method returns a string that
«textually represents» this object. The result should
be a concise but informative representation that is easy for a
person to read.
It is recommended that all subclasses override this method.

Quotation from the «Effective Java» book:

One important decision you’ll have to make when implementing a toString
method is whether to specify the format of the return value in the documentation.
It is recommended that you do this for value classes, such as phone numbers or
matrices. The advantage of specifying the format is that it serves as a standard,
unambiguous, human-readable representation of the object. This representation
can be used for input and output and in persistent human-readable data objects,
such as XML documents. If you specify the format, it’s usually a good idea to pro-
vide a matching static factory or constructor so programmers can easily translate
back and forth between the object and its string representation. This approach is
taken by many value classes in the Java platform libraries, including BigInteger ,
BigDecimal , and most of the boxed primitive classes.

I found that most of code that I saw uses some unwritten «toString() contact». The contract mostly based on difference between Entity and Value objects.

1. «String typization» mechanism

The Delphi programming language has a great conception of Variant type. It is difficult to me to explain this in few words. It is like an universal container for the primitive types.

This is like a def keyword in Groovy: it mean any type. But any primitive type, not an basic Object.
And there is convention like a «Groovy Truth» how one primitive type should be converted to another.

Unfortunately Java hasn’t Variant type, so it uses String as it replacement. Hence, any primitive type you can convert to sting presentation: numbers, dates and boolean.
This is called StringlyTyped pattern and actually it makes code understanding painfully.

String typization

That’s why we should look on toString() as on data converter «as string».
And it should work only with Value classes and primitive datatypes wrappers, i.e. Integer, Boolean, Double, Date, Phone Numbers etc.

Important thing here is that this resulting string representation of value can be parsed verse to get an original value.

2. Serialization

In more common sense toString() it is a kind of serialization.
Even more, toString() can return JSON on CSV value.
But you should remember that deserialization is not granted by method contract.
That’s why you should use standard approach and implement Serializable interface.

But you still can use toString() as serialization for basic types that already contains written toString(), parse() and valueOf() methods.

3. Human readable representation of object

Another thing is when we need to show the object to a user. In this case it may be better to create another method called like a getDisplayName(), getTitle() or getCaption().

For example User class can contain getFullName() that return First Name and Second Name with space between them.

public class User {
   String firstName;
   String lastName;
   
   String getFullName() {
       return firstName + " " + lastName;
   }
}

Why it is better? First of all human readable names can be different and one string representation method may be not enough.

For example lets take a look on Facebook. In the private mail conversation between two users we can just write first name. At the public profile page we can display «First name + (nickname) Second name».

Also, usually this kind of display names can be localized. For example name of month or book title.

4. Log/Debug representation

In all other cases toString() used for logging or debug output. Just to make developer life easier.

The Groovy has a helpful @ToString annotation that generates this method in runtime.
For example class User can contain toString() method that return user login or email:

@ToString(includeNames = true, includes = 'email,firstName')
class User {
   String email
   String firstName
}

...

def user = new User(email: "admin@example.com", firstName: "Administrator")
assert user.toString() == "User(email:admin@example.com, firstName:Administrator)"

...
log.info("User ${user} logged in")

Here log.info() will call toString() method that is not good. I’m totally agree with Fabian and such method should be named toDebug() or dump(), but not toString().

But you should always remember that logging can cause problems for security and performance.
Not always you need to write to log everything that object contains.
For example if a hacker got an access to logs he can see a lot of stuff like user password and other credentials or even credit card number.
So you should take care to exclude from logs sensitive information.
Always mask credit card numbers and users personal info.

Another big problem is log injection vulnerability when some XSS scripts from logs can be executed in dashboard. Please read carefully OWASP Logging Cheat Sheet

Conclusion

Using this conventions may make your code better and safer.
I would be very thankful if you share conventions from your experience 🙂

Проблемы OpenJDK или в очередной раз про идиотизм Orcale

Ну для начала лекция для тех кому интересно въехать в курс дела:

У меня к OpenJDK есть такие претензии:
1. Название, я поначалу подумал «ну вот ето JDK а мне на сервер достаточно только JRE» и искал OpenJRE 🙂
2. Сайт: посмотрите на сайт Mono http://www.mono-project.com/ — красивый, всё ясно куда нажимать. А теперь посмотрите на это уродство http://openjdk.java.net/ . Я не дизайнер, и неприхотливый но даже меня тошнит. А ведь это же маркетинг!
4. Почему IDEA упорно не дружит с ним? Это меня настораживает — вы говорите что OpenJDK на 99% соответсвует обычной OracleJDK, но идея пишет что будут проблемы с графикой. Это правда? В чём причина? Напишите JetBrains чтобы они убрали это сообщение.
5. Где версия под Windows?
6. Отправлять патчик по мылу это прошлый век — перенесите проект на GitHub!

До сих пор у всех осталось отношение к OpenJDK как к кастрированому форку православной сановской Явы.
Боюсь чтоы избавится от этого его прийдётся переименовать и впихнуть в него что-то модное чтобы пресса рассказала о нём как о прорыве.

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

Ruby, Ruby, Ruby, Ruby! And do ya, do ya, do ya, do ya!

Просто несколько вещей которые бесят постоянно. Можно расписывать их много, но тут я акцентирую внимание на том что уровень вхождения в Яву выходит большим из-за банального разгильдяйства Oracle. Неожиданно, но они совсем не учитывают что платформу нужно ПРОДАВАТЬ, и очень важен маркетинг. А ведь ещё «корпорацией бабла» называются 🙂

JDK, JRE — WTF?

JDK содержит в себе полную JRE + SDK (компилятор, декомпилятор, дебагер и.т.д). Тем не менее, вместо того чтобы ставить отдельно SDK, всегда приходится полностью выкачивать JDK содержащий JRE.
Самое интересное, что теперь у нас есть OpenJDK, и несмотря на JDK в названии он же и JRE. Я окончательно запутался.

Is Java open soure?

Принято считать, что Java открытая платформа. Что можно считать открытой платформой? Сам язык Java, насколько я в курсе это вполне проприетарная технология. Открытые исходные коды — это ещё не значит что это открытая платформа. Например разработка Android ведётся в строжайшем секрете и ты не знаешь чем тебя удивит Google в следующей версии. Но так-то исходники открывают, да.
Изначально SUN не хотела выкладывать исходники Java из-за того что те содержали какой-то патентированый код. Я не очень понимаю почему это было большой проблемой. Можно было выложить то, что можно, а запатентированный код либо переписать, либо выделить в отдельный модуль. В принципе так вроде и сделали в результате чего получилась OpenJDK. Но тут есть ключевой момент: OpenJDK — это отдельный проект. Его нужно отдельно расскручивать, у него отдельный сайт, своё сообщество и, что потенциально опасно, свой код который может начать отличатся от того что внутри оракловой JDK. И тут сразу возникает следующий вопрос…

OpenJDK == Oracle?

На конференциях парни из Oracle утверждают что OpenJDK это на 99.9% тоже что и Oracle JRE, и что они вообще билдятся из одних исходников. Тем не менее, IntelliJ упорно отказывается работать с OpenJDK и запугивают проблемами с производительностью. Наверное тут дело в криворукости JetBrains, но всё равно настораживает.
Тем не менее, все продолжают использовать именно OracleJDK

Oracle принципиально не делает дистрибутива для Debian, а только для своей Solaris.
А в Ubuntu выпилили этот пакет, в результате каждый раз установка джавы превращаются в пляску с бубном: нужно прописать сторонний PPA, в котором инсталятор Java, который за тебя выкачивает её из сайта Oracle и устанавливает. Естественно такой пакет из стороннего PPA нельзя использовать как зависимость в своём пакете.

  1. На сайте Оракла чёрт ногу сломит, всё страшное и некрасивое. Ещё и вымагают регистрацию. Никакой заботы о пользователях, никакого маркетинга.
  2. Почему-то инсталятор сам не прописывает переменную JAVA_HOME и JDK_HOME. Что ему, жалко что-ли? Вообще переменные окружения это большое зло, может уже пора искоренить их вовсе?
  3. Успех платформы во многом зависит от наличия пакетного менеджера в поставке с ней. В Ruby есть gem, в NodeJS — npm. В яве ничего.
  4. Туториалы на оф. сайте стары как мир, без подсветки синтаксиса и никакого интерактива.

Как так получилось что откровенно поганая платформа Ruby стала такой модной и популярной? Умелый маркетинг.
Посмотрите на сайт например Mono, он выглядит приятней и опрятней, пускай это аутсайдерский проект, но даже там пытаются хоть ка кто для людей сделать.
Я уже молчу про прямого конкурента Java — платформу .NET.
На сайте много всячины и сразу же баннер на Visual Studio.
А теперь гляньте на Web 1.0 сайт явы. Фу!
Кстати, тоже самое касается самого языка программирования.
Если MS в целях маркетинга впихнул всё нужное и ненужное в C#, то в Яве даже самые нужные фичи добавляют с огромным скрипом. Вот например, лямбд все ждут уже десятилетие, и вот уже наконец в восьмой Яве будут.
Конечно, Ява по философии консервативна и стремится быть минималистичной, но не до такой же степени чтобы ждать пятой версии для for each циклов.

Когда то ява была прорывом, и очень потенциальной технологией.
Но тянули до последнего с открытием исходников, забили на дистрибьюцию, забили на десктопы, оконные программы смотрятся ужасно, просрали рынок аплетов который теперь заполонил поганый Flash, поругались с MS, а теперь ещё и с Google.

Маркетинг господа. Если вы ещё не поняли, то в постиндустриальной эпохе это самое главное.

Software Environments

Программа может работать в разных условиях (environments), например у программиста на компьютере, где Windows и пару гибибайт оперативки, или на реальном «производственном» (production) сервере, с настоящей БД, с миллионом пользователей, мощным железом и под каким нибудь FreeBSD.
Соответсвенно на уровне конфигурации и кода нужно учитывать такие разные Environments.
Например если произошла ошибка то на компьютере программиста (development environment) мы вываливаем ему весь stacktrace, а вот на работающем сайте (production) мы пишем все ошибки только в логи, а перед пользователями извеняемся.

Так вот, какие чаще всего нужны Environments?
К сожалению я нигде в интернете не нашёл хорошего объяснения какие environments нужны и как их конфигурировать. Очень много и хорошо описано в документации к Grails но там описанные только самые базовые случаи.
Ещё немного описано в Википедии.
Поэтому постараюсь описать их все исходя из моего опыта.

Development, dev

Компьютер программиста
БД создаётся in-memory и каждый раз удаляется при выключении программы.
Пример конфигурации:

development {
    dataSource {
        url = 'jdbc:h2:mem:devDb' // Драйвер БД: H2, база в памяти, называние БД devDb
        dbCreate = 'create'       // Создать схему БД автоматически
        loggingSql = true         // Логировать SQL запросы
    }
    log4j = {
        all 'grails.app'  // Логируем всё из пакетов нашего приложения           
        root {
            all 'stdout'  // Выводим только в консоль
        }
    }
}

Здесь опция dbCreate = ‘create’ указывает что БД будет каждый раз снова создаваться снова.
прямо в оперативной памяти. При выходе из программы она будет уничтожатся.

More on dbCreate
Hibernate can automatically create the database tables required for your domain model. You have some control over when and how it does this through the dbCreate property, which can take these values:
create — Drops the existing schemaCreates the schema on startup, dropping existing tables, indexes, etc. first.
create-drop — Same as create, but also drops the tables when the application shuts down cleanly.
update — Creates missing tables and indexes, and updates the current schema without dropping any tables or data. Note that this can’t properly handle many schema changes like column renames (you’re left with the old column containing the existing data).
validate — Makes no changes to your database. Compares the configuration with the existing database schema and reports warnings.
Можно играться этими опциями.
Например если вы не хотите чтобы данные очищались, а просто обновилась схема то ставьте update и сохраняйте БД в файле.
Если у вас уже production БД то ставьте только validate а саму миграцию БД делайте с помощью SQL скриптов через инструменты DBMaintain или LiquidBase.

Test

Для прогона автоматических тестов.
Тут стоит отметить что тесты бывают:

  • модульные (unit) — им не нужно никаких конфигураций Environments по определению
  • интеграционные (integration, i11n) — вот для них обычно уже нужна БД а то и полностью стартовать сервер.
  • функциональные (functional) — это когда имитируются действия пользователя, и проверяется что все кнопочки работают как должны.

Т.е. environment нужен для integration и functional и в идеале разный.

Production, prod

Настоящий сайт.
Тут стоит отметить что здесь нельзя хранить настоящие пароли от БД. Я бы рекомендовал просто указать имя DSN, например для JNDI или ODBC.
Логирование нужно настроить в файл и на email. А вот в консоль логировать бессмысленно.

production {
    grails.serverURL = 'http://greenpay.com/'
    portMapper.httpPort = 80
    portMapper.httpsPort = 443
    dataSource {
        jndiName = "java:comp/env/myDataSource"
    }
    log4j = {
        warn 'grails.app'
        root {
            warn 'main', 'smtp'
            additivity = true
        }
    }
}

Staging, stg

Это тестовый сервер с железом, конфигурацией и данными максимально приближёнными к production.
Обычно данные берутся скриптом с реального сервера, и только персональная информация (пароли, email) перетираются тестовыми в целях безопасности.
На staging проводят нагрузочное тестирование и проверяются что реальные данные не поломают приложение. Например может оказатся что у вас в реальной БД есть пользователь с именем длинней чем размер поля в новой версии БД.

QA

Сборка программы для QA инженеров (тестировщиков).
Не путать с test environment — то для автоматических тестов. Автотесты не могут поймать все дефекты, особенно связанные с внешним видом.
Тут можно выделить два случая QA…

QA dev

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

QA release

За пару недель перед релизом новая разработка замораживается (code freeze) или уже ведётся в других ветках кода для следующего релиза.
За это время тестировщики делают регрессионное тестирование где проверяют что старый функционал работает как и прежде и ничего не поломалось.

HEAD

Continuous Integration, CI — это сервер который автоматически собирает ваш проект после каждого изменения кода (pull). HEAD — это последняя версия кода, т.е.
head environment это версия приложения максимально соответствующая последнему состоянию кода.
Зачем это нужно? Ну если у вас в команде несколько человек то бывает удобно когда есть общий доступный сервер на котором быстренько можно что-то глянуть.
Т.е. похоже на QA но обновляется чаще и имеет право содержать ошибки.

Demo, Acceptance

Демо версия для сдачи итерации заказчику. Этот сервер должен быть доступен заказчику из интернета.
Всё должно быть сделано так чтобы не произошло «демо эффекта» когда ты показываешь заказчику новый функционал и вдруг он выдаёт ошибку.
Поэтому БД всегда создаётся новая. Презентационные данные должны быть красивыми и заранее оттестированными и отрепетированными.
Известные баги нужно обходить стороной. Заказчику главное увидеть как оно работает, а то что там ещё есть баги это не так важно. Важными они станут только в ветке QA release.

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

Буду рад услышать если вы можете дополнить эту информацию или подскажете где можно почитать.
Расскажите как у вас настроено на проекте 🙂 Спасибо.

UPD Также почитайте мой совет Избегайте использования Environment вне файлов конфигураций