Некорректно выразился под данными, я имел ввиду конечные реализации.
В целом мне ваша позиция ясна. Вы предлагаете написать две независимые реализации для изменяемых и неизменямых объектов с общим доступом к источнику данных (в примере это массив _vector). Я предлагаю избавиться от дублирования кода реализации и делегировать вызовы неизменяемой реализации изменяемой. Ваша реализация предлагает скорость, т.к. отсутствует промежуточный слой и добавляет сложности в поддерживание кода, т.к. нужно синхронно вносить изменения во все реализации; моя — предлагает некоторое снижение производительности и упрощенное управление кодом, т.к. изменения нужно вносить только в изменяемую реализацию (принцип DRY). Понятно, что выбор целиком зависит от конкретного случая и экономия на промежуточном вызове может оказаться экономией на спичках.
Нет, не бесплатны. Но они не настолько снижают производительность, чтобы от них отказываться в пользу дублирования данных, что, в свою очередь, удваивает количество потребляемой памяти. Это в противовес, фиксированной стоимости промежуточного вызова.
ReadOnlyVector у Вас является оболочкой над Vector, но методы-то в нём Вам всё равно реализовывать. Это и есть то дублирование, которого у меня как раз-таки и нет.
Вся реализация сводится к делегированию подмножества методов для чтения защищаемому объекту. По сути, это реализация паттерна Адаптер.
Кстати говоря, я в статье постоянно упоминал про производительность, а Ваш wrapper — это мягко говоря, не очень эффективное решение.
Это ровно то же самое, что и у меня. Только у меня в ReadOnly сохраняется ссылка на сами данные класса (T[]), а не на сам класс. И вместо моего свойства Reader у Вас AsReadOnly().
Реализации выглядят, похоже, но исключенно дублирование данных и кода реализации. Кроме того, приведено к виду используемом в .Net Framework (пример — List(T).AsReadOnly)
И ещё у Вас Vector наследует от IReadOnlyVector, что заставит Вас реализовывать этот интерфейс дважды.
Что, простите? Не могли бы вы пояснить эту мысль примером с кодом?
И повторюсь, не всё является обычными коллекциями.
Мой предыдущий комментарий не содержал ни слова о коллекциях. Вы можете заменить все вхождения слова vector на user или order и т.д. и получить универсальный паттерн.
Дело не в конкретных интерфейсах, а в подходе. Например:
interface IReadOnlyVector
{
// readonly methods and properties
}
interface IVector : IReadOnlyVector
{
// any methods and properties
}
class ReadOnlyVector : IVector, IReadOnlyVector
{
private readonly IVector vector;
public ReadOnlyVector(IVector vector)
{
this.vector = vector;
}
}
class Vector : IVector, IReadOnlyVector
{
public IReadOnlyVector AsReadOnly()
{
return new ReadOnlyVector(this);
}
}
Защитит вас от downcast. В С++ const и упомянутые интерфейсы для меня это прежде всего контракт, соглашение если угодно, и если пользователь моей библиотеки играет не по правилам, т.е. проводит явное преобразование, то я необязан гарантировать корректное поведение.
Ох, глядя на сайт, чисто юридический подход — много воды с крупицами фактов. Из лучших побуждений:
1. Сократите количество текста, пишите только необходимое;
2. Шаги должны быть простыми и наглядными — сейчас этого нет;
3. Ссылки в зелёных блоках стилизуйте под кнопки;
4. Мыло в лого, которое нельзя скопировать — моветон;
5. Смените логотип — продвигать проект с логотипом, состоящем из буквы Г и чего-то пирамидного и коричневого слева будет очень сложно.
А так вы про эту книгу Dino Esposito. Вот уж кто любит по верхам показать как надо правильно, сильно не вдаваясь в подробности. Книгу ни кому не рекомендую, в отличии от первых его книг по ASP.NET. Лучше уж прочитать ASP.NET MVC in Action.
Во-первых, что отвратительный перевод. Во-вторых, что мы там как раз видим premature generalization. И это скучно и неинтересно.
Здесь не соглашусь, т.к. в статье описано, почему отваливается привязка модели для вложенных моделей в частичных представлениях. Как следствие, показана проблема и решение на основе шаблона редактора. Пост от ScottGu (видимо этот) объясняет, что появилась такая функциональность и чем она полезна. На мой взгляд, в этом посте акцент явно на другом. Если не трудно, то поделиться ссылкой на Dino Esposito, мне его труд на глаза не попадался. Кроме того, в посте есть отсылка к Brad Wilson практически идентичным описанием с ScottGu.
Хотел бы ещё отметить по поводу свежести предыдущий пост Jimmy Bogard, который я также перевёл. Для меня его подход тоже не первой свежести, хотя людей, кто его использует (особенно в России) единицы. Что вы думаете по этому поводу?
Возможно, тем более, что автор несколько раз восхищается функционалом ASP.NET MVC 2. Просто из практики и по постам на gotdotnet вижу, что люди про это не знают или городят откровенные костыли.
Способ достаточно старый и проверенный, но… На мой взгляд главная идея OnStart должна быть в передаче управления сборке с логикой, которая в свою очередь должна быть покрыта тестами. Кроме того, иногда необходимо протестировать с правами под которыми была установлена служба. Поэтому мой выбор System.Diagnostics.Debugger.Break(), а Environment.UserInteractive использую для автоматической установки сервиса.
В целом мне ваша позиция ясна. Вы предлагаете написать две независимые реализации для изменяемых и неизменямых объектов с общим доступом к источнику данных (в примере это массив _vector). Я предлагаю избавиться от дублирования кода реализации и делегировать вызовы неизменяемой реализации изменяемой. Ваша реализация предлагает скорость, т.к. отсутствует промежуточный слой и добавляет сложности в поддерживание кода, т.к. нужно синхронно вносить изменения во все реализации; моя — предлагает некоторое снижение производительности и упрощенное управление кодом, т.к. изменения нужно вносить только в изменяемую реализацию (принцип DRY). Понятно, что выбор целиком зависит от конкретного случая и экономия на промежуточном вызове может оказаться экономией на спичках.
Спасибо за дискуссию, я понял вашу точку зрения.
Вся реализация сводится к делегированию подмножества методов для чтения защищаемому объекту. По сути, это реализация паттерна Адаптер.
Почему?
Реализации выглядят, похоже, но исключенно дублирование данных и кода реализации. Кроме того, приведено к виду используемом в .Net Framework (пример — List(T).AsReadOnly)
Что, простите? Не могли бы вы пояснить эту мысль примером с кодом?
Мой предыдущий комментарий не содержал ни слова о коллекциях. Вы можете заменить все вхождения слова vector на user или order и т.д. и получить универсальный паттерн.
Конечно же.
Защитит вас от downcast. В С++ const и упомянутые интерфейсы для меня это прежде всего контракт, соглашение если угодно, и если пользователь моей библиотеки играет не по правилам, т.е. проводит явное преобразование, то я необязан гарантировать корректное поведение.
Т.е. ваш класс мог бы поддержать интерфейс IEnumerable(T) или IReadOnlyCollection(T). Если добавить к ним ещё IReadOnlyList(T) и IReadOnlyDictionary(TKey, TValue), то в большинстве случаев этого будет достаточно чтобы защитить коллекции от изменений.
1. Сократите количество текста, пишите только необходимое;
2. Шаги должны быть простыми и наглядными — сейчас этого нет;
3. Ссылки в зелёных блоках стилизуйте под кнопки;
4. Мыло в лого, которое нельзя скопировать — моветон;
5. Смените логотип — продвигать проект с логотипом, состоящем из буквы Г и чего-то пирамидного и коричневого слева будет очень сложно.
Спасибо, учту.
Хотел бы ещё отметить по поводу свежести предыдущий пост Jimmy Bogard, который я также перевёл. Для меня его подход тоже не первой свежести, хотя людей, кто его использует (особенно в России) единицы. Что вы думаете по этому поводу?
Однако, наличие собственного дела, которое приносит доход не может не радовать. Успехов.