Что такое куб масштабирования?
Куб масштабирования (scale cube, из книги The Art of Scalability) является наглядным изображением трёх ортогональных способов увеличения производительности приложения: sharding, mirrorring и microservices.
• Sharding (data partioning) — разбиение и размещение однотипных данных по разным узлам.
• Mirroring (horizontal duplication) — дублирование или клонирование данных для уменьшения времени отклика.
• Microservices — архитектурный подход, при котором функциональность системы разбивается на отдельные сервисы по бизнес-задачам.
Куб масштабирования (scale cube, из книги The Art of Scalability) является наглядным изображением трёх ортогональных способов увеличения производительности приложения: sharding, mirrorring и microservices.
• Sharding (data partioning) — разбиение и размещение однотипных данных по разным узлам.
• Mirroring (horizontal duplication) — дублирование или клонирование данных для уменьшения времени отклика.
• Microservices — архитектурный подход, при котором функциональность системы разбивается на отдельные сервисы по бизнес-задачам.
👍18🔥3
В каких случаях использование TreeSetпредпочтительнее использования HashSet?
Anonymous Quiz
10%
Если требуется модифицировать производительность итератора по коллекции
9%
Если необходимо часто осуществлять обращение к элементу Set
12%
Если необходимо часто вставлять в Set новые элементы или удалять их
69%
Если нужно гарантировать сохранения порядка элементов коллекции
🔥22👍9
Чем сервисная архитектура отличается от микросервисной?
Сервис-ориентированная архитектура (SOA) — независимый от технологий, компаний и программных продуктов подход к разработке программного обеспечения на основе распределённых, слабосвязанных заменяемых компонентов с чётко определёнными интерфейсами и протоколами взаимодействия. Область охвата SOA — это всё предприятие, где происходит взаимодействие между приложениями. SOA делает ставку на доступ к бизнес-функциям предприятия через повторно используемые интерфейсы.
Сервис в данной архитектуре:
• представляет бизнес-логику с определённым результатом (много ответственностей, связанных единой бизнес-областью, целью, смыслом и т.п.);
• может состоять из других сервисов или зависеть от них;
• является "чёрным ящиком" для своих клиентов.
Как и все серьёзные подходы к чему-либо имеет свой манифест
Микросервисная архитектура (MSA) — частный случай SOA, побуждающий строить взаимодействие насколько это возможно и необходимо небольших, слабосвязанных, легко изменяемых и взаимозаменяемых компонентов (микросервисов). MSA ориентирована, в первую очередь, на структуру и компоненты отдельного приложения.
Микросервис:
• выполняет только одну достаточно элементарную и определённую функцию (Unix way — единственная ответственность);
• деплоится и разрабатывается независимо от других микросервисов;
• является независимым от других микросервисов (в том числе максимальная минимизация общего кода);
• является "чёрным ящиком" для своих клиентов.
Можно найти несколько источников, где MSA представляется как нечто новое и хорошее, а SOA — старое и умирающее. Часто это ещё и подаётся под соусом технологий. ИМХО — это больше маркетинговая туфта, чем хорошее сравнение. MSA и SOA не завязаны на технологии и не ограничивают в их использовании. Более того, оба подхода можно совмещать с пользой для бизнеса.
Сервис-ориентированная архитектура (SOA) — независимый от технологий, компаний и программных продуктов подход к разработке программного обеспечения на основе распределённых, слабосвязанных заменяемых компонентов с чётко определёнными интерфейсами и протоколами взаимодействия. Область охвата SOA — это всё предприятие, где происходит взаимодействие между приложениями. SOA делает ставку на доступ к бизнес-функциям предприятия через повторно используемые интерфейсы.
Сервис в данной архитектуре:
• представляет бизнес-логику с определённым результатом (много ответственностей, связанных единой бизнес-областью, целью, смыслом и т.п.);
• может состоять из других сервисов или зависеть от них;
• является "чёрным ящиком" для своих клиентов.
Как и все серьёзные подходы к чему-либо имеет свой манифест
Микросервисная архитектура (MSA) — частный случай SOA, побуждающий строить взаимодействие насколько это возможно и необходимо небольших, слабосвязанных, легко изменяемых и взаимозаменяемых компонентов (микросервисов). MSA ориентирована, в первую очередь, на структуру и компоненты отдельного приложения.
Микросервис:
• выполняет только одну достаточно элементарную и определённую функцию (Unix way — единственная ответственность);
• деплоится и разрабатывается независимо от других микросервисов;
• является независимым от других микросервисов (в том числе максимальная минимизация общего кода);
• является "чёрным ящиком" для своих клиентов.
Можно найти несколько источников, где MSA представляется как нечто новое и хорошее, а SOA — старое и умирающее. Часто это ещё и подаётся под соусом технологий. ИМХО — это больше маркетинговая туфта, чем хорошее сравнение. MSA и SOA не завязаны на технологии и не ограничивают в их использовании. Более того, оба подхода можно совмещать с пользой для бизнеса.
👍19🔥10❤1☃1
Какие исключения будут брошены методом main?
Anonymous Quiz
38%
IndexOutOfBoundsException
29%
Код не скомпилируется
21%
NullPointerException
12%
ClassCastException
👍16👌6🌭2
Какие есть ограничения у микросервисов? Назовите достоинства и недостатки микросервисной архитектуры
Достоинства:
• Меньше кода на программный компонент (микросервис) -> проще и быстрее разрабатывать, поддерживать, тестировать, понимать, выбросить и переписать, реализовывать с помощью наиболее подходящих технологий и инструментов (в том числе на новые)
• Меньше команда -> меньше проблем и конфликтов при мёрже и совместной разработке
• Проще горизонтально масштабировать
• Быстрее и проще как внедрять, так и откатывать
Недостатки:
• Увеличение накладных расходов на взаимодействие между программными компонентами (микросервисами) — обмен между ними выполняется по сети со всем вытекающим (сериализация/десериализация, задержки и т.д.)
• Возможно появление необходимости распределённых транзакций
• Увеличение объёмов логирования и мониторинга
• Дублирование кода
• Сложнее дебажить и отлавливать ошибки
• Нужно быть готовым и способным продолжить работать, когда любой из микросервисов отвалится
• Общая сложность растёт с количеством микросервисов
Достоинства:
• Меньше кода на программный компонент (микросервис) -> проще и быстрее разрабатывать, поддерживать, тестировать, понимать, выбросить и переписать, реализовывать с помощью наиболее подходящих технологий и инструментов (в том числе на новые)
• Меньше команда -> меньше проблем и конфликтов при мёрже и совместной разработке
• Проще горизонтально масштабировать
• Быстрее и проще как внедрять, так и откатывать
Недостатки:
• Увеличение накладных расходов на взаимодействие между программными компонентами (микросервисами) — обмен между ними выполняется по сети со всем вытекающим (сериализация/десериализация, задержки и т.д.)
• Возможно появление необходимости распределённых транзакций
• Увеличение объёмов логирования и мониторинга
• Дублирование кода
• Сложнее дебажить и отлавливать ошибки
• Нужно быть готовым и способным продолжить работать, когда любой из микросервисов отвалится
• Общая сложность растёт с количеством микросервисов
👍38🤔2
Что выведет следующий код?
Anonymous Quiz
17%
Exception
22%
ArithmeticExceptionFinally
29%
Код не скомпилируется
31%
ExceptionFinally
🌚12👍8🏆3🌭2
Чем композиция отличается от агрегации?
Композиция (composition) — отношение "является частью" (HAS-A Relationship), при котором целое явно контролирует время жизни своей составной части.
Агрегация (aggregation) — отношение "является частью" (HAS-A Relationship), при котором целое хоть и содержит свою составную часть, время их жизни не связано.
Композиция (composition) — отношение "является частью" (HAS-A Relationship), при котором целое явно контролирует время жизни своей составной части.
Агрегация (aggregation) — отношение "является частью" (HAS-A Relationship), при котором целое хоть и содержит свою составную часть, время их жизни не связано.
👍27🤯4🤔3❤🔥1🤣1
Что выведет следующий код?
Anonymous Quiz
31%
36
28%
Результат вычисления имеет непредсказуемое поведение (undefined behavior)
28%
43
13%
33
👍18🌭5⚡2🍌2
Какие бывают тестовые объекты (заглушки)? Чем стаб отличается от мока?
Тестовый объект (Test Double) — объекты, которые необходимы в тестах для подмены внешних зависимостей тестируемого кода.
Типы тестовых объектов:
• Dummy — объекты, которые передаются в методы, но не используются. Например: заполнение списка параметров, часто это просто null
• Fake — заглушка, являющаяся рабочей имплементацией, но с урезанной функциональностью и неприменима в production-окружении. Например: in-memory БД (fake database)
• Stub — заглушка с жестко заданными ответами на вызовы со стороны тестируемого объекта (system under test — SUT) во время теста
• Spy — это разновидность Stub, которая записывает информацию о произошедшем с ней, какие вызовы её методов были выполнены и сколько раз, как изменилось состояние и т.п.
• Mock — заглушка с ожиданиями определённого набора вызовов, которые будут на ней выполнены в ходе теста
Из данного набора заглушек только Mock используется для верификации поведения, остальные — для верификации состояния тестируемого объекта.
Тестовый объект (Test Double) — объекты, которые необходимы в тестах для подмены внешних зависимостей тестируемого кода.
Типы тестовых объектов:
• Dummy — объекты, которые передаются в методы, но не используются. Например: заполнение списка параметров, часто это просто null
• Fake — заглушка, являющаяся рабочей имплементацией, но с урезанной функциональностью и неприменима в production-окружении. Например: in-memory БД (fake database)
• Stub — заглушка с жестко заданными ответами на вызовы со стороны тестируемого объекта (system under test — SUT) во время теста
• Spy — это разновидность Stub, которая записывает информацию о произошедшем с ней, какие вызовы её методов были выполнены и сколько раз, как изменилось состояние и т.п.
• Mock — заглушка с ожиданиями определённого набора вызовов, которые будут на ней выполнены в ходе теста
Из данного набора заглушек только Mock используется для верификации поведения, остальные — для верификации состояния тестируемого объекта.
🔥18👍12☃1
👍15😱15☃14🐳5🤨5
Дайте определение полиморфизму
Термин “полиморфизм” обозначает семейство различных механизмов, позволяющих использовать один и тот же участок программы с различными типами в различных контекстах.
Полиморфизм бывает следующих видов:
1. Универсальный полиморфизм. Он подразделяется на:
• Параметрический полиморфизм — описывает вычисления в общем виде, абстрагируясь от конкретных типов, которые будут использованы. Параметрически полиморфные функции также называются обобщенными (Generic).
• Полиморфизм включений (inclusive) — описывает вычисления не только для конкретного типа, но для и всех его возможных подтипов. Отражает принцип подстановки Барбары Лисков.
2. Специальный полиморфизм (или ad-hoc) — диспетчеризация (перенаправление) к одной или нескольким функциям для конкретного типа аргумента. Из него выделяют подтипы:
• Перегрузка (overloading) позволяет объявлять функции с одним и тем же именем, но с разными типами аргументов и их количеством (арностью).
• Неявное приведение типов — преобразование одного типа в другой по определённым правилам, описанным в стандарте языка, и выполняемое компилятором.
Термин “полиморфизм” обозначает семейство различных механизмов, позволяющих использовать один и тот же участок программы с различными типами в различных контекстах.
Полиморфизм бывает следующих видов:
1. Универсальный полиморфизм. Он подразделяется на:
• Параметрический полиморфизм — описывает вычисления в общем виде, абстрагируясь от конкретных типов, которые будут использованы. Параметрически полиморфные функции также называются обобщенными (Generic).
• Полиморфизм включений (inclusive) — описывает вычисления не только для конкретного типа, но для и всех его возможных подтипов. Отражает принцип подстановки Барбары Лисков.
2. Специальный полиморфизм (или ad-hoc) — диспетчеризация (перенаправление) к одной или нескольким функциям для конкретного типа аргумента. Из него выделяют подтипы:
• Перегрузка (overloading) позволяет объявлять функции с одним и тем же именем, но с разными типами аргументов и их количеством (арностью).
• Неявное приведение типов — преобразование одного типа в другой по определённым правилам, описанным в стандарте языка, и выполняемое компилятором.
👍25😱2🌭2🎉1🍾1
Что выведет следующий код?
Anonymous Quiz
22%
falsetrue
33%
truetrue
14%
falsefalse
31%
Произойдет ошибка компиляции
👍18
Какими коллекциями пользоваться в многопоточной среде?
Первый вариант – превратить в синхронизированную обычную коллекцию, вызвав соответствующий ее типу метод
Если работа с коллекцией состоит в основном из чтения, лучшая в плане производительности альтернатива –
Третий вариант – использование
• Неблокирующие хэш-таблицы
• Неблокирующие очереди
Первый вариант – превратить в синхронизированную обычную коллекцию, вызвав соответствующий ее типу метод
Collections.synchronized*(). Самый общий и самый примитивный способ, создает обертку с синхронизацией всех операций с помощью synchronized.Если работа с коллекцией состоит в основном из чтения, лучшая в плане производительности альтернатива –
CopyOnWriteArrayList, и содержащий его в реализации CopyOnWriteArraySet. Потокобезопасность достигается копированием внутреннего массива при любой модификации, оригинальный массив остается immutable. Program order достигается модификатором volatile на внутреннем массиве.Третий вариант – использование
Concurrent-коллекций:• Неблокирующие хэш-таблицы
ConcurrentSkipListMap, ConcurrentHashMap и ConcurrentSkipListSet (хэш-таблица в основе реализации)• Неблокирующие очереди
ConcurrentLinkedQueue и ConcurrentLinkedDeque
• Большой набор различных блокирующих очередей👍27
Что выведет следующий код?
Anonymous Quiz
37%
truetruetrue
26%
falsefalsefalse
8%
truefalsetrue
29%
falsefalsetrue
👍14🤨1
Как в лямбде изменить внешнюю локальную переменную?
Это нельзя сделать в лоб. Такой код не скомпилируется, потому что захваченная локальная переменная обязана быть effectively final. Такое требование исходит из следующих причин.
Локальная переменная хранится на стеке, а значит время ее жизни в отличие от долгоживущих элементов хипа ограничено скоупом и текущим потоком. Но экземпляр лямбды, захвативший эту переменную, мог бы быть передан наружу и использован для доступа к этой переменной из другого потока и после выхода из метода.
Эта проблема решается тем, что в лямбду копируется значение локальной переменной. Такая копия живет независимо, возможно дольше оригинала. Но это решение приведет к сложному поведению из-за возможности работы с неактуальным значением – копия и оригинал станут двумя разными переменными. Поэтому значение должно быть вечно актуально – неизменяемо.
Поля экземпляра менять можно, потому что захваченной переменной в этом случае выступает effectively final значение this.
Если локальную переменную всё же хочется изменить, решение очевидно – поместить её в кучу. Для этого нужно использовать любого рода обертку: одноэлементный массив, объект-atomic, специально созданный класс с этой переменной как полем.
Хак с оберткой решает проблему времени жизни и даёт коду скомпилироваться, но возвращает проблему сложности поведения. Если среда многопоточная, то вероятно порядок операций с этой переменной придется синхронизировать вручную.
Это нельзя сделать в лоб. Такой код не скомпилируется, потому что захваченная локальная переменная обязана быть effectively final. Такое требование исходит из следующих причин.
Локальная переменная хранится на стеке, а значит время ее жизни в отличие от долгоживущих элементов хипа ограничено скоупом и текущим потоком. Но экземпляр лямбды, захвативший эту переменную, мог бы быть передан наружу и использован для доступа к этой переменной из другого потока и после выхода из метода.
Эта проблема решается тем, что в лямбду копируется значение локальной переменной. Такая копия живет независимо, возможно дольше оригинала. Но это решение приведет к сложному поведению из-за возможности работы с неактуальным значением – копия и оригинал станут двумя разными переменными. Поэтому значение должно быть вечно актуально – неизменяемо.
Поля экземпляра менять можно, потому что захваченной переменной в этом случае выступает effectively final значение this.
Если локальную переменную всё же хочется изменить, решение очевидно – поместить её в кучу. Для этого нужно использовать любого рода обертку: одноэлементный массив, объект-atomic, специально созданный класс с этой переменной как полем.
Хак с оберткой решает проблему времени жизни и даёт коду скомпилироваться, но возвращает проблему сложности поведения. Если среда многопоточная, то вероятно порядок операций с этой переменной придется синхронизировать вручную.
👍21🤯10👏1