А зачем? Вот опять-таки, если мы не говорим о модульности (нет требований) и не говорим о тестируемости — то зачем нам видеть внешние зависимости?
Если это сервисный класс (например, контроллер в ASP.NET MVC), то наверное и правда незачем. Если доменный, то чем четче вы очертите в коде его ответственности и зависимости, тем лучше для поддержки такого кода, т.к доменный слой — это ядро системы. В-общем, думаю вопрос действительно спорный и неоднозначный, много зависит от привычек конкретных разработчиков. Каких-то явный преимуществ кроме некоторого субъективного повышения читаемости я назвать сейчас не могу.
Если бы все люди исполняли свои обязанности, жизнь была бы прекрасна. Однако даже в одной команде при большой базе кода это малореализуемо (к сожалению), а уж при взаимодействии нескольких команд… В итоге, в каждом месте, где есть возможность расширения, появляется необходимость обработки всех пограничных ситуаций.
Вы в любом случае не сможете оградить вашу систему от того, чтобы разработчики дописали ее так, чтобы все сломалось. Эти вещи не решаются техническими средствами — только общением.
У каждого решения есть свои trade-offs. Черт с ней с тестируемостью, но ваше решение не очень хорошее с т.з. читаемости — нельзя сразу понять какие у класса внешние зависимости. Решение с интерфейсами мне нравится еще меньше — вводить интерфейсы «чтоб было» противоречит YAGNI.
Лучшим решением здесь я считаю внедрением конкретных классов. Выделять интерфейсы/абстрактные классы не следует до того, как появится доменная необходимость в них (создание mock/stub не входит в это понятие).
Единственный минус здесь — невозможно определить класс как sealed и необходимость пометки методов как virtual.
Кстати по поводу того, что «в нем остается слишком много точек расширения, чтобы его можно было сломать» — это уже обязанность разработчика подкласса писать его так, чтобы он не нарушал LSP.
Мне кажется этот вариант устроил бы вас и вашего оппонента как компромиссный. С одной стороны вы используете DI, с другой — не вводите ненужные абстракции
Согласен со всем написанным вами, но хочу высказать два замечания.
1) Вы неправильно используете термин «POCO-объекты». Poco по аналогии с pojo означает «чистые» объекты, не унаследованные от громоздких базовых классов и интерфейсов. Например если вы строите свою доменную модель, то не нужно наследоваться от классов из пространства имен ComponentModel, напишите свои, простые и понятные классы. При этом в poco вполне могут быть как данные, так и методы по работе с ними, это номальные классы rich-модели. То, о чем пишете вы, называется просто анемичная модель.
2) Если вы используете NHibernate, то можете указать два конструктора — один private без параметров только для ORM, второй нормальный public для классов бизнес логики, это решает проблемы контрактов класса.
Плюс в ORM без годогеренации вполне можно соблюсти контракты, добавляя конструктор по умолчанию с модификатором доступа private, чтобы к нему имела доступ только ORM
К предыдущему комменту добавил бы еще: тем не менее, алгоритмы — это очень хорошо. У многих энтерпрайз разработчиков в этом пробел и часто вижу что уже опытные коллеги (я в том числе) начинают изучать их, чтобы его заполнить.
Не позволяйте самомнению (все мы мнительные) мешать объективно смотреть на свой уровень, изучайте все, до чего сможете дотянуться, и вы подтянитесь довольно быстро.
Если не секрет, более выгодные предложения — это какие?
Как вы оцениваете идею о том, на любой планете с более-менее подходящими условиями почти со 100% вероятностью в течение нескольких сот миллионов лет появляется простейшая жизнь? Если на Марсе обнаружат ее следы, то идея получит весомую аргументацию
Закроется только в релизной версии с включенной оптимизацией кода. Иначе локальные переменные трактуются как «живые» вплоть до выхода из области их видимости.
Первые два пункта — абсолютно верно, compareTo дает менее строгий результат, чем equals, например в некотрых локалях «u» и «u с черточкой» выдают compareTo == 0
Child контейнеры (в Unity) нужны, чтобы разделить логику резолва зависимостей. К примеру для классов такого-то типа резолвить IContext в Context1, для других — в Context2.
В Windsor это достигается путем добавления SelectionHandler-ов
Именно. IEnumerable предполагает только то, что по коллекции можно пройтись, ничего более.
И кстати это одна из причин не использовать IEnumerable на практике: интерфейс не налагает почти никаких предусловий, что приводит к тому, что реализации интерфейса гарантируемо нарушают принцип LSP, т.к. невозможно реализовать его, не усилив предусловия: требуется либо коннект к базе (в случае с LINQ-2-SQL), либо конечность коллекции (во всех остальных случаях).
Лично я использую и всем рекомендую использовать IList<>, либо IReadOnlyList<>
Я и не писал, что масса покоя растет со скоростью. Гравитирующая масса — абстракция, заменяющая собой понятие тензора энергии-импульса тела.
Суть в том, что с возрастанием скорости тела оно сильнее искривляет пространство-время, т.е. сила притяжения этого тела увеличивается. Это и есть «гравитирующая масса»
Если это сервисный класс (например, контроллер в ASP.NET MVC), то наверное и правда незачем. Если доменный, то чем четче вы очертите в коде его ответственности и зависимости, тем лучше для поддержки такого кода, т.к доменный слой — это ядро системы. В-общем, думаю вопрос действительно спорный и неоднозначный, много зависит от привычек конкретных разработчиков. Каких-то явный преимуществ кроме некоторого субъективного повышения читаемости я назвать сейчас не могу.
Вы в любом случае не сможете оградить вашу систему от того, чтобы разработчики дописали ее так, чтобы все сломалось. Эти вещи не решаются техническими средствами — только общением.
Лучшим решением здесь я считаю внедрением конкретных классов. Выделять интерфейсы/абстрактные классы не следует до того, как появится доменная необходимость в них (создание mock/stub не входит в это понятие).
Единственный минус здесь — невозможно определить класс как sealed и необходимость пометки методов как virtual.
Кстати по поводу того, что «в нем остается слишком много точек расширения, чтобы его можно было сломать» — это уже обязанность разработчика подкласса писать его так, чтобы он не нарушал LSP.
1) Вы неправильно используете термин «POCO-объекты». Poco по аналогии с pojo означает «чистые» объекты, не унаследованные от громоздких базовых классов и интерфейсов. Например если вы строите свою доменную модель, то не нужно наследоваться от классов из пространства имен ComponentModel, напишите свои, простые и понятные классы. При этом в poco вполне могут быть как данные, так и методы по работе с ними, это номальные классы rich-модели. То, о чем пишете вы, называется просто анемичная модель.
2) Если вы используете NHibernate, то можете указать два конструктора — один private без параметров только для ORM, второй нормальный public для классов бизнес логики, это решает проблемы контрактов класса.
Не позволяйте самомнению (все мы мнительные) мешать объективно смотреть на свой уровень, изучайте все, до чего сможете дотянуться, и вы подтянитесь довольно быстро.
Если не секрет, более выгодные предложения — это какие?
Первые два пункта — абсолютно верно, compareTo дает менее строгий результат, чем equals, например в некотрых локалях «u» и «u с черточкой» выдают compareTo == 0
В Windsor это достигается путем добавления SelectionHandler-ов
И кстати это одна из причин не использовать IEnumerable на практике: интерфейс не налагает почти никаких предусловий, что приводит к тому, что реализации интерфейса гарантируемо нарушают принцип LSP, т.к. невозможно реализовать его, не усилив предусловия: требуется либо коннект к базе (в случае с LINQ-2-SQL), либо конечность коллекции (во всех остальных случаях).
Лично я использую и всем рекомендую использовать IList<>, либо IReadOnlyList<>
Суть в том, что с возрастанием скорости тела оно сильнее искривляет пространство-время, т.е. сила притяжения этого тела увеличивается. Это и есть «гравитирующая масса»