А мне нравится такой подход. Взять готовые популярные библиотеки и адаптировать под свой каркас с необходимыми интеграциями. Сделать свое ядро на основе хорошо работающих и протестированных решений от других разработчиков, предоставив интерфейсы модулям для инициализации приложения.
Делали так на одном проекте (rest api). Очень понравился результат. Код стал намного чище и гибче.
В России можно смело заменить «вопросы к HR» на «вопросы к руководящему технарю».
Ни один из вышеперечисленных вопросов я не задавал непосредственно HR. HR — это в основном согласование времени собеседования, небольшая вводная по организационным вопросам, проверка на общую адекватность и передача кандидата технарям на растерзание :)
Зато почти половину вопросов на собеседовании задавал людям, с которыми в последствии работал в команде или мне пришлось бы с ними работать. Только они знали ответы, и только их реакцию можно было анализировать. Да и вообще в 80% российских компаний технари являются самым ключевым звеном на собеседованиях (я имею в виду технические должности), и всю информацию нужно тянуть из них.
Но список вопросов очень толковый, учел что-то для себя. Спасибо.
Именно так. Даже более того: монолитная архитектура сэкономит очень много времени, т.к. зачастую внутри все протестировано, и за вами остается только тестирование слоя домена, не углубляясь в дебри ядра. Экономия времени на интеграцию, но можно наткнуться на проблемы роста. Зависит от темпа развития проекта.
Монолит предоставляет или диктует архитектуру постройки приложения. У всех его компонентов и расширений есть интерфейсы для этого. Когда начинаешь отходить от того, что предоставляет фреймворк, рано или поздно приходишь к своему набору библиотек, и сам фреймворк становится не сильно нужен. Разве что отдельные компоненты от него.
Другое дело, что некоторые проекты можно писать в рамках фреймворка и его расширений. И функционала будет достаточно. В таких случаях монолит хороший выбор.
Потому что интерфейсы приложения очень часто выходят за пределы интерфейсов PSR. Например, работа с правами доступа, аутентификация, расширение уникальных типов для абстракций доктрины, регистрация уникальных VO для модулей и т.д. Те же правила роутинга пишутся по разному от библиотеки к библиотеке.
В основном три причины:
— Избыточность, протекание абсолютно ненужного функционала на доменный слой. Может навредить, потому что предоставляет все возможности его причинить.
— Недостаток какого-либо функционала, который необходим. Например, добавить в роутере версионирование api.
— Более строгий интерфейс, который предостережет от множества ошибок в будущем.
Слой приложения
— Создаем интерфейс компонента для приложения.
— Создаем реализацию интерфейса в слое приложения. Это может быть как самописный компонент, так и взятый с гитхаба, обернутый под текущий интерфейс приложения.
Доменный слой
— Создаем базовый bootstrap для модулей, в который инжектим необходимые для доменного слоя интерфейсы (Например, интерфесы для добавления правил роутинга, прав доступа, событийный диспатчер)
— Указываем правила роутинга, прав доступа, обработку событий для каждого отдельного модуля, у которого есть что предоставить этим компонентам.
Вот каждый компонент нужно интегрировать, и использование базового интерфейса библиотеки с гитхаба, как правило, не подходит под задачи проекта. Хоть небольшая оберточка (или большая в отдельных случаях), но будет везде.
Все равно слои зависят от чего-то более базового. Например, мы можем конфигурировать на уровне домена роутинг отдельных модулей, но библиотека роутинга интегрирована на уровне приложения (ядра), и предоставляет интерфейс домену для конфигурации. Реализация интеграции ложится на плечи программиста — это цена такого подхода.
Я прекрасно понимаю, о чем написано в статье. Просто говорю о том, что это весьма затратный путь, и не всегда эти затраты оправданы. И уж точно он требует более глубоких знаний в программировании и проектировании, нежели монолитный фреймворк.
«Пакеты фреймворков» — это отдельные компоненты? Или имеются в виду сами фреймворки?
Если компоненты, то да, решения готовые. Но все равно требуется их интеграция в ядро. А за интеграцией скрывается проектирование интерфейсов, донастройка их под свои нужды, расширение при необходимости, покрытие тестами, чтобы убедиться, что интеграция прошла успешно. Иногда это большие затраты, а иногда интеграция минималистична. Зависит от сложности библиотеки.
Если возможности фреймворка покрывают цели на весомом уровне, лучше взять и использовать фреймворк как проверенное решение. Значительная экономия времени, но обрастание костылями при ситуациях, когда проект растет и архитектура фреймворка перестает справляться со своими задачами.
Если же хочется поэксперементировать с иной архитектурой или точно знаешь, что фреймворк не справится с рядом задач для проекта, можно сделать свое ядро на основе интерфейсов, реализацией которых будут заниматься различные компоненты с гитхаба или самописные либы. Самый затратный вариант по времени и скиллам специалистов, но гарантировано себя оправдывает, если это энтерпрайз уровень, или к качеству кода предъявлены высокие требования.
Лично я для себя выбрал второй вариант, т.к. насмотрелся вдоволь на проекты, которые пошли по первому варианту, и в итоге там стали очень неповоротливыми иной раз даже для простейших доработок. Но затраты на реализацию стали довольно дорогими. Но как разработчику мне больше нравится уделять времени качеству кода, а не переводить время на поиск багов в костылях из-за архитектурных ошибок проекта.
Так или иначе, подход к разработке определит бизнес с его требованиями :)
Просто в голове не укладывается подобное допущение, и думаю, что при росте проекта и команды необходимо ограничивать интерфейс как можно жестче, чтобы мы могли заранее избежать многих казусов, даже не допуская трату времени на ошибки из разряда «мне класс позволяет это сделать, так почему бы и нет?».
А вообще, основной проблемой у вас я вижу протекание логики приложения, инфраструктурной логики на уровень бизнес-логики. Плохо не то, что модули доменного уровня общаются друг с другом через EntityManager (Doctrine как я понимаю?), а то, что они вообще знают о его существовании и его используют. Плохо то, что знают о первичном ключе.
Про первичный ключ я грубо написал — работа ведется непосредственно с самой сущностью, но в большинстве случаев в конечном итоге из этой сущности берется только первичный ключ для записи в базу. Есть, конечно, исключения (например, денормализованные данные для поиска в эластике), и в этих исключениях по текущей схеме проектирования мы работаем с репозиториями очень многих сущностей, что меня и напрягает. Слишком много зависимостей между модулями. Мне не очень нравится, что само понятие «модульность» начинает терять свой смысл.
Столкнулся с тем, что репозитории нарушают инкапсуляцию модулей довольно во многих проектах. Берут Entity из другого модуля и пользуются первичным ключом этой Entity, чтобы скормить менеджеру при создании других зависимых Entity. При этом интерфейс Entity торчит наружу, и мы вольны делать с ней что угодно.
Считаю это неправильным подходом.
Мое решение про закрытие репозитория через классы-интерфесы модуля, которые возвращают read-only Entity для сторонних модулей и не дают им повлиять на состояние сущностей других модулей было наглухо отвергнуто под предлогом «слишком сложно, да и не вижу ничего плохого в подходе с работой Entity из других модулей. Ты же не дурак, и не будешь их изменять в том месте».
Вот сижу и думаю, а какие еще могут быть подходы? Или это нормально, что модули друг с другом общаются через неявный use классов-репозиториев ($entityManager->getRepository(OtherModuleEntity::class))?
Вы действительно хотите получить какие-то результаты от такого хакатона?
Атмосфера ведь вообще непродуктивная. Мне почему-то кажется, что большинство участников придет тупо посмотреть на сиськи.
Больше всего меня раздражали HR из рекрутинговых компаний. Это что-то с чем-то. Проводят получасовую беседу по телефону, чтобы занести в базу обрывки твоих фраз об опыте (при этом имея перед глазами подробнейшее резюме) и пропадают после завершения разговора. Просыпаются через месяц, когда работа уже найдена, и сообщают, что не могут назвать компанию, но вакансия очень подходит по совпадению тех ключевых слов, что были сказаны за месяц до этого по телефону. Таким людям под конец я начал сообщать, что мне не интересны их услуги, и натыкался на такие обиды, будто на их глазах убил котенка.
В целом, примерно 80% моих собеседований (было более 10 в этом году) проводились без участия HR. HR максимум назначал встречу, а собеседовали уже технари. Считаю, что так и должно быть. Задушевная беседа с людьми «не из своего лагеря» не сложится. Ты идешь на собеседование в основном за техническими и организационными данными о компании. Технические директора и тимлиды ответят намного полнее, чем сможет это сделать HR.
Про курсы очень точно подмечено. На курсах можно научиться лишь самым основам для дальнейшего развития.
Сам ходил на курсы по паскалю в старших классах. Получил базовые кирпичики в виде языковых конструкций и основ алгоритмов, начал применять полученные знания уже в сфере веба самостоятельно. Более половины сокурсников ходили сами не зная для чего. Кого родители заставили, кто сам хотел делать игры, и увидя код разочаровался в процессе. Сам преподаватель говорил, что у него пропадает мотивация обучать, т.к. были скромные 15-20%, которые действительно хотели познать дзен. Программирование полностью пропитано внутренней мотивацией. Поэтому я не переживаю за водителей автобусов, которые хотят в IT — из них большая часть все равно вернется обратно за баранку.
Что касается тестовых заданий и трехмесячной стажировки по 2-3 часа в день, то тут бы я никак не согласился на такие условия. Сейчас работу юниором можно получить с гораздо меньшими жертвами и бОльшими компенсациями, чем просто опыт. За те 2-3 месяца стажировки некоторые юниоры уже могут получить небольшое повышение в компании на полной ставке. Я не проработав ни дня на коммерческой разработке получил 2 оффера в первые 3 дня собеседований (дефолт сити). Люди покупались на горящие глаза и верхушки знаний.
Думаю, у наемных программистов это один из самых больных факторов. Потому что работа иногда не оправдывает ожидания, а первоначальные стимулы могут меняться со временем. Да и программистами чаще становятся из-за внутренней мотивации, и когда она начинает конфликтовать с текущим положением дел, начинаются стрессы и прочие психозы.
Лично испытал на себе чувство «побыстрее бы сдать проект и уйти в другое место» с постоянными отсрочками и изменениями требований. Не из приятных.
К сожалению, не доводилось встречать Ваш подход на собеседованиях.
Что касаемо задач, они не обязательно должны быть стандартными. Главное, чтобы были из реального проекта и не слишком узкоспециализированные. Практически в любой компании появляются не совсем тривиальные задачи, которые могут представлять собой подпорку для задач на собеседовании с небольшой доработкой. И порой даже на решении стандартной задачи можно услышать очень оригинальные способы решения (как плохие, так и хорошие). Решение во-первых подкрепит или опровергнет то, что у человека в резюме, а во-вторых покажет, насколько развито у человека критическое мышление, если задача для него нова или он не сталкивался с подобным на прошлых работах.
Я встречал такие вопросы, и часть из них была:
— Зависима от версии Php/MySQL или рабочего окружения.
— Ужасно преподнесена. Например:
$y = 10;
$z = 3;
$x = ( $y % 5 > 0 )? ( $z == 3)? $z * 2: $y + 3: ( $z < 3 )? $y — $z: $z++;
Чему равен x?
— Неполной. Т.е. иногда сам собеседующий путался в вопросе и примере кода.
И никогда не был полностью удовлетворен ответом на вопрос «зачем Вам нужен ответ на это?». Я не вижу преимуществ у людей, которые могут или не могут ответить на подобные вопросы. Игра в интерпретатор хороша при отлове сложных багов, но тут большую роль играет общее знакомство с проектом, а не отлов синтаксических или языковых ошибок (из них до кода проекта доходит лишь очень скромная и практически невесомая часть, т.к. обычно программист тестирует свой код хотя бы на ручном уровне).
Хотите понять мое мышление — дайте практическую задачу, и попросите меня изложить алгоритм решения на словах. Вы получите гораздо больше информации, и я получу минимум стресса и непонимания от вопросов, которые мне непонятны на идеологическом уровне.
Делали так на одном проекте (rest api). Очень понравился результат. Код стал намного чище и гибче.
Ни один из вышеперечисленных вопросов я не задавал непосредственно HR. HR — это в основном согласование времени собеседования, небольшая вводная по организационным вопросам, проверка на общую адекватность и передача кандидата технарям на растерзание :)
Зато почти половину вопросов на собеседовании задавал людям, с которыми в последствии работал в команде или мне пришлось бы с ними работать. Только они знали ответы, и только их реакцию можно было анализировать. Да и вообще в 80% российских компаний технари являются самым ключевым звеном на собеседованиях (я имею в виду технические должности), и всю информацию нужно тянуть из них.
Но список вопросов очень толковый, учел что-то для себя. Спасибо.
Другое дело, что некоторые проекты можно писать в рамках фреймворка и его расширений. И функционала будет достаточно. В таких случаях монолит хороший выбор.
Домен содержит реализацию бизнес-логики и настройку приложения через интерфейсы, иногда внедряя свои зависимости для конкретных модулей.
Иными словами, мы можем легко заменить домен, оставив прим этом приложение. Но не можем заменить приложение для домена.
— Избыточность, протекание абсолютно ненужного функционала на доменный слой. Может навредить, потому что предоставляет все возможности его причинить.
— Недостаток какого-либо функционала, который необходим. Например, добавить в роутере версионирование api.
— Более строгий интерфейс, который предостережет от множества ошибок в будущем.
— Создаем интерфейс компонента для приложения.
— Создаем реализацию интерфейса в слое приложения. Это может быть как самописный компонент, так и взятый с гитхаба, обернутый под текущий интерфейс приложения.
Доменный слой
— Создаем базовый bootstrap для модулей, в который инжектим необходимые для доменного слоя интерфейсы (Например, интерфесы для добавления правил роутинга, прав доступа, событийный диспатчер)
— Указываем правила роутинга, прав доступа, обработку событий для каждого отдельного модуля, у которого есть что предоставить этим компонентам.
Вот каждый компонент нужно интегрировать, и использование базового интерфейса библиотеки с гитхаба, как правило, не подходит под задачи проекта. Хоть небольшая оберточка (или большая в отдельных случаях), но будет везде.
Я прекрасно понимаю, о чем написано в статье. Просто говорю о том, что это весьма затратный путь, и не всегда эти затраты оправданы. И уж точно он требует более глубоких знаний в программировании и проектировании, нежели монолитный фреймворк.
Если компоненты, то да, решения готовые. Но все равно требуется их интеграция в ядро. А за интеграцией скрывается проектирование интерфейсов, донастройка их под свои нужды, расширение при необходимости, покрытие тестами, чтобы убедиться, что интеграция прошла успешно. Иногда это большие затраты, а иногда интеграция минималистична. Зависит от сложности библиотеки.
Если возможности фреймворка покрывают цели на весомом уровне, лучше взять и использовать фреймворк как проверенное решение. Значительная экономия времени, но обрастание костылями при ситуациях, когда проект растет и архитектура фреймворка перестает справляться со своими задачами.
Если же хочется поэксперементировать с иной архитектурой или точно знаешь, что фреймворк не справится с рядом задач для проекта, можно сделать свое ядро на основе интерфейсов, реализацией которых будут заниматься различные компоненты с гитхаба или самописные либы. Самый затратный вариант по времени и скиллам специалистов, но гарантировано себя оправдывает, если это энтерпрайз уровень, или к качеству кода предъявлены высокие требования.
Лично я для себя выбрал второй вариант, т.к. насмотрелся вдоволь на проекты, которые пошли по первому варианту, и в итоге там стали очень неповоротливыми иной раз даже для простейших доработок. Но затраты на реализацию стали довольно дорогими. Но как разработчику мне больше нравится уделять времени качеству кода, а не переводить время на поиск багов в костылях из-за архитектурных ошибок проекта.
Так или иначе, подход к разработке определит бизнес с его требованиями :)
Просто в голове не укладывается подобное допущение, и думаю, что при росте проекта и команды необходимо ограничивать интерфейс как можно жестче, чтобы мы могли заранее избежать многих казусов, даже не допуская трату времени на ошибки из разряда «мне класс позволяет это сделать, так почему бы и нет?».
Про первичный ключ я грубо написал — работа ведется непосредственно с самой сущностью, но в большинстве случаев в конечном итоге из этой сущности берется только первичный ключ для записи в базу. Есть, конечно, исключения (например, денормализованные данные для поиска в эластике), и в этих исключениях по текущей схеме проектирования мы работаем с репозиториями очень многих сущностей, что меня и напрягает. Слишком много зависимостей между модулями. Мне не очень нравится, что само понятие «модульность» начинает терять свой смысл.
Считаю это неправильным подходом.
Мое решение про закрытие репозитория через классы-интерфесы модуля, которые возвращают read-only Entity для сторонних модулей и не дают им повлиять на состояние сущностей других модулей было наглухо отвергнуто под предлогом «слишком сложно, да и не вижу ничего плохого в подходе с работой Entity из других модулей. Ты же не дурак, и не будешь их изменять в том месте».
Вот сижу и думаю, а какие еще могут быть подходы? Или это нормально, что модули друг с другом общаются через неявный use классов-репозиториев ($entityManager->getRepository(OtherModuleEntity::class))?
Атмосфера ведь вообще непродуктивная. Мне почему-то кажется, что большинство участников придет тупо посмотреть на сиськи.
В целом, примерно 80% моих собеседований (было более 10 в этом году) проводились без участия HR. HR максимум назначал встречу, а собеседовали уже технари. Считаю, что так и должно быть. Задушевная беседа с людьми «не из своего лагеря» не сложится. Ты идешь на собеседование в основном за техническими и организационными данными о компании. Технические директора и тимлиды ответят намного полнее, чем сможет это сделать HR.
Сам ходил на курсы по паскалю в старших классах. Получил базовые кирпичики в виде языковых конструкций и основ алгоритмов, начал применять полученные знания уже в сфере веба самостоятельно. Более половины сокурсников ходили сами не зная для чего. Кого родители заставили, кто сам хотел делать игры, и увидя код разочаровался в процессе. Сам преподаватель говорил, что у него пропадает мотивация обучать, т.к. были скромные 15-20%, которые действительно хотели познать дзен. Программирование полностью пропитано внутренней мотивацией. Поэтому я не переживаю за водителей автобусов, которые хотят в IT — из них большая часть все равно вернется обратно за баранку.
Что касается тестовых заданий и трехмесячной стажировки по 2-3 часа в день, то тут бы я никак не согласился на такие условия. Сейчас работу юниором можно получить с гораздо меньшими жертвами и бОльшими компенсациями, чем просто опыт. За те 2-3 месяца стажировки некоторые юниоры уже могут получить небольшое повышение в компании на полной ставке. Я не проработав ни дня на коммерческой разработке получил 2 оффера в первые 3 дня собеседований (дефолт сити). Люди покупались на горящие глаза и верхушки знаний.
Думаю, у наемных программистов это один из самых больных факторов. Потому что работа иногда не оправдывает ожидания, а первоначальные стимулы могут меняться со временем. Да и программистами чаще становятся из-за внутренней мотивации, и когда она начинает конфликтовать с текущим положением дел, начинаются стрессы и прочие психозы.
Лично испытал на себе чувство «побыстрее бы сдать проект и уйти в другое место» с постоянными отсрочками и изменениями требований. Не из приятных.
Что касаемо задач, они не обязательно должны быть стандартными. Главное, чтобы были из реального проекта и не слишком узкоспециализированные. Практически в любой компании появляются не совсем тривиальные задачи, которые могут представлять собой подпорку для задач на собеседовании с небольшой доработкой. И порой даже на решении стандартной задачи можно услышать очень оригинальные способы решения (как плохие, так и хорошие). Решение во-первых подкрепит или опровергнет то, что у человека в резюме, а во-вторых покажет, насколько развито у человека критическое мышление, если задача для него нова или он не сталкивался с подобным на прошлых работах.
— Зависима от версии Php/MySQL или рабочего окружения.
— Ужасно преподнесена. Например:
$y = 10;
$z = 3;
$x = ( $y % 5 > 0 )? ( $z == 3)? $z * 2: $y + 3: ( $z < 3 )? $y — $z: $z++;
Чему равен x?
— Неполной. Т.е. иногда сам собеседующий путался в вопросе и примере кода.
И никогда не был полностью удовлетворен ответом на вопрос «зачем Вам нужен ответ на это?». Я не вижу преимуществ у людей, которые могут или не могут ответить на подобные вопросы. Игра в интерпретатор хороша при отлове сложных багов, но тут большую роль играет общее знакомство с проектом, а не отлов синтаксических или языковых ошибок (из них до кода проекта доходит лишь очень скромная и практически невесомая часть, т.к. обычно программист тестирует свой код хотя бы на ручном уровне).
Хотите понять мое мышление — дайте практическую задачу, и попросите меня изложить алгоритм решения на словах. Вы получите гораздо больше информации, и я получу минимум стресса и непонимания от вопросов, которые мне непонятны на идеологическом уровне.