Автор: vit

  • Про архитектуру

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

    Есть такая книга “Thinking, Fast and Slow”. На русский язык название почему-то перевели как “Думай медленно… решай быстро“, хотя буквальный перевод означает “Быстрое и медленное мышление”.

    Написана она Даниэлем Канеманом – нобелевским лауреатом по экономики, тем не менее книга написана скорее в стиле занимательной психологии. Читал давно, но после прочтения, хорошо запомнилось несколько интересных идей. Самое интересное в ней про две системы мышления – быстрая и медленная.

    Быстрое мышление хорошо развивается тогда, когда есть быстрый ответ на действие (назову его знакомым для тех специалистов термином – “фидбек”). Например если взять профессию пожарного, то он “чует” опасность, его интуиции можно доверять. Если кричит бежим – надо бежать, кричит лежать – надо падать и лежать. Иначе в этой профессии не выжить, поскольку “фидбек” на действие (или бездействие) срабатывает мгновенно. Причем с возрастом интуиция у них прокачивается всё больше и больше. Это и есть быстрое мышление. Оно не плохое и не хорошее, оно нужно для того, чтобы экономить кучу времени, сил, а также порой спасает жизнь.

    С другой стороны, если взять профессию терапевта, там “фидбек” медленный. Пациент может выздороветь из-за правильного лечения, а может сам по себе, за счет крепкого иммунитета. Терапевт может никогда не узнать, сработало его назначения или нет, поскольку пациент может не прийти на повторный прием по нескольким причинам. Например может перестать обращаться к этому врачу если стало лучше (нет смысла дальше тратить время и деньги) или если стало хуже (опять нет смысла, надо менять клинику/врача). Получается в таких профессиях сложнее развивать интуицию, т.к. обратная связь может быть очень долгой или вообще отсутствовать. В итоге доверять можно только такому врачу, который смог “прорваться” за годы работы, через огромный массив “зашумленных” данных и развить у себя экспертизу в своей профессиональной деятельности.

    К чему я веду.

    Возьмем сотрудника тех поддержки, например системного администратора, который только начинает свой профессиональный путь. Если он делает свою работу небрежно, то фидбек он получает очень быстро. Если он что-то не туда воткнул, ввел неправильный пароль, указал неправильный ip адрес, то получает моментальную ответную реакцию. Поэтому в этой профессии люди очень быстро учатся. У них бывает замечательная интуиция и они могут раньше других почувствовать, когда что-то пошло не так… Правда не всегда понимают, как все работает на самом деле.

    Перейдем теперь к программистам. Они могут писать грязный код, с большим количество “копипасты”, сложно поддерживаемый, плохо тестируемый. Тем не менее если программа работает и как-то решает проблемы бизнеса, то о плохом качестве кода могут не знать несколько недель или даже месяцев.

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

    Получается, что если “слабого” программиста команда (или менеджмент) может разоблачить только через несколько недель или месяцев, то ошибки архитектора могут проявить себя еще позже, через год или два.

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

    Бывает другая ситуация, когда у программиста срабатывает своеобразный “импринтинг” и он начинает применять везде одно и тоже архитектурное решение, которому он научился в начале карьеры и полюбил. Например, я часто видел и слышал категоричные утверждения:

    • Все успешные компании используют Spring и Hibernate!
    • В проде – только Oracle (хотя сейчас чаще слышу – только PostgreSQL)!
    • Нам нужна Кафка!
    • Все используют микросервисы!
    • Только Java, т.к. C# скоро умрет (здесь вместо Java и С# – можно подставить любые другие языки программирования)!

    Это конечно звучит мощно и просто, но.. нет, не надо торопиться. Здесь как раз и надо включать, то самое “медленное мышление” про которое пишет Канеман, так называемая “Вторая система”:

    • Система 1: срабатывает автоматически и очень быстро, почти не требуя усилий и не давая ощущения намеренного контроля
    • Система 2: выделяет внимание, необходимое для сознательных умственных усилий, в том числе для сложных вычислений

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

    Вот несколько рекомендаций с моей стороны.

    • Конечно замечательно, когда можно довериться интуиции. Только интуицию нужно сформировать, а для этого нужен опыт. Причем опыт не программирования, а именно проектирования архитектуры. Проверить программный код можно относительно быстро, проверить архитектуру – нет.
      Ищите человека с опытом.
    • Если опытного архитектора нет, а есть простой программист, который делает всё, то возможно его “чуйка” еще не прокачена. Тогда ему надо стараться думать, анализировать, искать недостающую информацию, а не действовать интуитивно. Не использовать первую систему, методика “попробуйте выключить и включить” не сработает.
    • На проекте должен быть только один архитектор, но об этом как-нибудь в другой раз…
  • Запечатывание в Java.

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

    Запечатанные классы определяются с помощью ключевого слова sealed. Это нужно, чтобы ограничить в наследовании. Потенциальных наследников в таком случае нужно указать явно, через запятую после permits.

    Например так:

    public abstract sealed class Shape
        permits Circle, Rectangle, Square { ... }

    На самом деле, основной вопрос который мне задают, не как ограничить наследование, а зачем вообще запрещать или ограничивать наследование? Ведь наследование – один из столпов ООП, такое же как и инкапсуляция и полиморфизм…

    Если посмотреть официальные цели в JEP, то в них написано:

    1. Allow the author of a class or interface to control which code is responsible for implementing it.

    2. Provide a more declarative way than access modifiers to restrict the use of a superclass.

    3. Support future directions in pattern matching by providing a foundation for the exhaustive analysis of patterns.

    JEP 409: Sealed Classes

    Цели №1 и №2 под “контролировать” и “… более декларативный способ для ограничения … ” означает “мы даем вам возможность запрещать”, не раскрывая зачем это нужно. Цель №3 интереснее, в ней виден прикладной аспект, но о нем позднее.

    Начнем с того, что прикладному программисту, который пользуется готовыми библиотеками, особой пользы в sealed нет или эта польза не особо видна. Этот “инструмент для запечатывания” нужен архитектору или ведущему программисту, который пытается построить дизайн/архитектуру проекта.

    Например, если совсем никак не ограничивать наследование, то иерархия классов начинает сильно разрастаться и в ней становиться тяжело ориентироваться. Возьмем популярный фреймворк Spring. В нем наследование AnnotationConfigWebApplicationContext выглядит так:

    java.lang.Object
      ↑ org.springframework.core.io.DefaultResourceLoader
        ↑ ...context.support.AbstractApplicationContext
          ↑ ...support.AbstractRefreshableApplicationContext
            ↑ ...AbstractRefreshableConfigApplicationContext
              ↑ ...AbstractRefreshableWebApplicationContext
                 ↑ AnnotationConfigWebApplicationContext

    В случае Spring-а это сделано умышлено, это всё росло годами и хорошо показывает всю гибкость этого огромного фреймворка.

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

    Теперь возможно.

    Если смотреть на вопрос глобально, то ограничения в программирование, это очень полезная вещь. Например некоторые радикально настроенные программисты вообще считают, что ограничение – двигатель прогресса.

    Очень ёмко эту идею изложил Роберт Мартин (также всем известный как дядюшка Боб или “Uncle Bob”) в книге Идеальная архитектура.

    Парадигмы говорят нам не столько что делать, сколько чего делать нельзя.

    Роберт Мартин.

    Здесь речь идет, не об sealed классов, а в целом о роли различных запретов и ограничениях в программировании.

    Например структурное программирование – борется с таким злом как оператор “goto”. ООП вводит ограничение на косвенную передачу управления. Функциональное программирование накладывает ограничение на присваивание.

    Конечно это слишком смелая идея, полностью принять и согласиться с ней я не могу. Например, мне кажется, что крутость ООП не только в том, что борется с передачей управлением, а ещё в том, что борется засильем глобальных переменных, а также дает возможность программистам выразить в коде “вот эти методы и поля не смей трогать!”.

    С другой стороны, в целом идея верная. Например если взять такой живой пример, как очень популярный сейчас язык программирования Python. В нем наложили запрет на плохо отформатированный код. Казалось бы люди должны страдать от того, что не могут ставить пробелы и/или таб так, как они хотят и где хотят. Тем не менее, за счет этого ограничения, Python стало особо привлекателен и выразителен.

    Вернемся к sealed классам.

    Использование запечатанных классов довольно простое.
    Перед классом или интерфейсом указываем sealed, потом указываем после permits список классов-наследников. Классы должны быть final.

    Например:

    sealed class S permits A,B,C { }

    Означает, что объект класса S может быть объектом класса A, B или C.

    S abc = new A(); // Объект abc может быть только A, B или C
    abc = new B();
    abc = new C();

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

    В качестве грубой аналогии, это можно представить как сумму множеств:

    S = тип A + тип B + тип C 
      или можно написать так:
    S = A U B U C 

    Осторожно! Это всего лишь грубая аналогия. Мои выкладки здесь никак не связанны с теорией множеств и настоящей математикой. Кто учил матан и дискретку должны это понимать.

    Теперь двигаемся дальше в сторону алгебраических типов данных. Берем произведение типов. Мы можем их сделать с помощью record.

    Например:

    record R(A a, B b) { }

    Аналогия прямого произведения множества R = A x B, которое может содержать различные комбинации объектов из A и B.
    Естественно объекты класса R также могут быть частью S.

    sealed interface S permits A,B,C,R {}
    
    record R(A a, B b) implements S {}

    Что-то вроде S = A U B U C U R , где R = A x B

    Также в permits можно использовать enum.

    sealed interface S permits A,B,C,R,E {}
    record R(A a, B b) implements S {}
    // Делаем enum для запечатанного S
    enum E implements S { AZ, BUKI, VEDI, GLAGOL, DOBRO }

    Важно понимать, что sealed это про объединение “типов”, а enum – объединение объектов одного типа. Разница как между множеством и элементами множества.

    Архитекторы языка Java нам оставили специальное ключевое слово non-sealed. Это такой аварийный люк, который можно использовать, чтобы “распечатать” запечатанный класс.

    sealed interface S permits A,B,C,R,E, Gin { }
    record R(A a, B b) implements S { }
    enum E implements S { AZ, BUKI, VEDI, GLAGOL, DOBRO; }
    // От этого класса можно наследоваться, он не final
    non-sealed class Gin { }

    Ключевое слово non-sealed очень необычное. Это первый hyphenated keyword. Другими словами написанный через дефис, т.е. в kebab-case или шашлык-нотации. Такая нотация наиболее популярна в lisp-е и в частности в clojure, но в Java встречается впервые.

    Что касается в целом последних изменений в языке и своего опыта. В последнее время активно использую record. По ощущениям, это “новшество” почти такое же крутое, как появление в 2004-ом году generic-ов в Java 5 или нормальных коллекций в 1998-ом, когда вместо Vector и Hashtable в Java 2 появились List, Map.. Постоянно думаешь, почему этого не было раньше.

    Про sealed не могу сказать также. Жду сентября 2023 года, когда выйдет Java 21 LTS. Тогда можно будет использовать новый pattern matching в полную силу.

    Про новый pattern matching в другой раз, а то итак статья очень большая получилась.

    PS: Сделал телеграм канал @prgrmdr для анонсов

  • Про record

    Появились в версии Java 14, но я предпочитаю использовать LTS версии, поэтому начал активно использовать только в Java 17.

    Не вижу смысла в очередной раз переписывать однотипные статьи из интернета с одними и тем же примерами record-ов вида “Hello World”. Здесь хотел поделиться своими впечатлениями после нескольких месяцев использования, когда и как их удобно использовать, а также небольшими техническими нюансами.

    Если кратко, то самое банальное использование record-ов, это применять их вместо кортежей (tuple). В более сложных кейсах – создание объекта для хранения/передачи данных. Причем хранение и передачи не в контексте работы с СУБД или передачи через сеть, а в самом простом смысле – внутри кода.

    Вот простой пример. Представьте, допустим был какой-то метод:

    String findFoo(...)

    Пусть этот метод возвращает какой-то строковый идентификатор (ID).

    Теперь представим, что ситуация изменилась и нужно возвращать не только ID, а например ещё булевый флаг true/false.

    После наступления такого события у некоторых java-программистов (особенно начинающих) могут начаться душевные метания, экзистенциальный кризис. Возникает внутренний конфликт между необходимостью вернуть из метода сразу несколько значений и отсутствием такой возможность в синтаксисе Java. Причем осознание того, что в языках программирования Scala или Python такая возможность есть ещё больше усиливает страдания и начинает порождать мысли о том, что дальнейшее программирование на Java лишено смысла и нужно что-то делать. Потом возникают различные шальные идеи:

    • А что если просто сделать еще один метод, который делает почти тоже самое, но возвращает булевый флаг, например: boolean findFooFlag(..)?
    • А что если сделать мапу/лист/массив и в него положить два значения, сейчас же это просто! Есть Map.of(), List.of() или вообще все преобразовать к String[]?
      Был метод String findFoo(...), станет String[] findFoo(...).
    • А может взять какой-нибудь готовый Pair<String, Boolean>, смысл изобретать велосипед?
      Был метод String findFoo(...), станет Pair<String, Boolean> findFoo(...). На стековерфлоу предлагают кучу библиотек – javatuples, apache commons collections, Map.Entry и т.д.

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

    Сделать REST-контроллер на Spring-е, который смотрит в БД и возвращает данные – это за 5 минут, никаких проблем. Взять готовый код, поправить в нем какие-то хитрые условия, критерии выборки, разобрать бизнес-логику – 10-15 минут и никаких проблем…

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

    Я вижу несколько причин.

    Во-первых лень. Зачем делать, когда можно не делать и взять готовый Pair, Tuple и т.д.?
    Во-вторых нужно придумывать название для класса. Это сложно.
    В-третьих это “много строк кода” – объявить поля, сделать конструктор, сделать get***() методы для каждого поля. Среда разработки конечно делает эту всю работу за программиста, но все равно нужно лишний раз нажимать на кнопки.


    Ситуация становится совсем фатальной, если добавляется еще один объект, например метод должен возвращать ещё какой-нибудь внешний идентификатор, например long extId. В таком случае Pair не проходит, а делать Pair<String, Pair<Boolean, Long>> или подключать Triplet<String, Boolean, Long> уже перебор.

    Так вот тут нам и помогут record-ы.

    Объявляем например:

    record Foo(String id, boolean enabled, long extId) {} 

    Головная боль уходит!

    Правда есть неудобство, если собираем больше 3-х полей в одном рекорде, то начинает пухнуть конструктор. С учетом того, что в java нет именованных параметров, легко ошибиться и перепутать поля, особенно если все четыре поля – строки. Можно попробовать решить это через билдер, но совсем другая история.

    Кроме этого неудобства, в остальном мне очень нравятся рекорды. Их удобно использовать как в императивном стиле, так и в функциональном, особенно удобно для map-инга в стримах.

    В них есть сразу готовые методы для доступа к полям. В нашем случае id(), enabled(), extId(). Есть готовый toString(), hashCode(), equals().
    Благодаря toString() чуть меньше мороки с логами, а готовый hashCode()/equals(), полезная штука в качестве защиты от дурака, например если рекорды складывать в коллекции.

    Еще рекорды удобны если их вложить внутрь класса. Согласно спецификации вложенный рекорд будет неявный static, т.е. не будет прицепом тащить за собой внешний объект. Более того, его можно объявлять локально, т.е. внутри метода.

    Кстати, для public record-ов конструктор будет всегда public. Просто есть любители статичных фабричных методов, которые прячут private-конструкторами возможность создания объекта. Здесь спрятать просто так не получится.

    Есть интересный вид конструктора, называется компактный конструктор.
    Например вот такой:

    record Foo(String id, boolean enabled, long extId) {
        Foo {
            Objects.requireNonNull(id);
       }
    }

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

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

    В целом по поводу данных, похоже увлечение функциональщиной проходит и отрасль начинает двигаться в сторону data oriented programming (не путать с data driven development и data-oriented design).

    Также с нетерпением жду когда в java появятся а-ля алгебраические типы данных. Сейчас уже через record-классы – мы можем делать подобие умножения, а через sealed-классы – сложение.

    Если из preview режима выведут type pattern matching, то можно начать использовать. По-крайней мере новый instaceof оказался очень удобный.

    До Scala конечно далеко, но таков Java путь.

    PS: У меня слетели все комментарии к блогу, т.к. были через фб, а как подключить новые еще не придумал. Без комментариев конечно грустно. Может придумаю что-то…
    Еще после очередного обновления WP слетело форматирование кода, тоже буду думать, что с этим делать.

  • Все хотят стать программистами

    Как двадцать лет тому назад все хотели стать экономистами. А как иначе? На человека давит авторитетное мнение “знающих” людей – старших товарищей или родителей, пресловутое herd behavior, реклама со всех сторон и вот, в итоге, человек вымучивает поступление на факультет хоть как-то связанный с информационными технологиями или идет в какую-то свежеиспеченную школу-программирования или на худой конец записывается на онлайн-курсы с “гарантированным” трудоустройством.

    Неправильно всё это, так это не работает. Безусловно программирование очень увлекательное занятие, но только для того, кому это интересно и у кого есть к этому склонность. Если нет никакого интереса, зачем заставлять? Очевидно же, что “свобода лучше, чем несвобода”.

    В случае свободного выбора, люди стараются найти занятие, которое максимально соответствует их личным характеристикам. “Принуждение к ИТ” приводит к тому, что человек занимается не тем, в чем лучше всего может себя проявить. В итоге время, которое должно быть потрачено в первую очередь на накопление человеческого капитала (фундаментальное образование, прикладные навыки, саморазвитие и т.д.) тратится в пустую.

    Почему все хотят зайти в ИТ? Мне очень нравится объяснение, которое привела одна моя знакомая:
    – Я не люблю программирование и вообще ИТ, но мне нравятся деньги. Возможно ли так, что моя любовь к деньгам, перевесит нелюбовь к программированию?

    Конечно, при прочих равных, то наверное можно попробовать программирование/верстку/тестирование или что-то ещё в ИТ и только ради денег. С другой стороны может разумнее попробовать такой род деятельности, который все-таки интересен и при этом тоже приносит деньги?

    Может вместо того, чтобы пытаться запихнуть в человека объектно-ориентированное программирование, лямбда-функции и монады, пусть он лучше пойдет учиться к примеру на психолога, управлять яхтой, самолетом или играть на ударных?

    Все-таки программирование это очень специфичная штука. У Сергея Лукьяненко в какой-то книге был эпизод в котором главный герой от безысходности нанимается на звездолет кем-то вроде “расчетного модуля” – сидишь в корабле, а мозги обсчитывают траекторию полета. Так вот в этом фантастическом мире ничего хорошего с такими людьми не происходило. Точно не помню, но кажется около процента может остаться более-менее адекватными, готовыми к живому общению и сохранить интерес к миру и происходящему.

    Может где-то наврал, читал еще студентом, в книжке этот эпизод совсем не главный. Я привел его здесь скорее для яркого образа. Главное о чем я хотел сказать, что если не хочешь и нет в этом крайней нужды, то не нужно становится таким “расчетным модулем”.

    Эта статья в поддержку тех, кто совсем не хочет в ИТ, а все вокруг говорят, что надо.

  • Прошло несколько лет…

    Спустя 4 года и 5 месяцев решил поднять из бэкапа свой блог. Что с ним делать дальше ещё не решил. Пока обновил WordPress и переехал на новый хостинг – VPS-ка от reg.ru. Пока всё устраивает. До этого, когда-то давным давно, пользовался услугами brim.ru, потом кажется DigitalOcean, потом очень долгое время блог жил на виртуалке, которую друзья дали. Это был очень крутой подарок.

    Мне первые несколько лет было интересно писать заметки и статьи в блоге. Потом надоело, наверное перегорел.
    Когда поднял бэкап, обнаружил в черновиках пару недописанных статей – одна про JMX, другая “поток мыслей” про будущее ИТ. Буду думать, что с ними делать. Наверное просто удалю. Смысла нет, поскольку многое поменялось за это время. Персональные блоги почти все переехали на medium, а сайты сейчас делают на тильде (а может уже и нет). Да и в целом мир изменился, я изменился. Java изменилась. WordPress изменился. Его новый интерфейс непривычен, но обещает новые возможности.

    На этом всё. Пусть это будет первая пробная статья после длительного перерыва.

  • Multi-map в Java 8

    Мультикарта (multi-map) может пригодиться в реальной работе или на собеседовании. Почему-то в некоторых компаниях при приёме на работу любят давать алгоритмические задачки на её использование (лично я так не поступаю).
    По сути это обычная карта (Map) в которой значением является коллекция (List или Set).
    Сейчас в JCF (Java Collections Framework) нет готового класса для Multimap.

    До выхода Java 8 приходилось логику работы писать вручную.
    Например так.
    Допустим, нам поступают такие данные:

    Moscow=ru
    Omsk=ru
    Tula=ru
    NY=us
    LA=us
    London=uk и т.д.

    Их нужно представить в виде:

    ru=Moscow, Omsk, Tula
    us=NY, LA
    uk=London

    Тогда логику можно реализовать, например, в таком виде: (далее…)

  • Про настройку шрифтов в IDE (Netbeans) под Linux.

    Какой самый лучший шрифт для программиста?
    Каждому своё.
    Одним нравятся округлые очертания, другому наоборот тонкие и острые. Поэтому выбор шрифта — дело вкуса, хотя конечно есть базовые требования.
    Самое главное и очевидное — шрифт должен быть моноширинным, т.е. все символы должны быть одной ширины. Это очень важно для того, чтобы сохранить структуру кода, т.к. иначе будут плыть все отступы и исходный код будет плохо читаться.
    Если человек пришел в программирование с дизайнерским/типографским прошлым, такой шрифт его может раздражать. Моноширинные шрифты не самые приятные для чтения, хотя их используют не только программисты-техногики, но и люди искусства.
    Например, если верить википедии, в западной театральной и кинематографической традиции сценаристы используют шрифт Courier-12. Одна страница такого сценария длится примерно одну минуту. Вроде это какой-то даже у них стандарт де-факто в отрасли.

    Кроме моноширинности, при выборе следует обратить внимание на следующее:
    – Цифра 0 (ноль) должна отличаться от буквы O.
    – Цифра 1 (один) должна отличаться от буквы l (маленькая L).

    Что касается меня, то сейчас я использую шрифт Consolas.

    Специфика Linux.

    На момент написания этой статьи у некоторых пользователей Linux (Ubuntu) есть определенное недовольство качеством отображения шрифтов в IDE.
    Итак, что можно попробовать сделать.

    Во-первых, я ставлю набор микрософтовских шрифтов:

    $sudo apt-get install ttf-mscorefonts-installer
    

    Во-вторых, особо чувствительные к шрифтам могут поставить Infinality.

    В-третьих и самое главное. Это не сильно помогает, т.к. на момент написания этой статьи в Java (точнее в её графической подсистеме AWT/Swing) есть какие-то проблемы с красивым отображением шрифтом в Ubuntu. Другими словами проблема актуальна для Netbeans и Android Studio.

    Единственное нормальное решение я нашел здесь askubuntu.com.
    Итак чуть более подробный пересказ, что нужно делать.
    (далее…)

  • Про org.json парсер

    С json парсерами в Java дела обстоят следующим образом. С одной стороны их существует несколько разновидностей, с другой стороны сложно сделать выбор.

    Хорошо когда только один критерий принятия решения, например скорость работы или размер библиотеки. Сложности начинаются тогда, когда нужно выбрать с учетом нескольких характеристик.
    В этой небольшой заметке я хотел бы кратко описать случаи, когда уместно использование библиотеки org.json.

    Итак, кратко плюсы и минусы.

    Минусы:
    – Далеко не самый быстрый парсер.
    – Нет автоматической сериализации в JavaBean-ы.

    Плюсы:
    + По-умолчанию есть в стандартной поставке Android
    + Простое API

    Занятные факты:
    ~ Первые версии этой библиотеки были написаны Дугласом Крокфордом (англ. Douglas Crockford) — создателем формата JSON.

    Теперь чуть подробнее.

    Наличие в стандартной поставки Android API это действительно плюс, с учетом лимита в Android-е на кол-во методов в 64К (65 536 шт) любая дополнительная библиотека может обернуться лишней головной болью.

    Другими словами, если нет необходимости разбирать большие массивы данных в json и структура данных примитивна, то им вполне можно обойтись. Типичный пример – небольшой конфигурационный файл, в котором всего около десятка различных параметров.

    В случае если объем данных занимает мегабайты, а ручной разбор и мэппинг в бины – утомителен и однотипен, то естественно надо от него уходить в сторону других решений.
    Лично я предпочитаю в таких случаях использовать gson, но это дело вкуса и технической необходимости. Никаких предубеждений против того же jackson-a я не имею.

    В стандартной Java появление легковесного API пока не предвидится. В новостях были сообщения, что JEP 198: Light-Weight JSON API не будут включать в Java 9, аргументируя это тем, что и так много опенсорных json-парсеров.

    Поэтому если все-таки нужен именно “org.json” в стандартной Java, то его можно подключить через мавен.

    	 	 
    
        org.json
        json
        20160810
     
    

    При этом надо понимать, что во-первых в нормальной Java (не Android) нет ограничений в 64К методов, во-вторых нет стандартного json парсера, поэтому использование org.json не столь очевидно.

    Что касается Java EE, в нем есть стандартный javax.json пакет с классами для работы с JSON-ом.

  • Компьютер/ноутбук для программиста

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

    Мой опыт.

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

    Кратко, как было у меня. Изначально, кажется в 2009-ом году, когда нужно было много ездить по разным встречам, я предпочитал небольшие ноутбуки. В частности, у меня был 13-дюймовый ноутбук (BenQ T31) с достаточными на тот момент характеристикам для компиляции и запуска IDE. Продержался я на нем не так долго, т.к. на маленьком экране и компактной клавиатуре не очень удобно работать. Выходил из положения подключением внешнего монитора (кажется 21-дюймовый Samsung) и клавиатуры.
    probook
    Через некоторое время я заменил BenQ на HP Probook 4720s и отправил старый ноутбук на дачу. Новый ноутбук был полноценной боевой машиной весом больше трех килограмм с 17-дюймовым экраном и нормальной полноразмерной клавиатурой. В целом машиной был доволен, но пришлось приобрести специальный большой компьютерный рюкзак.

    Работать на выезде у заказчика и в поездках стало почти также комфортно как и за рабочим столом. Приблизительно в это же время я перестал работать дома и переехал в коворкинг (на ДЗ Флакон) с фиксированным рабочим местом. При этом от стационарного монитора и клавиатуры я не отказался. Правда я заменил Samsung на ViewSonic чуть большей диагонали.

    Через некоторое время я взял новый ноутбук ASUS G550JK серии ROG (Republic of Gamers).asus Старый ноутбук я отдал племяннику, он на нём учится программировать. Новый ноутбук хоть и был из игровой серии (Asus ROG) именно эта модель получила много негативных отзывов от геймеров, поскольку в нем не самая мощная видеокарта. Для моих задач, как программиста это было не важно, главное было то, что в нем стоит неплохой процессор (i7) и 16 Gb памяти.

    Через некоторое время я сменил внешний монитор ViewSonic на DELL с 24″. Замена мне понравилась. Старый ViewSonic показал себя не с лучшей стороны, первые полтора года отработал без проблем, но потом пару раз сломался, даже пришлось обратиться в гарантийным отдел. Я редко обращаюсь в сервис, обычно не чиню, а просто покупаю новое оборудование и перестаю пользоваться изделиями этого бренда, просто у этого монитора оказалась очень длительная гарантия, но тем не менее, думаю в ближайшее время ViewSonic-ами пользоваться не буду.

    Что касается периферии – мышек и клавиатур, то я меняю их достаточно часто (раз-два в год). Любимые бренды – A4Tech, Logitech и Microsoft. Кстати кто не знает, у микрософта в линейке клавиатур и мышек всегда имелись неплохие модели. Сейчас работаю на Microsoft Wireless Comfort Desktop 5000, уже больше года. Пока это для меня самая удобная клавиатура.

    В такой конфигурации я проработал около года, потом опять всё немного поменялись и я перестал таскать с собой ноутбук на встречи, клиенты стали чаще приезжать сюда в коворкинг. Спустя несколько месяцев у меня оказалась без дела рабочая станция на DELL и я решил переехать с ноутбука на стационарный компьютер. Для того чтобы принять это решение пришлось себя немного “поломать”. Сложно было принять рациональное решение, тем не менее из плюсов – еще лучше железо, больше свободного места на столе и самое главное, не нужно вечно таскать как черепашка-ниндзя на своей спине рюкзак с ноутбуком. После этого у меня началась настоящая “Dolce Vita!” для программиста.

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

    Вот так выглядит мое рабочее место.
    desktop

    Мои друзья.

    Безусловно такое непостоянство в смене компьютеров возможно является следствием моего темперамента или типом личности. Например, мой друг купивший где-то в конце 2000-ных(!) Thinkpad T520 остается ему верен до сих пор. Безусловно это отличная модель, с хорошими характеристиками, четким линиям и выразительными чертами в дизайне. Второй его ноутбук, это Asus ROG, стилизованный под спорткар Ламборгини, обладает ещё большей маскулинностью. Это тяжелая брутальная заряженная машина сделанная в черно-матовом дизайне. Он тяжелый, массивный и очень резвый.

    Если взять другой пример, например вы хрупкая девушка-программист, которая пишет мобильные приложения под iOS и выбираете ноутбук, то в таком случае нужно брать MacBook (или какой-нибудь другой компьютер от Apple). Это будет самый правильный способ и если не хочется каких-то острых извращений, то для эффективной разработки iOS-приложений компьютеры Apple будут самым нормальным решением. Плюс конечно, макбуки это просто красиво и у них действительно неплохая аппаратная платформа. Хотя ничто не идеально, сломаться может всё что угодно, а ремонт мака может обойтись существенно дороже обычного pc.
    (далее…)

  • Установка и настройка Apache Tomcat под Linux

    Tomcat-logo

    Причины.

    Замысел написать эту статью про установку и настройку, наверное, одного и самых популярных веб-серверов на Java возник уже давно. Одной из причин было желание сделать небольшую заметку “для себя” с подробной инструкцией. Возможно эта статья также пригодится другим java программистам. Пользы для кого-нибудь ещё, например для системных администраторов в ней будет не так много. Скорее всего они просто сделают так: apt-get install tomcat8 и затем потребуют у программиста war-ик для развертывания. Программист же часто хочет чуть большего — например, возможности работать с различными версиями серверов (которых может даже ещё нет в официальном репозитории) или наоборот откатиться к какой-то специфичной версии. Системному администратору такие исследования, как правило, не нужны. По-хорошему, у него должна стоять просто стабильная работающая версия, на которую периодически он будет накатывать обновления и лишний раз на неё не дышать.

    В общем, это статья про то, как программисту установить Apache Tomcat под Linux чтобы “поиграться” с ним, но при этом ничего сильно не сломать.
    Также эта статья может быть полезна в тех случаях, когда начинающий java программист отладив свое веб-приложение Tomcat запущенным на Windows, сталкивается со жгучим желанием развернуть свой сайт на какой-нибудь недорогой VPS-ке с Ubunt-ой.

    Статья может показаться излишне многословной, но мне хотелось рассказать про основные “грабли” и способы их обхода. Могу предположить, что системные администраторы могут быть недовольны тем, что это решение недостаточно системные. Поэтому тем, кто хочет подробно изучить данный вопрос или посвятить свою жизнь профессиональной (т.е. получать за это деньги) настройки линуксовых серверов, тому лучше следует обратиться к соответствующей литературе, обучится этому ремеслу у профессионала и черпать знания у сисадминского сообщества. Здесь же у меня просто блог для java программистов.

    Итак, поехали!

    Подготовка

    Исходные данные.
    Linux. Debian 9. 64bit.

    1. Устанавливаем JDK.
    Почему JDK, а не JRE? По-факту достаточно JRE, но лично мне приятно иметь возможность в случае необходимости по-быстрому скомпилировать программку на java прямо на сервере.
    Вы не поверите, но жизнь такая интересная штука, никогда не угадаешь когда тебе может понадобится скомпилировать и запустить что-то на Java. Лично мне запуск javac из консоли на сервере помогал несколько раз.

    Далее, я предпочитаю ставить Oracle JDK. Собственно OpenJDK тоже неплох и устанавливается гораздо проще (sudo apt-get install default-jdk). Просто я отдаю предпочтение оригинальной Sun/Oracle. Тем не менее, ставить Oracle JDK, OpenJDK или какую-либо другую версию – личное дело каждого. Лично я отношусь к пользователям Open JDK без предубеждения. Более того, сам часто использую версии Open JDK (например Java 9) для того, чтобы ознакомиться с их новыми возможностями.

    Установка Oracle JDK под Windows и Linux сильно отличаются. Под Windows проще установить Oracle JDK проще простого (скачать и запустить), а сборку Open JDK под Windows нужно ещё поискать.
    С Linux-ом всё наоборот. Open JDK как я писал ставится очень просто через apt, с Oracle JDK чуть сложнее.

    В интернете существует совет, что для установки нужно добавить ещё один apt-репозиторий. Я так не делаю. Возможно это лично моя паранойя, но я стараюсь так не делать и делаю установку руками. Особенно если учесть, что установка заключается в том, чтобы скачать и распаковать архив.

    Для этого заходим на сайт загрузки Oracle.

    Выбираем jdk-XYZ-linux-x64.tar.gz файл. Правой кнопкой – сохранить ссылку.

    Далее скачиваем архив:

    $wget --header "Cookie: oraclelicense=accept-securebackup-cookie" [ссылка]
    

    Например так:

    $wget --header "Cookie: oraclelicense=accept-securebackup-cookie" 
        http://download.oracle.com/otn-pub/java/jdk/8u73-b02/jdk-8u73-linux-x64.tar.gz
    

    Специально для параноиков, нужно проверить SHA-1 сумму (поскольку выкачиваем-то по голому http).

    Проверяем:

    $sha256sum jdk-8u73-linux-x64.tar.gz
    

    Смотрим что показалось на экране и сверяем значение, с тем что опубликовано на официальном сайте. (далее…)