Re[4]: Сергей Тепляков книжку написал!
От: LaptevVV Россия  
Дата: 29.04.15 03:53
Оценка:
LVV>>1. Если мы всех программеров поделим на касты: юниор, постюниор, мидл, постмидл, эксперт, — то книжка написана как минимум постмидлом для мидлов.
I>В этой книге продолжается тема GoF, фактически подмена решения проблемы и проектирование на перебор паттернов. Кому ты это адресуешь, совершенно неинтересно.
Не. Адресат — важен. Прежде, чем книжку писать — важно определиться с тем, кому книжка предназначена. Вот я четко знал, что пишу для своих студентов.
Соответственно и строил изложение.
Здесь книжка как минимум для постюниоров — студенты мало что поймут.
LVV>>2. В книжке есть сквозной пример: простое приложение импорта лог-файлов для последующего полнотекстового поиска. На нем все паттерны и показываются.
I>Плохой пример. Нужны реальные проблемы, а не высосаные из пальца. Вот скажем у Джошуа Кериевски, Физерса и того же Кента Бека очень четкий подход, резко отличный от GoF. Посмотри туда для начала.
Ну, если лог-файлы существуют — значит это кому-нибудь нужно?
Физерс — это кто?
Остальных — читал.
Но они паттерны стали в реальных задачах прописывать только после книжки банды 4.
Объясняя практическую природу паттернов.
А книжка банды — это диссер Гаммы...
Совершенно академаческий подход.
Или справочник...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Сергей Тепляков книжку написал!
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 29.04.15 04:20
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Паттерны проектирования на платформе .NET

LVV>http://www.ozon.ru/context/detail/id/31789305/
LVV>На Озоне есть оглавление и фрагменты текста.
LVV>Описаны основные паттерны из книги Банды 4 и SOLID.

Этой книги не читал, осуждать не буду, но, единственное нормальное описание паттернов которе я когда либо встречал было в POSA, все остальное какое-то невероятно унылое УГ, включая Банду 4-х. Да, я говорю не про содержание, а про манер изложения.
Re[5]: Сергей Тепляков книжку написал!
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 29.04.15 06:43
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Не. Адресат — важен. Прежде, чем книжку писать — важно определиться с тем, кому книжка предназначена. Вот я четко знал, что пишу для своих студентов.

LVV>Соответственно и строил изложение.
LVV>Здесь книжка как минимум для постюниоров — студенты мало что поймут.

Здесь книга для фанатичных адептов паттернов.

I>>Плохой пример. Нужны реальные проблемы, а не высосаные из пальца. Вот скажем у Джошуа Кериевски, Физерса и того же Кента Бека очень четкий подход, резко отличный от GoF. Посмотри туда для начала.

LVV>Ну, если лог-файлы существуют — значит это кому-нибудь нужно?
LVV>Физерс — это кто?

Майкл Физерс. Legacy Code

LVV>Но они паттерны стали в реальных задачах прописывать только после книжки банды 4.


Вообще говоря GoF не изобретали паттерны. Они всего то структурировали имеющиеся решения.
Re[6]: Сергей Тепляков книжку написал!
От: LaptevVV Россия  
Дата: 29.04.15 11:54
Оценка:
LVV>>Физерс — это кто?
I>Майкл Физерс. Legacy Code
А, понятно. Спасибо.
LVV>>Но они паттерны стали в реальных задачах прописывать только после книжки банды 4.
I>Вообще говоря GoF не изобретали паттерны. Они всего то структурировали имеющиеся решения.
Всякая наука начинается с классификации...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Сергей Тепляков книжку написал!
От: HolyNick  
Дата: 29.04.15 14:59
Оценка:
Ну, что Вы.)
А выучить по десять пунктов за и против (всего, наверно, около 1000 наберется) использования конкретного паттерна. Что может быть интереснее.)) Не можешь(хочешь) думать — развивай память))
Re: Глава 2. Паттерн «Шаблонный метод»
От: Qbit86 Кипр
Дата: 11.05.15 11:30
Оценка: 1 (1)
В главе про Template Method не раскрыта важнейшая тема про NVI (Non-Virtual Interface), прекрасно (на целых две страницы) расписанная в книжке Саттера и Александреску.

Рекомендованная реализация паттерна Dispose Pattern, на мой взгляд, некорректна. Цитата к листингу 2.9: «Автору производного класса будет четко понятно, что можно делать в переопрделенном методе, а что — нет». Вопрос: откуда автору производного класса будет понятно, нужно ли вызывать в переопределённом методе DisposeNativeResources() этот же метод базового класса?

