Pull to refresh
6
0

Разработчик

Send message
Это конечно нифига не репрезентативно и статистики никакой я не собирал специально, но по моим личным впечатленям на основании рассмотрения достаточно большого количества вакансий уровней миддл и синьор(поиск работы весной 2014 в Москве и весной 2015 в Северной Каролине) могу заметить несколько вещей:
— Тут откровенно больше десктопной разработки, особенно WPF.
— Тут достаточно много VB.Net, особенно в госсекторе
— Откровенно слабые собеседования. Топы вроде майкрософта меня не звали на собеседование, но просто крупные компании — вполне. Спрашивали FizzBuzz.
— Хорошему миддлу можно рассчитывать на зарплату примерно в 3-4 раза выше Московской (net).
Зубчатое колесо в центре осталось нераспознанным.
Явно не учли то его количество, которое было произведено при изготовлении аккумуляторных батарей и выработку электроэнергии для их зарядки.
Регулярно слышу от других людей про разделение на тех кто придумывает и на тех кто пишет — за исключением очень редких случаев это просто не работает. По моему опыту продукт такого симбиоза получается не просто с багами а опасно нестабильным. Архитекторы которые сами не участвуют в написании кода проекта — жалкое зрелище. Впрочем как и кодеры, которые понятия не имеют как их код взаимодействуют со связанными компонентами.

Может конечно у Вас более позитивный опыт — очень хотелось бы почитать.
В папке «Samples» от Borland IDE можно найти рабочий пример ТCP-чата
Ваше решение я и имел ввиду в первом комментарии. Выглядит громоздко, но ничего лучше я пока не нашел.
Спасибо. Я имел в виду достаточно распространенные сценарии когда в кеш подгружается много объектов периодически (раз в Х минут). И как правило переживают несколько сборок мусора прежде чем «протухнут». В итоге у нас второе поколение забито миллионами объектов что радикально увеличивает время сборки в этом поколении.

Хорошего универсального способа обойти эти грабли я к сожалению не нашел.
Может быть я невнимательно читал и статья совсем про другое, но я так и не увидел — что происходит с инвалидированными объектами, выкинутыми из кеша, но все еще остающимися в памяти? Висят во втором поколении мертвым грузом, ожидая своего stop the world секунд на несколько?

Имхо это одна из основных проблем для реализации кешей в средах с автоматическим управлением памятью. В недавней статье на хабре на эту тему предлагалось решение через сериализацию в длинные массивы. Ожидал увидеть тут какую-то альтернативу.
Примерно год назад начали наблюдать LicenceException в логе после обновления на 4 версию — ввели ограничение — бесплатны только первые 10 таблиц.
По-хорошему могли хотя бы назвать коммерческий пакет по-другому чтобы не ломать код при обновлениях. В итоге перешли на Dapper, т.к. в OrmLite неизвестно что еще сломают в следующей версии.
Ну все-таки сравнивать компанию, выпускающую коммерческие продукты на андроид с физлицом скачавшим операционку для личных целей несколько некорректно, не находите?
Я, если честно, понятия не имею, каким образом они доказывали вину, знаю лишь, что с провайдера всегда просили паспортные данные и адрес подключения.

Никакую информацию больше. Даже сами логи не спрашивали. И это не единичный случай, запросы приходили регулярно.
У провайдера логи как правило с DHCP или с VPN-сервера. IP+время начала/конца сессии. То есть вся вина на владельце.

Да и из органов, насколько я помню по опыту работы в провайдере, приходит бумага, в которой требование лишь сообщить паспортные данные владельца внешнего IP X.X.X.X в определенное время.

