Comments 32
Спасибо :)
Когда есть смысл писать свой:В первую очередь нужно писать своей, когда ты чувствуешь, что хочешь сделать лучше, чем есть. Это необходимое условие, а достаточное — если ты чувствуешь, что можешь сделать лучше чем есть (включая разные возможности и квалификация и свободное время и финансы). И есть еще одна важная причина написания своего решения, хоть даже есть на рынке и можно купить — владение им vs лицензирование. Представь, что организация имеет тысячи сотрудников, каждому из которых нужно поставить какой-то софт, можно покупать тысячи лицензий, но чаще оказывается, что разработать просто дешевле и потом самому его неограниченно использовать, да и контроль над продуктом есть, ибо производителя сложно убедить, что нужно срочно добавить функцию в его коробочный продукт.
По поводу клиента, и того, что клиент всегда прав — рад, что ты подправил в этой части свое видение. Но я все же приведу тут свое мнение полностью. Я согласен, что хороший прогрммист-исполнитель должен делать то, что у него заказывают, но задача архитектора — показать клиенту в чем он ошибается, он еще и аналитик, и чаще, ему виднее чем заказчику, что именно нужно этому заказчику. Типичный заказчик это пучок заблуждений. Если заказчику вовремя не сделать клизьму головного мозга с ромашкой, а просто сделать то, что он хочет, то проект рухнет и полная отверженность ляжет на заказчика, а частичная (закрытие темы) уже на архитектора. Грамотных заказчиков крайне мало, и их иногда можно выявить по признаку — они спрашивают «возможно, я ошибаюсь, что ты думаешь по этому поводу?». А неграмотные захвачены идеей и эмоциями и у них никогда не возникает сомнения. Если переубеждать заказчика, а он видит потом, что ты был прав и сэкономил ему время, деньги и нервы, то такой заказчик будет уже постоянным твоим приверженцем и не захочет искать кого-то другого на следующие проекты.
Грамотных заказчиков крайне мало, и их иногда можно выявить по признаку — они спрашивают «возможно, я ошибаюсь, что ты думаешь по этому поводу?»
Полностью согласен. Это вообще вопрос присущий людям которые думают. Те кто не думает — уверенны что их мнение единственно-верное, и и мнение других их не интересует в принципе.
но чаще оказывается, что разработать просто дешевле и потом самому его неограниченно использовать
Обычно, компании покупают продукты, чтобы последние приносили деньги. Поэтому, платить программисту, но оттягивать получение продукта — сильно под вопросом. Если в сумме даже и дешевле будет, то потерянное время может быть значительно дороже.
Потом, я как программист, прекрасно в курсе своего бесконечного оптимизма. Всегда есть смысл пользоваться готовым продуктом. Свое — это и свои проблемы поддержки. Не только владение.
Когда нужно (можно) писать свое:
Когда время на «прикручивание» заметно превышает время на реализацию своего. Особенно, в случае, если требуется очень ограниченный функционал. Не писать свои велосипеды — это хорошо и правильно. Но не стоит впадать в другую крайность и на каждый «чих» тащить огромные чужие библиотеки. Как пример, когда-то мне нужно было сделать преобразования Фурье. Мне настоятельно советовали «библиотеку», мол не стоит писать велосипед. После полдня разбирательств, я бросил эту затею и написал что мне надо было: не преувеличиваю, ровно 4 строки кода.
> Логику и типы данных лучше выносить в отдельные сборки
Я один не понял о чем речь?
Я один не понял о чем речь?
Возможно, автор имел ввиду т.н. анемичную модель данных, когда единые модели данных разделяются на модели-контейнеры данных (содержащие в основном поля и свойства) и отдельно — модели по работе с этими данными (содержащие в основном методы по обработке анемичных моделей). Это если я правильно понял.
Да, именно так.
Кстати, это антипаттерн
Не всегда. Могу привести пример:
Common — содержит простые классы предметной области.
Logic.Server — содержит логику серверной части
Logic.Client — содержит логику клиента.
И там и там используются одни и те же классы, но логика разнесена сообразно слоям приложения.
Common — содержит простые классы предметной области.
Logic.Server — содержит логику серверной части
Logic.Client — содержит логику клиента.
И там и там используются одни и те же классы, но логика разнесена сообразно слоям приложения.
Мы рискуем скатиться в очередной холивар «domain-centric vs data-centric архитектуры».
В data-centric архитектуре anemic модель оправдана. Вопрос в том, оправдана ли data-centric архитектура в сложном enterprise-приложении
В data-centric архитектуре anemic модель оправдана. Вопрос в том, оправдана ли data-centric архитектура в сложном enterprise-приложении
Только все равно лучше разделять типы сервера и клиента. И использовать мапперы.
Вообще не антипаттерн. Особенно если работаете с SOA.
Вот что пишет Фаулер на эту тему: www.martinfowler.com/bliki/AnemicDomainModel.html
Я с ним в этой части согласен
Я с ним в этой части согласен
Хорошо, как ваш объект с методами пролезет в сериализацию? Как будет обеспечиваться интероперабельность с другими платформами?
Объект прекрасно сериализируется, не зависимо от того есть у него методы или нет. Взаимодействие с другими платформами так же не зависит от того есть у объектов методы или нет, а обеспечивается через стандартные механизмы, например WCF
Ну да, Dictionary проблем не вызывает, как и циклические ссылки, сериализуется все автоматом, события тоже работают по http.
Где вы в словах «объект с методами» увидели события, словари и циклические ссылки?
смысл в том, что DTO/View-модели делают не от хорошей жизни, а от того, что:
1) попробуйте передать Entity из EF/NHibernate по WCF
2) вы правда, хотите отдать клиенту через сервис отображение вашей БД? обычно надо отдавать немного другое.
1) попробуйте передать Entity из EF/NHibernate по WCF
2) вы правда, хотите отдать клиенту через сервис отображение вашей БД? обычно надо отдавать немного другое.
На моём проекте пришлось отказаться от «классических» моделей типа Active Record в сторону анемичных по 2-м причинам:
1. Увеличение сложности и распухание моделей. Около 20 полей, на каждое по 2 свойства, + обобщающие аксессоры, + 5 конструкторов, и очень много методов по работе со всем этим добром. И это всё — единая сущность. Прошло время, и сложность увеличилась до такого уровня, что ни вынос Repository в отдельный слой, ни наследование, ни вложенные классы не помогли уменьшить 1000+-строкового монстра. разделение данных и методов помогает бороться со сложностью.
2. Проблемы с сериализацией (ASP.NET 3.5). Для хранения данных в сессии используется State Server => все объекты, подлежащие хранению, должны быть помечены атрибутом [Serializable()]. Соотв., если у вас класс, поля которого являются другими классами, то вся эта цепочка тоже должна быть помечена через данный атрибут. А так как модели неразрывно связаны с Repository, ViewModels и Service layer, то лепить атрибут [Serializable()] пришлось бы вообще на всё подряд.
1. Увеличение сложности и распухание моделей. Около 20 полей, на каждое по 2 свойства, + обобщающие аксессоры, + 5 конструкторов, и очень много методов по работе со всем этим добром. И это всё — единая сущность. Прошло время, и сложность увеличилась до такого уровня, что ни вынос Repository в отдельный слой, ни наследование, ни вложенные классы не помогли уменьшить 1000+-строкового монстра. разделение данных и методов помогает бороться со сложностью.
2. Проблемы с сериализацией (ASP.NET 3.5). Для хранения данных в сессии используется State Server => все объекты, подлежащие хранению, должны быть помечены атрибутом [Serializable()]. Соотв., если у вас класс, поля которого являются другими классами, то вся эта цепочка тоже должна быть помечена через данный атрибут. А так как модели неразрывно связаны с Repository, ViewModels и Service layer, то лепить атрибут [Serializable()] пришлось бы вообще на всё подряд.
1. Вы выбрали неверный способ борьбы со сложностью. Помещать все методы, относящиеся к классу, в этот класс — такой же антипаттерн как и анемичная модель. Должно быть разделение на репозитории, сервисы, доменную модель, фабрики и т.д. Рекомендую прочесть «DDD» Эванса. Также можно прослушать наше обсуждение книги: ru-studygroup.livejournal.com/1517.html
2. Хранение в кеше — отдельная тема. Вкратце — нужно либо исключать из сериализации ненужные поля атрибутом [NonSerialized], либо делать свою систему сериализации
2. Хранение в кеше — отдельная тема. Вкратце — нужно либо исключать из сериализации ненужные поля атрибутом [NonSerialized], либо делать свою систему сериализации
«Использование linq — это синтаксический сахар! Циклы и перебор лучше.»
Забудьте это. А еще лучше, возьмите свой сложный алгоритм на переборах, перепишите на linq и замерьте. Будете удивлены. В большинстве случаев linq будет работать так же, как и на переборах. Причем не важно for или foreach
UFO just landed and posted this here
Замерял. Работал правда не с Linq2SQL, а обычным Linq2Objects. Разница очень серьёзная в сравнении с for.
Я не помню, инлайнит ли полный десктопный JIT маленькие лямбды, но CE ничего подобного не делает. И миллионы раз вызывает метод, что крайне дорого (расположение аргументов на стеке, возврат, и так далее). И чем больше Linq инструкций (Select, Where, Aggregate и тд) у вас будет тем хуже.
Я не помню, инлайнит ли полный десктопный JIT маленькие лямбды, но CE ничего подобного не делает. И миллионы раз вызывает метод, что крайне дорого (расположение аргументов на стеке, возврат, и так далее). И чем больше Linq инструкций (Select, Where, Aggregate и тд) у вас будет тем хуже.
Вы сейчас попробуйте. Когда появился Linq — тормоза были, помню. В 4.5 дотнете уже всё в порядке. Вполне может быть, что linq не супер всё может оптимизировать, как это можно было бы вылизать долгими трудами и страшным кодом с помощью переборов, но работает в основном хорошо.
Я замерял и удивился. Реально сложный алгоритм, с групбаями, и всем прочим. Конечно, не могу сказать, что прямо репрезентативные замеры получились. Меня интересовал только мой алгоритм, исследования не проводил. Но вот линькью дал одинаковую производительность с «оптимизированным» алгоритмом. А код в несколько раз стал меньше и намного более читаемый. Причем, не важно, со структурами он работает, с классами и т.д.
Я замерял и удивился. Реально сложный алгоритм, с групбаями, и всем прочим. Конечно, не могу сказать, что прямо репрезентативные замеры получились. Меня интересовал только мой алгоритм, исследования не проводил. Но вот линькью дал одинаковую производительность с «оптимизированным» алгоритмом. А код в несколько раз стал меньше и намного более читаемый. Причем, не важно, со структурами он работает, с классами и т.д.
Про читаемость соглашусь, про перфоманс нет :)
Для сложного алгоритма у Linq в любом случае будет приличный оверхед(там явно компилятор не соптимизирует ничего). Ну скажем соотношение по времени с развернуты руками циклом будет 2:3.
Если получилось одно и то же время, вероятно вы просто что-то не то меряли и «переоптимизировали» алгоритм руками (например забыли про какой нибудь досрочный выход из цикла по условию :)
Для сложного алгоритма у Linq в любом случае будет приличный оверхед(там явно компилятор не соптимизирует ничего). Ну скажем соотношение по времени с развернуты руками циклом будет 2:3.
Если получилось одно и то же время, вероятно вы просто что-то не то меряли и «переоптимизировали» алгоритм руками (например забыли про какой нибудь досрочный выход из цикла по условию :)
Как минимум — получилось. Если действительно бывает, что линькью делает так же, как и ручной перебор, то уже можно следовать железному правилу — писать на линькью. А если окажется (вдруг), что тормозит, смотреть почему и оптимизировать. (достаточно сложный был у меня алгоритм с проверками и брейками)
Линькью может теоретически неплохо оптимизировать, если будет «знать», что данные в пределах запроса «иммутабельны» и плохо в других случаях, но не обязательно хуже, чем руками.
Потом, главное, что он не тормозит на порядки. Что он структуры не боксирует «по умолчанию». Что он приблизительно то же самое делает, что и руками. Поэтому, в большинстве случаев оптимизация переборами будет лишняя.
Я готов поверить, что в 3.0-3.5 дотнете линькью мог «принципиально» сильно тормозить. В результате чего и в посте написали — лучше перебор. Сейчас я такого не наблюдаю.
Линькью может теоретически неплохо оптимизировать, если будет «знать», что данные в пределах запроса «иммутабельны» и плохо в других случаях, но не обязательно хуже, чем руками.
Потом, главное, что он не тормозит на порядки. Что он структуры не боксирует «по умолчанию». Что он приблизительно то же самое делает, что и руками. Поэтому, в большинстве случаев оптимизация переборами будет лишняя.
Я готов поверить, что в 3.0-3.5 дотнете линькью мог «принципиально» сильно тормозить. В результате чего и в посте написали — лучше перебор. Сейчас я такого не наблюдаю.
На каждый пункт можно привести не один аргумент как «за» так и «против». Хоть бы и отсюда
Несколько пунктов.
Упрощать сложно. Нужны критерии «простоты» — что именно должно быть «просто»? Потому что абсолютно все «просто» быть не может.
Конечно, кто спорит. Но есть нюанс — нужно знать, что есть этот фреймворк, нужно понять, что он в принципе подходит, нужно знать, как именно его правильно использовать. А если их несколько похожих — нужно сравнить и выбрать наиболее подходящий. А время идет и подспудно сидит мысль — "давно бы уже сам все написал, чем сидеть выбирать, я ж программист, и я точно знаю, что именно мне нужно!"
Тоже поспорю. Плохое ТЗ создает ложное представление о наличии какой-то информации, в то время как на самом деле информация может быть неактуальной, несистематизированной и т.п. И разработка по этому ТЗ будет пустой тратой времени. А делать не то что нужно — это (имхо) обычно гораздо хуже, чем вообще ничего не делать.
Каждый проект — сложный клубок компромиссов и паллиативов, основанных на предметной области, задаче и опыте каждой конкретной команды. И никакой «свод правил» не избавит от проблем. Вопрос только в их количестве :)
Несколько пунктов.
Чем проще решение тем оно надежней
Упрощать сложно. Нужны критерии «простоты» — что именно должно быть «просто»? Потому что абсолютно все «просто» быть не может.
Не стоит изобретатель велосипеды
Конечно, кто спорит. Но есть нюанс — нужно знать, что есть этот фреймворк, нужно понять, что он в принципе подходит, нужно знать, как именно его правильно использовать. А если их несколько похожих — нужно сравнить и выбрать наиболее подходящий. А время идет и подспудно сидит мысль — "давно бы уже сам все написал, чем сидеть выбирать, я ж программист, и я точно знаю, что именно мне нужно!"
Даже плохое ТЗ лучше чем отсутствие какого либо.
Тоже поспорю. Плохое ТЗ создает ложное представление о наличии какой-то информации, в то время как на самом деле информация может быть неактуальной, несистематизированной и т.п. И разработка по этому ТЗ будет пустой тратой времени. А делать не то что нужно — это (имхо) обычно гораздо хуже, чем вообще ничего не делать.
Каждый проект — сложный клубок компромиссов и паллиативов, основанных на предметной области, задаче и опыте каждой конкретной команды. И никакой «свод правил» не избавит от проблем. Вопрос только в их количестве :)
Так же встречались разработчики, которые предлагали клиенту отказаться от функционала, так как его не поддерживает CMS с которой разработчик умеет работать. Такой подход недопустим, если вы действительно хотите создать качественный продукт.
Бывают и такие случаи: у компании уже есть система с инструментами, в конечном итоге дающими заказчику тот результат, который он хотел; однако заказчик из-за недостатка опыта работы с подобными системами, либо от переизбытка фантазии, начинает выдумывать настолько нестандартные и бессмысленные варианты решения тех же самых задач и при этом настолько упорно стоит на своём и не хочет понимать объяснений, что аргумент «наша система не позволяет этого сделать» начинает казаться не таким уж и ужасным :)
Хочется пожелать всем — не только работайте, но и живите!
Как говорят французы «Art de vivre»
Ребята, будем жить! (с) :-)
Спасибо за теплые слова.
Спасибо за теплые слова.
Sign up to leave a comment.
Правила жизни в ИТ проектах