Чтобы избежать подобных вопросов как раз и применяется паттерн Шаблонный Метод, но в примере он почему-то не используется до конца!
Должно быть (имена утрированы):
private /*non-virtual*/ void DisposeNativeResources()
{
    ReleaseBuffer(_buffer);
    DisposeNativeResourcesCore_OverrideIfYouWant();
}

protected virtual /*non-abstract but empty*/ void DisposeNativeResourcesCore_OverrideIfYouWant()
{
    // Этот метод абстрактный, тут не должно быть никакой реализации.
    // Автор производного класса может переопределить этот шаг, а может не переопределять.
    // Он может вызывать этот метод, может не вызывать. Без разницы, метод же пустой.
    // Буффер этого класса в любом случае освободится; ошибка невызова метода базового класса невозможна.
}
Глаза у меня добрые, но рубашка — смирительная!
Re: Глава 4. Паттерн «Итератор»
От: Qbit86 Кипр
Дата: 11.05.15 13:13
Оценка: 1 (1)
Не кажется ли вам, что более естественным интерфейсом C#-like-итератора был бы не такой:
MoveNext(): bool
Current: T

а такой:
GetNext(): Option<T>

?

Теоретически, если игнорировать метод Reset() и интерфейс IDisposable, то в принципе интерфейс итератора вырождается до одного метода, так что интерфейс итерируемого может выглядеть лаконичнее:
GetIterator(): Action<Option<T>>
Глаза у меня добрые, но рубашка — смирительная!
Re: Глава 5. Паттерн «Наблюдатель»
От: Qbit86 Кипр
Дата: 11.05.15 14:32
Оценка: 14 (2)
В мотивации не упомянута ошибка в архитектуре встроенных событий .NET, усложняющая отписку (тем самым косвенно поощряя утечки):
// Подписка:
subject.SomeEvent += (sender, e) => { ... };

// Отписка:
subject.SomeEvent -= ???

вместо правильного
// Подписка:
IDisposable token = subject.SomeEvent += (sender, e) => { ... };

// Отписка:
token.Dispose();


В Rx так и сделано; хотя вот Эрик Мейер недавно написал: «In the original Rx .NET I made the mistake to have `Subscribe` return an `IDisposable` instead of making `IObserver` implement `IDisposable`»
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Глава 2. Паттерн «Шаблонный метод»
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 11.05.15 23:33
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>В главе про Template Method не раскрыта важнейшая тема про NVI (Non-Virtual Interface), прекрасно (на целых две страницы) расписанная в книжке Саттера и Александреску.


У меня в исходном варианте даже врезка такая была. Но я решил ее не включать, поскольку NVI — это достаточно редкий паттерн в .NET-е. Я в живую не разу не видел его активного применения.

Q>Рекомендованная реализация паттерна Dispose Pattern, на мой взгляд, некорректна. Цитата к листингу 2.9: «Автору производного класса будет четко понятно, что можно делать в переопрделенном методе, а что — нет». Вопрос: откуда автору производного класса будет понятно, нужно ли вызывать в переопределённом методе DisposeNativeResources() этот же метод базового класса?


Q>Чтобы избежать подобных вопросов как раз и применяется паттерн Шаблонный Метод, но в примере он почему-то не используется до конца!

Q>Должно быть (имена утрированы):
Q>
Q>private /*non-virtual*/ void DisposeNativeResources()
Q>{
Q>    ReleaseBuffer(_buffer);
Q>    DisposeNativeResourcesCore_OverrideIfYouWant();
Q>}

Q>protected virtual /*non-abstract but empty*/ void DisposeNativeResourcesCore_OverrideIfYouWant()
Q>{
Q>    // Этот метод абстрактный, тут не должно быть никакой реализации.
Q>    // Автор производного класса может переопределить этот шаг, а может не переопределять.
Q>    // Он может вызывать этот метод, может не вызывать. Без разницы, метод же пустой.
Q>    // Буффер этого класса в любом случае освободится; ошибка невызова метода базового класса невозможна.
Q>}
Q>


Конкретная реализация шаблонного метода сильно зависит от конкретного разрабочтика и его понимания, что является "постоянным шагом алгоритма", а что нет. В данном случае, у нас есть несколько постоянных шагов: во-первых, это сам метод Dispose. Он состоит из двух шагов — очистки управляемых и неуправляемых ресурсов. Во-вторых, каждый из этих шагов, может быть разбит еще на несколько подшагов: очистка ресурсов базовым классом и наследниками.

