Здравствуйте, George Seryakov, Вы писали:
GS>Здравствуйте, Hacker_Delphi, Вы писали:
LVV>>>Ты лучше скажи что за книжка и где ее взять. H_D>>Павел Шумилов (Павел Шумил) "Пойди поймай свою звезду".
GS>Виндж (рекомендую) тоже по программситам-археологам проходится.
Здравствуйте, Hacker_Delphi, Вы писали:
H_D>Вот отрывок из книши одного очень хорошего писателя: H_D>
H_D> - Долгая история. Все дело в том, что местные программисты пошли
H_D>по неверному пути. Этот путь называется объектно ориентированный подход
H_D>в программировании. На самом деле это мина с часовым механизмом в
H_D>красивой упаковке. В очень красивой упаковке. Как с этим бороться, я
H_D>не знаю. Упустил момент.
H_D> - Мастер, ближе к делу.
H_D> - Знаешь анекдот, как программист кипятит чайник. Дано: пустой
H_D>чайник, кран, спички, газовая плита. Программа действий: наполнить
H_D>чайник водой из-под крана, поставить на плиту, зажечь газ. Ждать, пока
H_D>закипит чайник. Эта программа оформляется как объект. Второй случай.
H_D>Все то же самое, но чайник с водой уже стоит на плите. Действия
H_D>программиста: вылить воду из чайника и выполнить предыдущий объект.
H_D> - Грустно. А нырнуть внутрь объекта нельзя? Туда, где надо газ
H_D>зажечь?
H_D> - Нельзя. Можно добавить новое свойство или действие. В нашем случае
H_D>- воду вылить. Будет новый объект. Но внутрь влезть нельзя. Объект дается
H_D>как единое целое. Никто не знает, что там внутри. Все давно забыли, откуда
H_D>ноги растут. В результате получается колоссальное дублирование кода и данных
H_D>и огромная потеря производительности компьютера. С каждым годом компьютеры
H_D>требуют все больше памяти, а работают все медленнее.
H_D>
Налицо неумелое проектирование. _Чайник_ должен быть представлен как отдельный объект, _Вода_ также как отдельный объект. _Чайник_с_водой_ представляет собой объект, отнаследованный от объектов _Чайник_ и _Вода_. Соответственно, имеем:
функция _Главная_
{
_Чайник_ экземпляр как _Чайник_с_водой_
_Устройство_для_кипячения_::_Кипятить_(экземпляр)
}
_Устройство_для_кипячения
{
функция _Кипятить_(_Чайник_ экземпляр)
{
если (экземпляр есть _Чайник_с_водой_)
кипятить
другое
пошел взад
}
}
Во втором случае просто сокращаем функцию _Главная_ на одну строчку.
Здравствуйте, Hacker_Delphi, Вы писали:
H_D>Вот отрывок из книши одного очень хорошего писателя: H_D>
H_D> - Долгая история. Все дело в том, что местные программисты пошли
H_D>по неверному пути. Этот путь называется объектно ориентированный подход
H_D>в программировании. На самом деле это мина с часовым механизмом в
H_D>красивой упаковке. В очень красивой упаковке. Как с этим бороться, я
H_D>не знаю. Упустил момент.
H_D> - Мастер, ближе к делу.
H_D> - Знаешь анекдот, как программист кипятит чайник. Дано: пустой
H_D>чайник, кран, спички, газовая плита. Программа действий: наполнить
H_D>чайник водой из-под крана, поставить на плиту, зажечь газ. Ждать, пока
H_D>закипит чайник. Эта программа оформляется как объект. Второй случай.
H_D>Все то же самое, но чайник с водой уже стоит на плите. Действия
H_D>программиста: вылить воду из чайника и выполнить предыдущий объект.
H_D> - Грустно. А нырнуть внутрь объекта нельзя? Туда, где надо газ
H_D>зажечь?
H_D> - Нельзя. Можно добавить новое свойство или действие. В нашем случае
H_D>- воду вылить. Будет новый объект. Но внутрь влезть нельзя. Объект дается
H_D>как единое целое. Никто не знает, что там внутри. Все давно забыли, откуда
H_D>ноги растут. В результате получается колоссальное дублирование кода и данных
H_D>и огромная потеря производительности компьютера. С каждым годом компьютеры
H_D>требуют все больше памяти, а работают все медленнее.
H_D>
H_D>Которая лишь подтверждает мысль, что ООП везде — это вред и блед, хотя и не отрицает что в бизнес приложениях ООП — это просто круто
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Налицо неумелое проектирование. _Чайник_ должен быть представлен как отдельный объект, _Вода_ также как отдельный объект. _Чайник_с_водой_ представляет собой объект, отнаследованный от объектов _Чайник_ и _Вода_.
С чего это отнаследованный? Самая типичная агрегация.
public abstract class Content
{
public vitual double Weight
{get;}
public vitual double Volume
{get;}
}
public abstract class LiquidContent : Content
{
public vitual double BoilTemperature
{get;}
public bool IsBoiled
{
get
{
return _temperature >= DoilTemperature;
}
}
}
public class WaterContent
{
public WaterContent(double count) {...}
public override double BoilTemperature
{
get { return 100f; }
}
}
public interface IContentProvider
{
Content GetContent(double count);
}
public class Tap : IContentProvider
{
WaterContent GetWater(double count)
{
try
{
_waterPipe.QueryWater(count);
catch (WaterAbortedBySomebodyException)
{
throw new NoWaterInTapException("Воду выпили жиды");
}
}
Content IContentProvider.GetContent(double count)
{
return GetWater(count);
}
}
public interface IContentContainer
{
double ContentRoom
{get;}
void PutContent(LiquidContent content);
}
public class Teapot : IContentContainer
{
public double ContentRoom {...}
public void PutContent(LiquidContent content)
{
if (content.Volume > (ContentRoom - _alreadyContained))
throw new OverflowException();
_alreadyContained += content.Volume;
}
}
public interface IFireable
{
bool IsFired
{get;}
void Fire(FireSource source);
}
public abstract class FireSourceProvider
{
public abstract FireSource CreateFireSource();
}
public abstract class FireSource : IFireable
{
protected abstract IsFired
{get;}
public abstract void Fire(FireSource source);
public bool DoFire(IFireable what)
{
while (!what.IsFired)
{
what.Fire(this);
if (IsFired)
return false;
}
return true;
}
}
public class Match : FireSource
{
public override bool IsFired
{
get { return _isFired; }
}
public override void Fire() {...}
}
public class MatchBox : FireSourceProvider
{
public override FireSource CreateFireSource()
{
if (_matchCount = 0)
throw new NotEnoughMatchesException();
_matchCount--;
return new Match();
}
}
public class Stove : IFireable
{
public bool IsFired
{
get { return _isFired; }
}
public void Fire()
{
...
_isFired = true;
}
public void PutOn(object what)
{
...
}
}
А теперь собственно требуемый код:
const double overflowPreventVolume = 0.05f;
Teapot teapot = Home.Instance.Kitchen.PlatesAndDishesShelf.Extract("Teapot #1");
double requiredContentCount = teapot.ContentRoom - teapot.Content.Volume - overflowPreventVolume;
if (requiredContentCount > 0)
teapot.PutContent(Home.Instance.Kitchen.Tap.GetContent(requiredContentCount));
MatchBox matchBox = Home.Instance.Kitchen.SmallShelf.Extract("MatchBox");
Stove stove = Home.Instance.Kitchen.Stove;
while (!stove.IsFired)
{
int atemptCount = 0;
const totalAtempts = 10;
FireSource match = matchBox.CreateFireSource();
while (!match.IsFired)
{
match.Fire(null);
atemtpCount++;
if (atemptCount > totalAtempts)
throw new ArgumentException("Черт побери, какого фига спички мокрые!");
}
match.DoFire(stove);
}
stove.PutOn(teapot);
const int checkInterval = 30000;
while (!teapot.Content.IsBoiled)
System.Threading.Sleep(checkInterval);
Так что нефиг свою криворукость списывать на недостатки ООП.
Это пример криво спроектированного чайника, который инкапсулирован с газовой плитой и водопроводным краном . Поддерживает сия штука лишь методы "ВылитьВоду", "НалитьВодуПоставитьНаПлитуВключитьГаз". Брр....
Такие "мины с часовым механизмом" закладываются не технологией, а архитектором.
Здравствуйте, _Obelisk_, Вы писали:
_O_>Здравствуйте, Hacker_Delphi, Вы писали:
_O_>Это пример криво спроектированного чайника, который инкапсулирован с газовой плитой и водопроводным краном . Поддерживает сия штука лишь методы "ВылитьВоду", "НалитьВодуПоставитьНаПлитуВключитьГаз". Брр.... _O_>Такие "мины с часовым механизмом" закладываются не технологией, а архитектором.
Ну почему надо цепляться за конкретный пример и говорить, что пример неправильный, поэтому автор не прав?
Понятно, что приведенный пример высосан из пальца. Но проблема выделена по моему достаточно ясно : Невозможность(трудоемкость или неудоно) изменить логику работы обьекта, когда он уже спроектирован и написан. И это проблемы ООП, а не архитектора. Архитекор в рамках ООП ДЛЯ ДАННОЙ ЗАДАЧИ может ъхорошо спроектировать обьект. Когда задача измениться, часто приходится делать новый класс обьектов.
Здравствуйте, Hacker_Delphi, Вы писали:
H_D>Которая лишь подтверждает мысль, что ООП везде — это вред и блед, хотя и не отрицает что в бизнес приложениях ООП — это просто круто
Не-ет, сякундочку...
Ничего я в этом отрывке подтверждающего не нашёл, одни словоизвороты. Никак смысла не пойму, может объяснит кто?
Там две задачи приведены. Посмотрим на первую задачу. Цитировать её не буду. Сразу напишу
type
Чайник = class()
private
procedure НалитьВоды();
procedure ПоставитьНаПлиту()
procedure ЗажечьГаз();
function ЖдатьКогдаЗакипит(): Boolean;
public
procedure Кипятить();
end;
procedure Чайник.Кипятить();
begin
НалитьВоды();
ПоставитьНаПлиту()
ЗажечьГаз();
repeat
until ЖдатьКогдаЗакипит();
end;
В начале нигде не сказано, что условия задачи могут меняться. А потом их взяли, да изменили. И пытаются показать, что раз мы не можем плюхнуться в середину метода Кипятить(), значит это глупо. А менять постановку задачи, значит, правильно, потому как из жизни.
Никто же не мешает модифицировать класс Чайник. Например, сделать метод Кипятить() виртуальным, и заменить его в потомке. А приватные методы сделать protected, раз уж нужно управляемое поведение.
Никто не мешает завести состояние класса чайник. "Вода есть?". "На плите?" "Газ зажжён?" Ждём, когда закипит?" "Чайник закипел?"
В чём фишка-то? В игре слов? Или в проектировании?
[skip] A>Там две задачи приведены. Посмотрим на первую задачу. Цитировать её не буду. Сразу напишу
[skip]
A>В начале нигде не сказано, что условия задачи могут меняться. А потом их взяли, да изменили. И пытаются показать, что раз мы не можем плюхнуться в середину метода Кипятить(), значит это глупо. А менять постановку задачи, значит, правильно, потому как из жизни.
В точку A>Никто же не мешает модифицировать класс Чайник. Например, сделать метод Кипятить() виртуальным, и заменить его в потомке. А приватные методы сделать protected, раз уж нужно управляемое поведение.
Нет нельзя.. представь, что вместо чайника — объект ядра ОС... (там-то про то, что ОСы ОО стали).
A>Никто не мешает завести состояние класса чайник. "Вода есть?". "На плите?" "Газ зажжён?" Ждём, когда закипит?" "Чайник закипел?"
Только в наследниках... т.е. велосипед
по идее — нужно наоборот делать
... << RSDN@Home 1.1.2 beta 2 >>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Здравствуйте, Ведмедь, Вы писали:
В>Понятно, что приведенный пример высосан из пальца. Но проблема выделена по моему достаточно ясно : Невозможность(трудоемкость или неудоно) изменить логику работы обьекта, когда он уже спроектирован и написан. И это проблемы ООП, а не архитектора. Архитекор в рамках ООП ДЛЯ ДАННОЙ ЗАДАЧИ может ъхорошо спроектировать обьект. Когда задача измениться, часто приходится делать новый класс обьектов.
Здравствуйте, akasoft, Вы писали:
A>Здравствуйте, Hacker_Delphi, Вы писали:
H_D>>Которая лишь подтверждает мысль, что ООП везде — это вред и блед, хотя и не отрицает что в бизнес приложениях ООП — это просто круто
A>
A>type
A> Чайник = class()
A> private
A> procedure НалитьВоды();
A> procedure ПоставитьНаПлиту()
A> procedure ЗажечьГаз();
A> function ЖдатьКогдаЗакипит(): Boolean;
A> public
A> procedure Кипятить();
A> end;
A>procedure Чайник.Кипятить();
A>begin
A> НалитьВоды();
A> ПоставитьНаПлиту()
A> ЗажечьГаз();
A> repeat
A> until ЖдатьКогдаЗакипит();
A>end;
A>
Вот только что хотел написать то же самое. На самом деле, грамотно спроектированная ОО модель может иметь очень низкие накладные расходы, связанные с поддержанием модели как таковой, а не функциональности приложения. В данном случае надо говорить не о том, что мы теряем при использовании оо подхода, а том, что в итоге приобретается. А приобретается при правильном подходе гораздо больше, чем теряется. Пример с чайником является образцом НЕПРАВИЛЬНОГО моделирования сущностей реального мира с использованием объектов.
Здравствуйте, _Obelisk_, Вы писали:
_O_>Здравствуйте, Ведмедь, Вы писали:
В>>Понятно, что приведенный пример высосан из пальца. Но проблема выделена по моему достаточно ясно : Невозможность(трудоемкость или неудоно) изменить логику работы обьекта, когда он уже спроектирован и написан. И это проблемы ООП, а не архитектора. Архитекор в рамках ООП ДЛЯ ДАННОЙ ЗАДАЧИ может ъхорошо спроектировать обьект. Когда задача измениться, часто приходится делать новый класс обьектов.
_O_>Есть ли подход, который решает эту проблему ?
однозначно? — нет... про что и речь — не нужно делать ОО ОС...
... << RSDN@Home 1.1.2 beta 2 >>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Здравствуйте, _Obelisk_, Вы писали:
_O_>Здравствуйте, Ведмедь, Вы писали:
В>>Понятно, что приведенный пример высосан из пальца. Но проблема выделена по моему достаточно ясно : Невозможность(трудоемкость или неудоно) изменить логику работы обьекта, когда он уже спроектирован и написан. И это проблемы ООП, а не архитектора. Архитекор в рамках ООП ДЛЯ ДАННОЙ ЗАДАЧИ может ъхорошо спроектировать обьект. Когда задача измениться, часто приходится делать новый класс обьектов.
Здравствуйте, _Obelisk_, Вы писали: _O_>Есть ли подход, который решает эту проблему ?
Да. Это рефакторинг, т.е. набор преобразований объектной модели, сохраняющих семантику. Это когда мы режем статический метод вскипятить на три виртуальных и получаем ту же функциональность, но в более гибкой модели.
... << RSDN@Home 1.1.0 stable >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, _Obelisk_, Вы писали: _O_>>Есть ли подход, который решает эту проблему ? S>Да. Это рефакторинг, т.е. набор преобразований объектной модели, сохраняющих семантику. Это когда мы режем статический метод вскипятить на три виртуальных и получаем ту же функциональность, но в более гибкой модели.
Это не то, ведь мы же перелопачиваем весь код в данном случае, т.е. лезем внутрь всего.
Здравствуйте, _Obelisk_, Вы писали: _O_>Это не то, ведь мы же перелопачиваем весь код в данном случае, т.е. лезем внутрь всего.
Да. Оставаясь в рамках модели, мы не сможем достичь некоторых целей. Что и показано чуть выше по топику. Так что это — именно то. В отличие от разработки модели с нуля, такой рефакторинг позволяет гарантировать функциональность без дополнительной отладки.
... << RSDN@Home 1.1.0 stable >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, _Obelisk_, Вы писали: _O_>>Это не то, ведь мы же перелопачиваем весь код в данном случае, т.е. лезем внутрь всего. S>Да. Оставаясь в рамках модели, мы не сможем достичь некоторых целей. Что и показано чуть выше по топику. Так что это — именно то. В отличие от разработки модели с нуля, такой рефакторинг позволяет гарантировать функциональность без дополнительной отладки.
Рефакторинг не страхует от кривых рук производещего этот самый рефакторинг. От отладки никуда не деться.
Здравствуйте, _Obelisk_, Вы писали:
_O_>Рефакторинг не страхует от кривых рук производещего этот самый рефакторинг. От отладки никуда не деться.
Это от того, что он не поддержиается средой. Я говорю именно о "математическом рефакторинге". Можно было лепить и объектные модели на С, вот только от кривых рук разработчика не было страховки, и в VMT могло оказаться все что угодно. Я прозрачно намекаю?
... << RSDN@Home 1.1.0 stable >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.