Мой любимый пример из личной практики на тему фигурных скобок в однострочниках:
if (logger.isLoggable(Level.DEBUG))
// level.debug("someDebugMsg");
doSomethingValuable();
Собственно, когда система вышла в production и настройки логгинга были изменены, баг внезапно и вылез.
Что касается конкретно Вашего примера — тут в целом ок, т.к. условие и действие в одну строку.
Вы ведь программист баз данных, верно?
Не соглашусь с Вами. Временами, сделать быстрее на БД — возможно, да и посмотреть наверно удобнее.
Только все это очень весело до того момента, пока проект не перевалит через некоторое пороговое значение своего размера и сложности. Потом начинаются неочевидные связи, черные ящики, вертикальное масштабирование и пр. Использование «множества возможностей» в итоге часто оборачиваются проблемами миграции на другие БД (например, при установке системы в банке, который имеет лицензию и поддержку альтернативной БД).
При всем моем уважении и любви к postgres — для меня это не более чем надежное ACID-хранилище, я сторонник логики в приложении почти всегда (за исключением разве что случаев обработки огромных массивов данных, чтобы не гонять их по сети).
Вызов sendfile проходит успешно и отправляет 5 мегабайт данных в буфер отправки.
Я не очень силен во внутренностях nginx, но 5МБ в буфер отправки — слишком расточительно. Сколько одновременных медленных клиентов потянет такой сервер? Даже при уменьшении буфера до мегабайта. Или здесь идет расчет на то, что клиентов не сильно много?
К примеру, выдержит ли сервер простую атаку на открытие ~1000 одновременных медленных curl с единственного хоста? Да и файл может быть не 5МБ, а куда больше.
Из личного опыта смелой профессиональной молодости. Был backend-демон, который контролировал единственность запущенного инстанса аж сразу двумя способами — блокировка pid-файла и pid-порта (реализация была сделана вручную, без врапперов). IDEA подсветила обе static-переменные как "can be converted to local variables", а я взял и поддался. Телефонный звонок тимлида застал меня в отпуске и я на втором слове понял, какую дурацкую ошибку я совершил (java gc закрывал эти объекты спустя какое-то время после старта приложения).
Небольшой оффтоп.
Долгое время сидели на gerrit (обертка над git), его идеология отличается от github-подобных систем тем, что один смысловой changeset — это один коммит, если есть правки после ревью, делается amend/squash, а ревью идет между ревизиями одного changeset. После ревью в основную ветку попадает ровно один коммит.
Так вот это я к тому, что когда изменения по одному тикету размазаны на несколько коммитов, очень неудобно смотреть лог, когда подряд идут коммиты с одним именем, скажем «PROJ-123 fixsmth».
Насколько я знаю, лицензия iOS запрещает создание исполняющей среды (виртуальной машины), поэтому javascript легально нельзя. Даже Chrome для iOS — обертка над Safari. Поправьте меня, если я не прав.
Но даже в случае, если под “full stack” понимать роль архитектора, необходимо определить о каком “стеке” идет речь. Стек веб разработки, мобильной разработки, нативных приложений?
Архитектор не обязан быть профи клиентской разработки, но должен понимать концепции работы GUI и мобильных приложений. К примеру, если речь идет о мобильном геймдеве и архитектор с акцентом на server side, то он по-хорошему должен заниматься протоколом, разбираться в кросс-платформенном C++ (по сути единственный язык программирования, на котором можно написать серверную и мобильную логику всех платформ), представлять ограничения платформы. Но не писать сам мобильный апп.
В противовес «full stack» можно получить другую крайность — каждый занимается своим делом. Вроде хорошо: мобильные разработчики занимаются мобильной разработкой, серверные-серверной, админы админят. Только вот нет человека (как правило, достаточно одного), который имеет общее представление о комплексной системе, видит ее «сверху», видит фундаментальные вещи — архитектуру целого.
Я однажды столкнулся с подобной проблемой, только сорцов не было, т.к. либа была проприетарная. Декомпилировал один нужный мне класс, сделал проект с одним этим классом (в его оригинальном пакете), а исходную либу прицепил как зависимость. Скомпилировал и засунул в архив назад. Вроде так все было.
Хорошие примеры:
Самый банальный пример — LinkedHashMap, protected-метод removeEldestEntry — здесь на уровне класс-дизайна заложили расширенную функциональность, не вытаскивая это в public (например, конструктор с параметром int вводил бы в заблуждение как initialSize, но не maxSize).
В более сложном случае — Spring Jdbc Templates я рассматриваю как один из образцов хорошего API. Развитая структура классов, которая в том числе содержит protected-логику — что позволяет встраиваться через наследование и делать то, что через делегирование требовало бы большого количества повторенного кода, а в некоторых местах было бы невозможно без форка библиотеки.
Плохой пример — любая библиотека, которую пришлось форкнуть, потому что ее class design не позволял изменить логику нужным образом. Здесь может быть много различных оговорок, например, об уместности конкретных доработок, нюансов security (из-за которых часть API может быть приватна или final) и пр., но, надеюсь, я донес свою мысль.
6.6. Все объекты объявляем в максимально узкой области видимости.
Это зависит. Конкретно это очень важно в случае public api, в нем полное скрытие внутренней логики иногда свидетельствует о плохом class design. В грамотном случае внутренняя логика (где это уместно) может быть сделана protected. В каждом конкретном случае, нужно, конечно, смотреть отдельно.
У многих проектов, как slf4j, на гитхабе зеркало, которое могло появиться совсем недавно. То же самое насчет проектов, которые жили много лет на google code, которого не стало. Количество звезд это удобная, но не лучшая мерка.
Собственно, когда система вышла в production и настройки логгинга были изменены, баг внезапно и вылез.
Что касается конкретно Вашего примера — тут в целом ок, т.к. условие и действие в одну строку.
И все же — ваше сообщение скорее про OLAP-область, не OLTP?
Не соглашусь с Вами. Временами, сделать быстрее на БД — возможно, да и посмотреть наверно удобнее.
Только все это очень весело до того момента, пока проект не перевалит через некоторое пороговое значение своего размера и сложности. Потом начинаются неочевидные связи, черные ящики, вертикальное масштабирование и пр. Использование «множества возможностей» в итоге часто оборачиваются проблемами миграции на другие БД (например, при установке системы в банке, который имеет лицензию и поддержку альтернативной БД).
При всем моем уважении и любви к postgres — для меня это не более чем надежное ACID-хранилище, я сторонник логики в приложении почти всегда (за исключением разве что случаев обработки огромных массивов данных, чтобы не гонять их по сети).
Я не очень силен во внутренностях nginx, но 5МБ в буфер отправки — слишком расточительно. Сколько одновременных медленных клиентов потянет такой сервер? Даже при уменьшении буфера до мегабайта. Или здесь идет расчет на то, что клиентов не сильно много?
К примеру, выдержит ли сервер простую атаку на открытие ~1000 одновременных медленных curl с единственного хоста? Да и файл может быть не 5МБ, а куда больше.
Я в MF не силен, но проверил — вызов кидает parse error.
У нас тут свои грабли были с форматом даты:
new SimpleDateFormat("YYYY-MM-DD hh:mm:ss") работало до тех пор, пока не включили setLenient(false) :)
Долгое время сидели на gerrit (обертка над git), его идеология отличается от github-подобных систем тем, что один смысловой changeset — это один коммит, если есть правки после ревью, делается amend/squash, а ревью идет между ревизиями одного changeset. После ревью в основную ветку попадает ровно один коммит.
Так вот это я к тому, что когда изменения по одному тикету размазаны на несколько коммитов, очень неудобно смотреть лог, когда подряд идут коммиты с одним именем, скажем «PROJ-123 fixsmth».
Архитектор не обязан быть профи клиентской разработки, но должен понимать концепции работы GUI и мобильных приложений. К примеру, если речь идет о мобильном геймдеве и архитектор с акцентом на server side, то он по-хорошему должен заниматься протоколом, разбираться в кросс-платформенном C++ (по сути единственный язык программирования, на котором можно написать серверную и мобильную логику всех платформ), представлять ограничения платформы. Но не писать сам мобильный апп.
В противовес «full stack» можно получить другую крайность — каждый занимается своим делом. Вроде хорошо: мобильные разработчики занимаются мобильной разработкой, серверные-серверной, админы админят. Только вот нет человека (как правило, достаточно одного), который имеет общее представление о комплексной системе, видит ее «сверху», видит фундаментальные вещи — архитектуру целого.
Самый банальный пример — LinkedHashMap, protected-метод removeEldestEntry — здесь на уровне класс-дизайна заложили расширенную функциональность, не вытаскивая это в public (например, конструктор с параметром int вводил бы в заблуждение как initialSize, но не maxSize).
В более сложном случае — Spring Jdbc Templates я рассматриваю как один из образцов хорошего API. Развитая структура классов, которая в том числе содержит protected-логику — что позволяет встраиваться через наследование и делать то, что через делегирование требовало бы большого количества повторенного кода, а в некоторых местах было бы невозможно без форка библиотеки.
Плохой пример — любая библиотека, которую пришлось форкнуть, потому что ее class design не позволял изменить логику нужным образом. Здесь может быть много различных оговорок, например, об уместности конкретных доработок, нюансов security (из-за которых часть API может быть приватна или final) и пр., но, надеюсь, я донес свою мысль.
Это зависит. Конкретно это очень важно в случае public api, в нем полное скрытие внутренней логики иногда свидетельствует о плохом class design. В грамотном случае внутренняя логика (где это уместно) может быть сделана protected. В каждом конкретном случае, нужно, конечно, смотреть отдельно.