В моем примере, я выделил только шаги первого уровня, оставив шаги второго уровня на усмотрения наследнику. Хорошо это или плохо, сказать сложно, но на практике, я бы правда остановился бы именно на этом, а не стал бы городить огород еще и с выделением еще более мелких шагов. В реальности, переопределение даже этих шагов — это дело достаточно редкое, городить еще один уровень абстракции — ИМХО, оверкил.
Re[2]: Глава 5. Паттерн «Наблюдатель»
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 11.05.15 23:36
Оценка: +1
Здравствуйте, Qbit86, Вы писали:

Q>В мотивации не упомянута ошибка в архитектуре встроенных событий .NET, усложняющая отписку (тем самым косвенно поощряя утечки):

Q>[cs]
Q>// Подписка:
Q>subject.SomeEvent += (sender, e) => { ... };

Спасибо, учту.

Но это не ошибка в архитектуре встроенных событий в .NET. Они проектировались за 5-6 лет до появления анонимных методов, которые оказались несовместимыми с процессом подписки отписки.

Для сценариев, для которых изначально разрабатывались события, отписка от делегата именно с помощью -= является более удобной. Вспомните, винформы. Наличие disposable отписки привело бы к появлению кучи дополнительных полей, управлять которыми было бы не сильно удобно.
Re[3]: Глава 2. Паттерн «Шаблонный метод»
От: Qbit86 Кипр
Дата: 12.05.15 00:11
Оценка: 5 (1) +1
Здравствуйте, SergeyT., Вы писали:

ST>Но я решил ее не включать, поскольку NVI — это достаточно редкий паттерн в .NET-е. Я в живую не разу не видел его активного применения.


На мой взгляд, NVI не столько паттерн, сколько некое «идеальное» применение наследования и полиморфизма в ООП. Сродни правилу не плодить глобальных переменных или не злоупотреблять goto, только ещё не устоявшееся.

ST>В моем примере, я выделил только шаги первого уровня, оставив шаги второго уровня на усмотрения наследнику. Хорошо это или плохо, сказать сложно, но на практике, я бы правда остановился бы именно на этом, а не стал бы городить огород еще и с выделением еще более мелких шагов. В реальности, переопределение даже этих шагов — это дело достаточно редкое, городить еще один уровень абстракции — ИМХО, оверкил.


Тут вопрос не в общей применимости паттерна Шаблонный Метод и насколько исчерпывающими должны быть подшаги. Просто попутно возникла другая, объективная проблема: непонятно, надо ли наследнику звать base.DisposeXxx(); и если вдруг не позовёт, то получим утечку. Она может возникнуть и в других ситуациях. Дизайн, который недопускает определённой потенциальной ошибки со стороны пользователя, лучше дизайна, который допускает. Метод типа DisposeManagedResources() был перегружен задачами: выполнял и роль точки настройки (переопределение в потомках), и интерфейс использования (вызов в потомках). При следовании идиоме NVI нет конфликтующих ролей.

А структура может быть такой же плоской, без лишнего уровня:
#region "Interface for inheritors"

protected virtual void DisposeNativeResourcesCore()
{
    // Intended to be empty.
}

protected virtual void DisposeManagedResourcesCore()
{
    // Intended to be empty.
}

#endregion

#region "Interface for callers"

public /*non-virtual*/ void Dispose()
{
    // Dispose own native resources:
    Release(_buffer);
    ...

    // Dispose inheritors' native resources:
    DisposeNativeResourcesCore();

    // Dispose own managed resources:
    _handle?.Dispose();
    ...

    // Dispose inheritors' managed resources:
    DisposeManagedResourcesCore();

    GC.SuppressFinalize(this);
}

#endregion
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: CompsiteDisposable
От: Qbit86 Кипр
Дата: 12.05.15 00:31
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Наличие disposable отписки привело бы к появлению кучи дополнительных полей, управлять которыми было бы не сильно удобно.


Ну не куча, а одно поле типа CompsiteDisposable. То есть мы подписываемся и сразу же кладём «напоминалку» об отложенной отписке:
    var s = subject.SomeEvent.Subscribe(e => {...});
    _subscriptions.Add(s);
...
public void Dispose()
{
    _subscriptions.Dispose();
}

Отписка не отторжена от подписки; её легче не потерять, если не откладывать на потом, а сразу запланировать.
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: Глава 2. Паттерн «Шаблонный метод»
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 12.05.15 01:37
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, SergeyT., Вы писали:


ST>>Но я решил ее не включать, поскольку NVI — это достаточно редкий паттерн в .NET-е. Я в живую не разу не видел его активного применения.


Q>На мой взгляд, NVI не столько паттерн, сколько некое «идеальное» применение наследования и полиморфизма в ООП. Сродни правилу не плодить глобальных переменных или не злоупотреблять goto, только ещё не устоявшееся.


