Здравствуйте, olegkr, Вы писали:
ГВ>>Ну вот видишь, а я это не считаю даже изменениями, не говоря об их критичности.
O>Зря не считаешь. Тот же переход на ООП породил интересную проблему — программисты, давно работающие испытывали сложности с переходом. Для них не было проблемы перейти с фортрана на C, решать сложнейшие задачи, но новая объектно-ориентированная концепция просто не вписывалась в их понимание. Это была самая настоящая ломка. Частенько недавние бывшие студенты легче воспринимали ООП, чем ветераны. Это я заметил даже в России на опыте коллег, хотя у нас это было малоактуально.
Я был свидетелем этих трудностей. Сам "пропихивал" ООП где надо и не надо. Правда, большой вопрос, стоило ли это делать так рьяно, но уж что было, то было. Сейчас я, правда, уверен, что "ломки" отечественных программистов связаны были не столько с распространением ООП, сколько с разрушением СССР и сопутствующей потерей много чего. ИМХО, это был самый тяжёлый фактор.
O>Но настоящая проблема была на западе, судя по прочитанными мною статьям.
Ничего удивительного на самом деле. Новый подход к формулировке решений породил вполне естественную волну ошибок, завышенных ожиданий, разочарований и ещё много чего. Та же история повторилась с 4GL, Java, COM, Web, вебсервисами...
O>Если ты не считаешь изменение всего мировоззрения даже изменением, то я не знаю, что ты таковым считаешь. Приведи пример, пожалуйста.
Пожалуй, на сегодняшний день это появление многопроцессорных настольных компьютеров.
ГВ>>Хм. То, о чём я упомянул, применялось в самом обычном бизнес-софте: склады, бухгалтерии, биллинги, какая-то ещё хрень того же порядка. Это узкая специализация?
O>У меня знакомый работает со складом и бухгалтерией. Чего-то в 1С ничего подобного он не пишет. Я писал биллинг, не очень большой, на полмиллиона абонентов. И скажу я тебе, что самая большая Ж у нас была с самописным языком по разбору логов [...].
Я тоже могу привести примеры неудачных решений. Ты спрашивал о моей специализации, я ответил.
ГВ>>Для того, чтобы не зубрить "паттерны" и массу странных слов, хотя бы. Сильно экономит время и нервы.
O>Было бы интересно посмотреть пример. Вот возьмем, банальный, всем известный паттерн Abstract Factory. Как его из LSP вывести?
Очень просто. Берём операцию "создать объект по параметру selector и работать с его интерфейсом SomeClass" и последовательно устраняем упоминания реализующих типов.
public void someMethod() {
SomeClass obj; // = NULL, тут объекта ещё нет
[** ... что-то делаем в зависимости от параметра SomeSelector() ...]
obj.method(); // А вот тут obj уже не NULL
}
Исходно [**] выглядит, например, так:
switch(SomeSelector())
{
case 1: obj = new SomeClass1;
case 2: obj = new SomeClass2;
}
Плохо, что упоминаются классы реализации. Сворачиваем, убирая упоминания SomeClass1, SomeClass2 в отдельный класс:
class Factory {
public SomeClass createInstance(selector);
};
Теперь [**] выглядят так (Это — паттерн Factory):
Factory f = new Factory;
obj = f.createInstance(SomeSelector());
Лучше, на этом можно бы и остановиться. Но похоже, что нам придётся добавлять ещё какие-то классы вместо SomeClass1 и SomeClass2. И очень сильно похоже, что для этого придётся сделать ещё одну фабрику. Так что, теперь хорошо бы исключить ещё и упоминание о типе самой фабрики. Модернизируем решение в соответствии с LSP:
interface Factory {
SomeClass createInstance(selector);
};
Теперь интерфейс Factory приезжает откуда-то извне, возможно, что это некий глобальный синглтон или, скажем, он передан параметром при создании экземпляра текущего класса. Как бы то ни было, но [**] сейчас выглядит так:
obj = factory.createInstance(SomeSelector());
Для определённости полагаем, что интерфейс Factory приезжает через параметр someMethod:
public void someMethod(Factory factory) { ... }
Тогда код в итоге упрощается до:
public void someMethod(Factory factory) {
SomeClass obj = factory.createInstance(SomeSelector());
obj.method();
}
Сам экземпляр фабрики порождается где-то очень сильно в стороне.
Итак, по ходу дела получились "паттерны" Factory и Abstract Factory. Произошло это вследствие последовательного вытеснения упоминаний типов уровня реализации из использующего кода. В строгом соответствии с LSP.
Вернее сказать, LSP тут используется для проверки того, что использующий код не зависит от реализаций.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!