Следует помнить, что вообще в джанге как таковой сервисный слой из коробки не предусмотрен, не считая middleware-ей, но у них немного иное предназначение, afaik.
Поэтому мне не кажется, что закинуть часть логики в модель это «архитектурное самоубийство», не говоря уже о том, что это никак не противоречит DDD.
Главное не забыть, что вся валидация-рендеринг и, возможно, поднятие модельных объектов должно остаться на уровне View, а модель должна работать на уровне именно модели — т.е. взаимодействовать с другими бизнес-объектами и ничего не знать о View.
Мне кажется, в данной статье немного смешаны 2 проблемы.
1-я, техническая на стороне кода — дублирование кода SQL-запросов в приложении.
Сразу же возникает запрос — действительно ли нужен сырой SQL в этих местах? На моей практике он был нужен для действительно тяжелых мест (получение первичных данных для расчета ЗП по подразделению, например), ну и для отчетов. И тех и тех мест мало, они известны, и с ними можно разбираться индивидуально.
Если принять, что в остальных местах SQL генерируется через ORM, то можно избежать дублирования, на мой взгляд. Попробуйте посмотреть в сторону паттерна Specification применительно к построению DAO/Repository слоя — он позволит, в целом, вынести «атомарные» бизнес-условия для сущностей в отдельные спецификации, компонуемые и реюзабельные далее везде в коде. Разумеется, это идеализированно, но тем не менее, может серьезно сократить дублирование кода.
В случае все-таки ручного написания SQL — проблему с повторением кода в целом никак не решить. Равно как и то, что каждый будет писать так, как привык. Остается принять это как данное, и перейти ко второй проблеме :)
2-я проблема, административная, на стороне СУБД — получение и анализ медленных запросов. Поможет slow-лог, очевидно, в той или иной реинкарнации для вашей СУБД. Кто-то (MS) умеет получать эти данные на лету с хорошей разверткой, и выдавать подсказки по индексам, для PostgreSQL/MySQL нужно смотреть именно slow log и далее анализировать запросы поштучно. В общем, зависит от специфики и удобства тулз для СУБД.
Всегда пожалуйста.
В ближайшем рассмотрении, подумайте о том, что nginx-ом стоит отдавать статику — он делает это гораздо лучше апача — экономя память, и CPU. А «динамику» в таком случае можно отдавать цепочкой nginx -> Apache -> JBoss. Это сохранит имеющуюся конфигурацию, и добавит снаружи от неё лишь один элемент — сервер с nginx-ом.
Настроить это достаточно просто — если у вас есть коллеги/друзья, хотя бы более-менее знающие nginx, то за полдня-день неспешно можно всё понять и сделать.
А в JBoss видимо так и остался тяжеловесным на сетевые соединения, что печально :(
Успехов!
Вообще, JBoss вроде бы умеет нормально редеплоить приложения, т.е. практически на лету. У нас на работе аналогичная конфигурация с томкатами — стопится первый, закидывается новый варник, стартует первый, стопится второй итд. Даунтайм равен нулю, не вижу проблем, кроме необходимости легкой автоматизации администратором.
Отвечу за автора — nginx не умеет AJP, но для связи с бэкендами по HTTP — вполне подойдёт. У него есть балансировка, и она будет работать честно. В случае с описанной конфигурацией (с репликацией сессий по всем аппсерверам) — все будет работать правильно.
С «историей» есть проблема — она начинает отъедать немеренно памяти. Потому что на каждое событие создаётся копия рабочего объекта и эта копия добавляется в стек, при нажатии Ctrl-Z сохраненный объект извлекается и замещает собой текущий. Так вот события в рабочей области генерятся оч часто.
babarun, реализуйте историю через паттерн «Команда» (command object). Просто сохраняйте последовательность действий/команд, и научитесь каждое действие откатывать. В таком случае вам не нужно сохранять копии рабочего объекта — это фейловая идея.
Про сервис ничего не скажу, вероятно, есть полезные юзкейсы, надо думать.
По сути описан слегка завуалированный event loop с callback-ами, вызывающимися на каждом «шаге».
Не совсем правильно называть это многозадачностью в классическом понимании.
> Задача это алгоритм обрабатывающий СОБЫТИЯ
Как раз отсюда и следует, что нам нужно обрабатывать много событий псевдопараллельно — значит, нам нужен цикл обработки событий.
Кстати, есть небольшая проблема в описанном подходе. Поскольку время у вас дискретно с шагом 10мс, то порядок обработки пришедших событий определяется исключительно порядком запуска задач, а не порядком возникновения событиый — то есть если одно событие произошло раньше другого, то совсем не следует, что оно будет обработано раньше.
Во-первых, Picasa закрыта (точнее, теперь её функционал в G+)
Во-вторых, к фототехнике пост имеет мало отношения.
В-третьих, видимо, следует переместить в «Я пиарюсь», либо описать больше про техническую часть.
Из положительного — симпатично, + узнаваемый bootstrap :)
На самом деле, можно использовать всё что угодно, лишь бы было удобно :)
Я вместо git-flow порекомендую git-extras, в котором есть различные облегчающие жизнь команды, как то — create&publish/delete branch/tag, генерация changelog-а, различная статистика по репозиторию итд :)
Вы не совсем правы. На Linux-е время не уходит назад при использовании NTP-синхронизации + adjtime (по дефолтам).
Оно может скакнуть назад разово при старте ОС, если включен ntpclient, который как раз выставляет время моментально. Хотя, даже его можно запустить с ключиком -B, который выполнит плавную коррекцию времени.
Так что, отрицательная длина бывает на не линуксах.
По поводу множественной сортировки удобно сделано в DevExpress-овских контролах.
Простой клик по шапке сортирует по колонке(по возрастанию/убыванию), и сбрасывает предыдущую сортировку.
Клик по шапке с Shift-ом добавляет данную колонку к списку сортируемых. Очень просто, и мало кликать.
Еще хорошая вещь придумана с фильтрацией. В шапке таблицы следующей строкой после имён идёт строка с пустыми input-полями для фильтрации — т.е. под каждым именем колонки есть input для поиска по данной колонке. Поэтому не нужно никаких дополнительных открывающихся окон (аля 1С) для фильтрации — вписал в поле, нажал Enter — пошла фильтрация. Фильтрация будет простая — т.е. для строк '..%', для остального — просто сравнение. В отдельном окне можно задать кастомную фильтрацию со всеми плюшками. Такое решение обеспечивает гибкость и достаточную быстроту выполнения типовых операций.
По поводу порядка — при фильтрации понятное дело разницы нет, а при сортировке — можно помечать цифирьками sub/sup-скриптом около имени сортируемой колонки в шапке. Изменять порядок конечно не очень понятно как, я согласен, но отобразить максимально понятно можно.
На самом деле, бессонные ночи — это преувеличение. Там геймплея для прохождения часа на 4 для первого раза, ну и часа 3 для остальных. Хотя после прохождения у вас будет где-то 10 уровень, так что до лимитированного 13 придётся всё же не спать :)
Идея достаточно хорошая. И всё же, её можно немного расширить для масштабируемости следующим образом:
1. Делим всю работу на бранчи master/develop/feature/hotfix и далее по вкусу, как описано в куче трудов.
2. Если вы привязываетесь к количеству коммитов, то логичным будет всю работу делать в feature-бранчах, и по окончанию этой работы делать git merge --no-ff в develop-ветку.
Результат: это даст увеличение количества коммитов в develop-ветке ровно на один, что будет соотвествовать единице добавленного функционала. То есть в dev-бранче +1 версия = +1 реализованный функционал. Удобно.
В feature-бранче же версия, посчитанная вашим образом, имеет конечный смысл для разработчика. И поэтому даст свободу по количеству коммитов в feature-бранче. Я например часто коммичу, тк стараюсь делать это достаточно атомарно.
Но, к сожалению, неизбежно возникает конфликт версий между dev-веткой и feature-веткой, тк версии считаются одинаково. Поэтому, я бы предложил форматировать версию для feature-ветки как-нибудь так:
Версия 0.8.2-<имя feature-ветки>-<количество коммитов в ней>, где 0.8.2 — версия из dev, от которой пошла feature-ветка. Конечный результат:
0.8.2-new_ui-9
Схема:
Версия 0.8.2|...........-> 0.8.3
Ветка dev -----------------------
Ветка new-ui \........./
Поэтому мне не кажется, что закинуть часть логики в модель это «архитектурное самоубийство», не говоря уже о том, что это никак не противоречит DDD.
Главное не забыть, что вся валидация-рендеринг и, возможно, поднятие модельных объектов должно остаться на уровне View, а модель должна работать на уровне именно модели — т.е. взаимодействовать с другими бизнес-объектами и ничего не знать о View.
1-я, техническая на стороне кода — дублирование кода SQL-запросов в приложении.
Сразу же возникает запрос — действительно ли нужен сырой SQL в этих местах? На моей практике он был нужен для действительно тяжелых мест (получение первичных данных для расчета ЗП по подразделению, например), ну и для отчетов. И тех и тех мест мало, они известны, и с ними можно разбираться индивидуально.
Если принять, что в остальных местах SQL генерируется через ORM, то можно избежать дублирования, на мой взгляд. Попробуйте посмотреть в сторону паттерна Specification применительно к построению DAO/Repository слоя — он позволит, в целом, вынести «атомарные» бизнес-условия для сущностей в отдельные спецификации, компонуемые и реюзабельные далее везде в коде. Разумеется, это идеализированно, но тем не менее, может серьезно сократить дублирование кода.
В случае все-таки ручного написания SQL — проблему с повторением кода в целом никак не решить. Равно как и то, что каждый будет писать так, как привык. Остается принять это как данное, и перейти ко второй проблеме :)
2-я проблема, административная, на стороне СУБД — получение и анализ медленных запросов. Поможет slow-лог, очевидно, в той или иной реинкарнации для вашей СУБД. Кто-то (MS) умеет получать эти данные на лету с хорошей разверткой, и выдавать подсказки по индексам, для PostgreSQL/MySQL нужно смотреть именно slow log и далее анализировать запросы поштучно. В общем, зависит от специфики и удобства тулз для СУБД.
В ближайшем рассмотрении, подумайте о том, что nginx-ом стоит отдавать статику — он делает это гораздо лучше апача — экономя память, и CPU. А «динамику» в таком случае можно отдавать цепочкой nginx -> Apache -> JBoss. Это сохранит имеющуюся конфигурацию, и добавит снаружи от неё лишь один элемент — сервер с nginx-ом.
Настроить это достаточно просто — если у вас есть коллеги/друзья, хотя бы более-менее знающие nginx, то за полдня-день неспешно можно всё понять и сделать.
А в JBoss видимо так и остался тяжеловесным на сетевые соединения, что печально :(
Успехов!
babarun, реализуйте историю через паттерн «Команда» (command object). Просто сохраняйте последовательность действий/команд, и научитесь каждое действие откатывать. В таком случае вам не нужно сохранять копии рабочего объекта — это фейловая идея.
Про сервис ничего не скажу, вероятно, есть полезные юзкейсы, надо думать.
Успехов!
По сути описан слегка завуалированный event loop с callback-ами, вызывающимися на каждом «шаге».
Не совсем правильно называть это многозадачностью в классическом понимании.
> Задача это алгоритм обрабатывающий СОБЫТИЯ
Как раз отсюда и следует, что нам нужно обрабатывать много событий псевдопараллельно — значит, нам нужен цикл обработки событий.
Кстати, есть небольшая проблема в описанном подходе. Поскольку время у вас дискретно с шагом 10мс, то порядок обработки пришедших событий определяется исключительно порядком запуска задач, а не порядком возникновения событиый — то есть если одно событие произошло раньше другого, то совсем не следует, что оно будет обработано раньше.
Не смешивайте сущности между собой :)
Во-вторых, к фототехнике пост имеет мало отношения.
В-третьих, видимо, следует переместить в «Я пиарюсь», либо описать больше про техническую часть.
Из положительного — симпатично, + узнаваемый bootstrap :)
Я вместо git-flow порекомендую git-extras, в котором есть различные облегчающие жизнь команды, как то — create&publish/delete branch/tag, генерация changelog-а, различная статистика по репозиторию итд :)
Оно может скакнуть назад разово при старте ОС, если включен ntpclient, который как раз выставляет время моментально. Хотя, даже его можно запустить с ключиком -B, который выполнит плавную коррекцию времени.
Так что, отрицательная длина бывает на не линуксах.
Да, конечно посмотрю, интересно.
Простой клик по шапке сортирует по колонке(по возрастанию/убыванию), и сбрасывает предыдущую сортировку.
Клик по шапке с Shift-ом добавляет данную колонку к списку сортируемых. Очень просто, и мало кликать.
Еще хорошая вещь придумана с фильтрацией. В шапке таблицы следующей строкой после имён идёт строка с пустыми input-полями для фильтрации — т.е. под каждым именем колонки есть input для поиска по данной колонке. Поэтому не нужно никаких дополнительных открывающихся окон (аля 1С) для фильтрации — вписал в поле, нажал Enter — пошла фильтрация. Фильтрация будет простая — т.е. для строк '..%', для остального — просто сравнение. В отдельном окне можно задать кастомную фильтрацию со всеми плюшками. Такое решение обеспечивает гибкость и достаточную быстроту выполнения типовых операций.
По поводу порядка — при фильтрации понятное дело разницы нет, а при сортировке — можно помечать цифирьками sub/sup-скриптом около имени сортируемой колонки в шапке. Изменять порядок конечно не очень понятно как, я согласен, но отобразить максимально понятно можно.
1. Делим всю работу на бранчи master/develop/feature/hotfix и далее по вкусу, как описано в куче трудов.
2. Если вы привязываетесь к количеству коммитов, то логичным будет всю работу делать в feature-бранчах, и по окончанию этой работы делать
git merge --no-ff
в develop-ветку.Результат: это даст увеличение количества коммитов в develop-ветке ровно на один, что будет соотвествовать единице добавленного функционала. То есть в dev-бранче +1 версия = +1 реализованный функционал. Удобно.
В feature-бранче же версия, посчитанная вашим образом, имеет конечный смысл для разработчика. И поэтому даст свободу по количеству коммитов в feature-бранче. Я например часто коммичу, тк стараюсь делать это достаточно атомарно.
Но, к сожалению, неизбежно возникает конфликт версий между dev-веткой и feature-веткой, тк версии считаются одинаково. Поэтому, я бы предложил форматировать версию для feature-ветки как-нибудь так:
Версия 0.8.2-<имя feature-ветки>-<количество коммитов в ней>
, где 0.8.2 — версия из dev, от которой пошла feature-ветка. Конечный результат:0.8.2-new_ui-9
Схема:
Версия 0.8.2|...........-> 0.8.3
Ветка dev -----------------------
Ветка new-ui \........./
Имхо, так лучше.