Можно назвать это патертном, идиомой или идеальным применением наследования и полимфорфизма в ООП. Проблема в том, что это не слишком применимо на практике в .NET.
Когда я писал на С++, то после книги Саттера начал активно применять эту идиому на практике. В .NET-е я практически ее не применяю и не вижу ее применения сообществом.

Q>Тут вопрос не в общей применимости паттерна Шаблонный Метод и насколько исчерпывающими должны быть подшаги. Просто попутно возникла другая, объективная проблема: непонятно, надо ли наследнику звать base.DisposeXxx(); и если вдруг не позовёт, то получим утечку. Она может возникнуть и в других ситуациях. Дизайн, который недопускает определённой потенциальной ошибки со стороны пользователя, лучше дизайна, который допускает. Метод типа DisposeManagedResources() был перегружен задачами: выполнял и роль точки настройки (переопределение в потомках), и интерфейс использования (вызов в потомках). При следовании идиоме NVI нет конфликтующих ролей.


На всякий случай напомню, что в моем коде нет нарушения NVI, поскольку методы DisposeNative/DisposeManaged методы являются защищенными.


Q>А структура может быть такой же плоской, без лишнего уровня:

Q>
Q>#region "Interface for inheritors"

Q>protected virtual void DisposeNativeResourcesCore()
Q>{
Q>    // Intended to be empty.
Q>}

Q>protected virtual void DisposeManagedResourcesCore()
Q>{
Q>    // Intended to be empty.
Q>}

Q>#endregion

Q>#region "Interface for callers"

Q>public /*non-virtual*/ void Dispose()
Q>{
Q>    // Dispose own native resources:
Q>    Release(_buffer);
Q>    ...

Q>    // Dispose inheritors' native resources:
Q>    DisposeNativeResourcesCore();

Q>    // Dispose own managed resources:
Q>    _handle?.Dispose();
Q>    ...

Q>    // Dispose inheritors' managed resources:
Q>    DisposeManagedResourcesCore();

Q>    GC.SuppressFinalize(this);
Q>}

Q>#endregion
Q>


Здесь все сложно С одной стороны, приведенный подход решает проблему "а нужно ли вызывать базовый метод", но решает он лишь на один уровень наследников. Ведь теперь, если у приведенного класса появится два уровня наследования, то мы столкнемся с той же самой проблемой: а нужно ли наследнику второго уровня вызывать DisposeNative/DisposeManaged или нет. Можно конечно, следовать шаблонному методу постоянно и на каждом уровне наследования делать переопределенный метод sealed и добавлять еще пару виртуальных методов DisposenativeResourcesCoreLevel2/DisposeManagedResorucesCoreLevel. Но стоит ли оно того? Я не уверен.

В некоторых случаях, когда у класса десятки наследников, и у каждого из которых есть свой этап освобождения ресурсов, и при этом я знаю, что глубина наследования обычно будет равна 2, то я пойду на выделение предложенных методов. Но в данном случае, слишком много если, чтобы давать это как более или менее стандартное решение.

Есть очень простой способ проверить валидность аргументов тех или иных аргументов.

Вы лично используете предложенный вами подход?

Я даже свой не использую на практике, поскольку на практике смешивания управляемых и управляемых ресурсов не происходит! Я же привел свой вариант, как пример, насколько шаблонный метод позволил бы многим понять намного быстрее разницу между управляемыми и неуправляемыми ресурсами.
Re[3]: Сергей Тепляков книжку написал!
От: мыщъх США http://nezumi-lab.org
Дата: 12.05.15 03:59
Оценка:
Здравствуйте, LaptevVV, Вы писали:

I>>Судя по примеру Стратегия подход ничем принципиально от GoF не отличается. Т.е. компиляция на заезженую тему. С учетом того, что у GoF телега впереди лошади, т.е. постановка проблемы через описание её решения, книга представляет интерес для только для определенного контингента.

LVV>Я уже получил, начал читать.
вы мне порвали шаблон сикель. вы рекомендовали книгу _до_ того как начали ее читать?!
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[4]: Сергей Тепляков книжку написал!
От: LaptevVV Россия  
Дата: 12.05.15 05:18
Оценка:
I>>>Судя по примеру Стратегия подход ничем принципиально от GoF не отличается. Т.е. компиляция на заезженую тему. С учетом того, что у GoF телега впереди лошади, т.е. постановка проблемы через описание её решения, книга представляет интерес для только для определенного контингента.
LVV>>Я уже получил, начал читать.
М>вы мне порвали шаблон сикель. вы рекомендовали книгу _до_ того как начали ее читать?!
На сайте магазина был фрагмент — народ прочитал.
А я не рекомендовал, а сообщил.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: NVI
От: Qbit86 Кипр
Дата: 12.05.15 06:45
Оценка:
Здравствуйте, SergeyT., Вы писали:

