Спасибо за статью, но код довольно запутанный и следить за ним не просто (Port вызывает методы AbstractActor и наоборот, каждый из них по отдельности нельзя понять), было бы неплохо добавить разбор того что происходит в простой паре producer-consumer и что означает block, поскольку он не блокирующий.
Пока не ясно чем этот подход лучше чего-то вроде:
class ProducerSubscription<T> extends Subscription<T> with Runnable {
private Subscriber<T> subscriber; // from constructor
private AtomicLong demand = new AtomicLong();
private AtomicLong spawnedId = new AtomicLong();
public void request(long size) {
if (demand.getAndAdd(size) == 0) {
executor.execute(this::send);
}
}
private void send() {
long id = spawnedId.incrementAndGet();
// ensure only one send spawned most of the time
while (spawnedId.get() == id) {
long batch = demand.getAndSet(0);
if (batch == 0) break;
while (batch-- > 0) {
subscriber.onNext(....);
}
}
}
}
Кто-то может так и думал, но очень многие просто делают как все, как видели в другом проекте или как генерит билдер проекта. Не все задумываются.
А между прочим такое разделение противоречит даже классическим многослойным архитектурам, так как тут нет бизнес слоя (он обычно размазан по всем, а в пакете "models" обычно анемичные модели или вообще DTO) и подходит разве что если у вас вся бизнес-логика в базе данных.
Абстрагирование — отвлечение в процессе познания от несущественных сторон, свойств, связей объекта (предмета или явления) с целью выделения их существенных, закономерных признаков.
Суть в том, что мы не можем охватить всю систему одновременно, умишком не вышли. Приходится делить ее на части и рассматривать каждую часть в отдельности, называя остальные несущественными для текущего фокуса. Для этого приходится придумывать абстракции и подгонять код под них, даже именованные переменные придумали для этого, потом функции, а потом пошло-поехало...
Я вот всегда задаюсь вопросом — зачем у джунов всегда спрашивают про механизмы наследования или про боксинг? Он же пишет код, если не работает — на стековерфлоу найдет решение, зачем эту теорию зубрить? (сарказм)
Мастерство разработки складывается из двух частей — алгоритмов и структур данных (не заученных, а умения решать задачи и писать код) и архитектуры (умения собрать всякие циклы и хеш-таблицы в большой проект, который не умрет под своим весом).
Когда я спрашиваю про SOLID меня устроит ответ "не помню конкретных принципов, но вот каким должен быть проект". Я вообще уважаю людей, которые ищут причины. Почему в Java при переопределении метода можно сузить тип результата? Почему нельзя добавить исключений? Почему Spring рекомендует инъекцию в конструктор, а не в поле? Почему в проекте обычно пакеты верхнего уровня это models/controllers/services?
Сервис может нарушать DI если хардкодит адрес зависимости, если api не достаточно абстрактен или если сервис полагается на особенности реализации другого.
В силу физического разделения приходится использовать api, но и в ооп интерфейс это не всегда абстракция.
Конечно существуют более общие и более абстрактные принципы как Low Coupling, High Cohesion а так же в целом абстракция. SOLID это более конкретные и более практичные советы на их базе. А уж двигаясь дальше в сторону практики и конкретики возникают паттерны.
Даже если вы соберёте все хотелки от бухгалтеров в одном классе, но код будет на одном уровне абстракции этот код будет лучше, чем многое из того, что я видел.
Для "простой" архитектуры не нужны принципы, это ещё php показал завоевав популярность всем кодом в одном файле.
Конечно не нужно цитировать solid с точностью до буквы, нужно их понять. А когда понял причины понимаешь когда следовать, а когда нарушать.
Не соглашусь с возражением о повторном использовании — эти инструменты достаточно просты, настолько небольшой код не стоит подключения как библиотеки, но использования в рамках проекта как утилиты — вполне.
Что касается SOLID, я пожалуй даже соглашусь, увы это вызвано желанием использовать стандартный тайпкласс, который в Scala не слишком сегрегированный, тут как по мне лучше стандартное чем небольшое. Код же вполне точно описывает требования, странно называть часть требований "особенностью" — все требования особенные.
Если под вашу задачу подходят существующие абстракции — пожалуйста используйте их, в этом и есть смысл сегрегации — небольшие абстракции лучше используются совместно с другими, а значит повторно. Ваш тайпкласс меньше, но не подходит под повторное использование (кстати он нарушает тот же принцип, поскольку его можно разделить на две ортогональных функциональности).
Я бы не назвал это tagless final, просто тайпкласс под специфичную проблему, что в целом не очень хорошо, так как такой тайпкласс не будет повторно использован.
На самом деле интервью вещь двусторонняя, у команды есть свои критерии и если вы по ним не подходите, то и команда вам не подходит. Хотя конечно желательно предупреждать о желаемом стиле.
С одной стороны тестовое задание это маленький пример большого проекта. С другой стороны как по мне сага тут уже перебор, да и редакс для таких мелких проектов не рекомендуют. Кроме того домен на стороне сервера в данный момент не домен вообще, а только набор датаклассов, которые без правил бесполезны, часть реального домена находится в сервисах (но остальная часть сервисов это не домен).
Кстати зачем возня с реентрант локами, когда каждая сессия это один и тот же инстанс, на котором можно синхронизироваться?
Оверинжиниринг это усложнение кода без явной необходимости, дело не только в читабельности. Этот код необходимо будет поддерживать, изменять, исправлять, и вы будете тратить на это больше усилий, чем на более простой код, допуская больше ошибок.
Да, остаток от деления определяется строго говоря делителем, так что нужен zero для типа делителя, да и отрицательные числа из Integral тут не нужны, но это стандартный тайпкласс, проще использовать его, чем писать свой.
В этом то и дело — Java разработчики в среднем дешевле и их больше, что нивелирует размер кода и количество багов. Тем более что на Java проект можно набрать и хороших и средних выдерживая баланс качество/стоимость.
Многие спорят о том, в чем секрет успеха Java. Да, язык консервативен, да, многословен, часто не безопасен, не слишком выразителен и неконсистентен.
Котлин в свою очередь довольно приятный язык, с очень чёткой маркетинговой нишей синтаксического сахара.
Но я думаю Java будет жить. Потому что писать плохой код можно на любом языке — я видел очень много плохого кода на Java и уверен, что Котлин даёт программисту свободу написать ещё хуже (в чем конечно нет вины языка). Java код скушный, но обычно понятный, ужасы кроются на уровень выше — в кривых абстракция, отсутствии архитектуры, копипасте и т.п. Но понятный код даёт ложное ощущение контроля и возможность средним программистам связать воедино куски, которые они не понимают.
Ни в коем случае не утверждаю, что все Java программисты средние — там немало ярких и интересных личностей. Но массовая популярность и спрос, а главное культура языка делают свое дело. И в копилку плюсов идёт все-же возможность как-то заставить этот хаос работать.
Kotlin на мой взгляд это возможность принести в Java проект немного свежего воздуха. Но если вы почувствовали вкус свободы — не стоит останавливаться, идите дальше — есть Scala, Haskell, Rust и много других интересных языков.
Развивайтесь.
Type class это не class, это класс типов — интересный вариант полиморфизма из функциональных языков когда протокол описывается отдельно от самого типа.
Что касается прямой и обратной задачи, prolog реализует поиск решения, описанного программой. Scala этого не делает — поиск нужно описать вместе с решением.
Смотря как считать, все функции кроме собственно fizzBuzz полезны в широком контексте и в проекте были бы общим кодом. Так что самого решения — одна функция в три строки :-)
Спасибо за статью, но код довольно запутанный и следить за ним не просто (Port вызывает методы AbstractActor и наоборот, каждый из них по отдельности нельзя понять), было бы неплохо добавить разбор того что происходит в простой паре producer-consumer и что означает block, поскольку он не блокирующий.
Пока не ясно чем этот подход лучше чего-то вроде:
Кто-то может так и думал, но очень многие просто делают как все, как видели в другом проекте или как генерит билдер проекта. Не все задумываются.
А между прочим такое разделение противоречит даже классическим многослойным архитектурам, так как тут нет бизнес слоя (он обычно размазан по всем, а в пакете "models" обычно анемичные модели или вообще DTO) и подходит разве что если у вас вся бизнес-логика в базе данных.
Суть в том, что мы не можем охватить всю систему одновременно, умишком не вышли. Приходится делить ее на части и рассматривать каждую часть в отдельности, называя остальные несущественными для текущего фокуса. Для этого приходится придумывать абстракции и подгонять код под них, даже именованные переменные придумали для этого, потом функции, а потом пошло-поехало...
Я вот всегда задаюсь вопросом — зачем у джунов всегда спрашивают про механизмы наследования или про боксинг? Он же пишет код, если не работает — на стековерфлоу найдет решение, зачем эту теорию зубрить? (сарказм)
Мастерство разработки складывается из двух частей — алгоритмов и структур данных (не заученных, а умения решать задачи и писать код) и архитектуры (умения собрать всякие циклы и хеш-таблицы в большой проект, который не умрет под своим весом).
Когда я спрашиваю про SOLID меня устроит ответ "не помню конкретных принципов, но вот каким должен быть проект". Я вообще уважаю людей, которые ищут причины. Почему в Java при переопределении метода можно сузить тип результата? Почему нельзя добавить исключений? Почему Spring рекомендует инъекцию в конструктор, а не в поле? Почему в проекте обычно пакеты верхнего уровня это models/controllers/services?
Сервис может нарушать DI если хардкодит адрес зависимости, если api не достаточно абстрактен или если сервис полагается на особенности реализации другого.
В силу физического разделения приходится использовать api, но и в ооп интерфейс это не всегда абстракция.
Почему нет? Полиморфизм это про абстракцию, DI, open/closed, инкапсуляция, паттерны это вообще все абстракции.
Не соглашусь с тем, что SRP только про классы, функция тоже модуль, она тоже должна быть сильно связной и слабо связанной с другими.
Конечно существуют более общие и более абстрактные принципы как Low Coupling, High Cohesion а так же в целом абстракция. SOLID это более конкретные и более практичные советы на их базе. А уж двигаясь дальше в сторону практики и конкретики возникают паттерны.
Спасибо, немного увлёкся)
Даже если вы соберёте все хотелки от бухгалтеров в одном классе, но код будет на одном уровне абстракции этот код будет лучше, чем многое из того, что я видел.
Для "простой" архитектуры не нужны принципы, это ещё php показал завоевав популярность всем кодом в одном файле.
Конечно не нужно цитировать solid с точностью до буквы, нужно их понять. А когда понял причины понимаешь когда следовать, а когда нарушать.
Не соглашусь с возражением о повторном использовании — эти инструменты достаточно просты, настолько небольшой код не стоит подключения как библиотеки, но использования в рамках проекта как утилиты — вполне.
Что касается SOLID, я пожалуй даже соглашусь, увы это вызвано желанием использовать стандартный тайпкласс, который в Scala не слишком сегрегированный, тут как по мне лучше стандартное чем небольшое. Код же вполне точно описывает требования, странно называть часть требований "особенностью" — все требования особенные.
Если под вашу задачу подходят существующие абстракции — пожалуйста используйте их, в этом и есть смысл сегрегации — небольшие абстракции лучше используются совместно с другими, а значит повторно. Ваш тайпкласс меньше, но не подходит под повторное использование (кстати он нарушает тот же принцип, поскольку его можно разделить на две ортогональных функциональности).
Я бы не назвал это tagless final, просто тайпкласс под специфичную проблему, что в целом не очень хорошо, так как такой тайпкласс не будет повторно использован.
На самом деле интервью вещь двусторонняя, у команды есть свои критерии и если вы по ним не подходите, то и команда вам не подходит. Хотя конечно желательно предупреждать о желаемом стиле.
С одной стороны тестовое задание это маленький пример большого проекта. С другой стороны как по мне сага тут уже перебор, да и редакс для таких мелких проектов не рекомендуют. Кроме того домен на стороне сервера в данный момент не домен вообще, а только набор датаклассов, которые без правил бесполезны, часть реального домена находится в сервисах (но остальная часть сервисов это не домен).
Кстати зачем возня с реентрант локами, когда каждая сессия это один и тот же инстанс, на котором можно синхронизироваться?
Оверинжиниринг это усложнение кода без явной необходимости, дело не только в читабельности. Этот код необходимо будет поддерживать, изменять, исправлять, и вы будете тратить на это больше усилий, чем на более простой код, допуская больше ошибок.
На самом деле нет, в коде:
Оператор % это синтаксис для
I.rem
, который импортируется изI
, так что это будет работать для любого типа, не только стандартных числовых.Да, остаток от деления определяется строго говоря делителем, так что нужен zero для типа делителя, да и отрицательные числа из Integral тут не нужны, но это стандартный тайпкласс, проще использовать его, чем писать свой.
В этом то и дело — Java разработчики в среднем дешевле и их больше, что нивелирует размер кода и количество багов. Тем более что на Java проект можно набрать и хороших и средних выдерживая баланс качество/стоимость.
Многие спорят о том, в чем секрет успеха Java. Да, язык консервативен, да, многословен, часто не безопасен, не слишком выразителен и неконсистентен.
Котлин в свою очередь довольно приятный язык, с очень чёткой маркетинговой нишей синтаксического сахара.
Но я думаю Java будет жить. Потому что писать плохой код можно на любом языке — я видел очень много плохого кода на Java и уверен, что Котлин даёт программисту свободу написать ещё хуже (в чем конечно нет вины языка). Java код скушный, но обычно понятный, ужасы кроются на уровень выше — в кривых абстракция, отсутствии архитектуры, копипасте и т.п. Но понятный код даёт ложное ощущение контроля и возможность средним программистам связать воедино куски, которые они не понимают.
Ни в коем случае не утверждаю, что все Java программисты средние — там немало ярких и интересных личностей. Но массовая популярность и спрос, а главное культура языка делают свое дело. И в копилку плюсов идёт все-же возможность как-то заставить этот хаос работать.
Kotlin на мой взгляд это возможность принести в Java проект немного свежего воздуха. Но если вы почувствовали вкус свободы — не стоит останавливаться, идите дальше — есть Scala, Haskell, Rust и много других интересных языков.
Развивайтесь.
Type class это не class, это класс типов — интересный вариант полиморфизма из функциональных языков когда протокол описывается отдельно от самого типа.
Что касается прямой и обратной задачи, prolog реализует поиск решения, описанного программой. Scala этого не делает — поиск нужно описать вместе с решением.
Смотря как считать, все функции кроме собственно
fizzBuzz
полезны в широком контексте и в проекте были бы общим кодом. Так что самого решения — одна функция в три строки :-)