Дальше уже провайдер не участвует, просто выезжают по адресу и забирают всю технику, способную получать IP. В таких условиях доказать свою невиновность — крайне проблематично.
Для тяжелых компонентов — синглтон практически единственный сценарий использования. Для всего остального ничто не мешает использовать IoC классически.
Естественно, если время старта устраивает, смысла нет. Я все это и затеял, когда суммарное время обновления нод (они обновляются по очереди) перевалило за час.
Это хороший подход, мне уже говорили некоторые коллеги, что он более правилен архитектурно. Но он и рассчитан на более хорошую кодовую базу, которая имеется не всегда. Зачастую имеется куча кода (например легаси), который, в общем, не знает об асинхронности, потому что писался 5 лет назад, у которого вся инициализация в конструкторе, который выполняется секунд эдак 30, причем в качестве параметра ему предварительно надо вычислить текущую фазу луны. К нему надо писать дополнительный слой абстракции. Это всё, конечно, крайние случаи, но они показывают что в моем коде разобраться будет, в общем, проще, т.к. вся инициализация от создания до регистрации в контейнере — в одном месте.

Кроме того, непроинициализированный компонент в IoC-контейнере — потенциально опасное место.
Я так изначально и задумывал. Но вышло весьма «корявенько». Поэтому оставил вариант с синхронизацией.
отсутствие выигрыша при параллельном запуске легко может объясняться, например, тем, что у вас все обращения идут к одной БД, и она не справляется
Если асинхронная инициализация отрицательно влияет на производительность, никто ведь не мешает часть компонентов проинициализировать по классической, синхронной схеме. Еще в рамках тюнинга конкретной ситуации можно внутри задачи someTask в самом начале явно прописать await someOtherTask — заставляя someOtherTask завершится до инициализации someTask, что в вашем случае положительно повлияет на производительность.

Я старался решить проблему ускорения загрузки приложений «в общем». Но вышло это ценой расположения регистраций по-порядку в коде (почему многие считают, что это минус?) и регистрации готовых инициализированных инстансов вместо типов (что в моем случае явный плюс, но тоже многие коллеги не согласны).
Как я упоминал в самом начале, для моих задач (бекенд за балансировщиком) мне выгоднее провести инициализацию всего тяжелого именно на старте. Я не хочу увеличивать время отклика первых пришедших пользователей. Поэтому стараюсь на старте загрузить по-максимуму, а отложенную инициализацию использую очень осторожно.
Это также помогает диагностике. Потому что приложение в случае проблем упадет прямо здесь и сейчас в момент запуска, когда администратор занят непосредственно запуском. А не через несколько часов, когда кто-то из клиентов вызовет крайне редкоиспользуемый метод.

Наверное, следовало все-таки вынести в статью, почему я предпочитаю явную инициализацию экземпляров вместо регистрации типов.
Главная причина — это понятность и читаемость кода. Когда открываешь сравнительно простой чужой проект с точки зрения бизнес-логики и видишь в инициализации IoC-контейнера адскую мешанину из многоэтажных конструкций RegisterType, Resolve и InjectionConstructor, то… тоска и желание закрыть это и больше никогда не открывать. Очень тяжело разобраться сходу какая реализация интерфейса будет использоваться в качестве зависимости (реализаций часто несколько), какой конструктор вызван и т.д. Совсем другое дело, когда зависимости компонентов прописаны явно, а не «размазаны» по коду.

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

В случае необходимости отложенной инициализации (как я уже упоминал, для моих задач это редкость) можно попробовать использовать Lazy<>, причем в функторе инициализации придется использовать heavyComponentXTask.Result вместо await heavyComponentXTask

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

В случае, если операции инициализации не приносят выигрыша при параллельном запуске (видимо инициализация происходит практически мгновенно), то инициализация не принесет и значительного проигрыша. Пара миллисекунд на создание обертки в виде задачи над инициализацией компонента — это совсем небольшой оверхед.

А с зависимостями, усложняющими граф самое вкусное. Достаточно описать задачу инициализации зависимости выше по коду чем задачи, где эта зависимость упоминается. Дальше задачи выстроятся в очередь планировщиком за счет использования await «автоматически».
Циклические зависимости компонентов друг от друга я не рассматриваю, т.к. это явные архитектурные проблемы.
12 ...
17

Information

Rating
Does not participate
Location
Cary, North Carolina, США
Registered
Activity