Q>>На мой взгляд, NVI не столько паттерн, сколько некое «идеальное» применение наследования и полиморфизма в ООП. Сродни правилу не плодить глобальных переменных или не злоупотреблять goto, только ещё не устоявшееся.

ST>Проблема в том, что это не слишком применимо на практике в .NET. Когда я писал на С++, то после книги Саттера начал активно применять эту идиому на практике.

Так а что такого изменилось в ООП с переходом от C++ к C#, что аргументы Саттера перестали работать? Разве что в кривом и косом C++ была приятная дополнительная фича private virtual (о которой, мне кажется, мало кто знает).

ST>В .NET-е я практически ее не применяю и не вижу ее применения сообществом.


Да я и в C++ не особо-то видел её применение сообществом. Мало ли, о чём там сообщество знает или не знает; это не должно мешать сеять доброе и вечное :)

ST>На всякий случай напомню, что в моем коде нет нарушения NVI, поскольку методы DisposeNative/DisposeManaged методы являются защищенными.


Они мало того, что могут быть вызваны в потомках (без private virtual от этого не уйти). Они ещё и должны быть вызваны в потомках. То есть они являются частью интерфейса вызова, при этом являются виртуальными; это противоречит букве N в NVI.

ST>Здесь все сложно:) С одной стороны, приведенный подход решает проблему "а нужно ли вызывать базовый метод", но решает он лишь на один уровень наследников.


Решить хотя бы на один уровень лучше, чем вообще не решить. Рашать эту проблему для внуков уже на ответственности авторов классов-наследников, и это норма.

ST>Есть очень простой способ проверить валидность аргументов тех или иных аргументов.

ST>Вы лично используете предложенный вами подход?

Да, когда я делаю иерархию классов, всегда начинаю с NVI. Это изначально чуть больше кода в базовом классе (полиморфные функции расслоены на callable и overridable ипостаси), но всегда окупается; проще в наследниках, и можно добавлять непереопределяемые и неотторжимые шаги в методы-оболочки базового класса. Например, в базовом классе в невиртуальных методах может происходить проверка аргументов на границе API «if (argument == null) ...», а в наследниках в переопределённых «виртуальных ядрах» валидность аргументов энфорсится «Debug.Assert(argument != null)».
Глаза у меня добрые, но рубашка — смирительная!
Re: Глава 6. Паттерн «Посетитель»
От: Qbit86 Кипр
Дата: 12.05.15 07:17
Оценка: +2
Я эту главу ещё не читал, но уже готов осуждать! Посетитель мой горячо любимый паттерн (хотя не помню, когда его использовал, и вообще скрипач не нужен), но никто не может его внятно описать.

Никто!
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: Хорошая книжка
От: Qbit86 Кипр
Дата: 12.05.15 07:23
Оценка:
Здравствуйте, мыщъх, Вы писали:

М>вы мне порвали шаблон сикель. вы рекомендовали книгу _до_ того как начали ее читать?!


Не понял, при чём тут сикель, но я уже начал читать. Щетаю, надабрать.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Сергей Тепляков книжку написал!
От: elmal  
Дата: 12.05.15 07:42
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Тема паттернов уже заезжена, что дальше ехать некуда...

Ээээ. Есть ли хоть одна книжка по best практикам применения и неприменения паттернов? А то я никогда в жизни ни один паттерн не применял в том виде, в каком они описаны в книжках. Всегда это либо комбинация паттернов. Например не синглтон, как он описан, а синглтон в зависимости от параметров. Разные параметры, разная конфигурация — разные инстансы. Одинаковые конфигурации — одинаковые индексы. Фабрика тоже, когда она мне была нужна, она была нужна вместе с инициализацией объектов, для инициализации приходилось всякие реестры делать, когда объекты при создании регистрируют себя в реестре, и соответственно фабрика в момент создания конкретного объекта учитывает соответствующую информацию. Визитор я никогда в жизни в коде не называл визитором. И по смыслу это просто всегда была лямбда.
Re[5]: Хорошая книжка
От: мыщъх США http://nezumi-lab.org
Дата: 12.05.15 08:17
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, мыщъх, Вы писали:


М>>вы мне порвали шаблон сикель. вы рекомендовали книгу _до_ того как начали ее читать?!


Q>Не понял, при чём тут сикель, но я уже начал читать. Щетаю, надабрать.

Сикль (евр. рас. שקל) — древнееврейская мера драг. металлов
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.