Здравствуйте, Sinclair, Вы писали:
S>Вот это меня опять настораживает. Я имею в виду — ввод паттернов на ровном месте.
Даже не знаю что ответить. Чем вас паттерны настораживают?
S>Ух ты ж блин! Сколько всего. И всё это вместо пары классов Path и Canvas. S>Круто, чё.
Вы всю логику хотите в 2 класса поместить? Видал я классы по 5000 строк, но уверяю что это неверный путь.
D>>К сожалению, я сталкивался с ситуациями, когда попытки построить иерархию на основе поведения приводили к разрастанию иерархии до безумных размеров с совершенно головоломной логикой наследования. S>Вынужден поверить вам на слово, хотя сам такого не видел.
Логически подумайте. Чем больше разнообразных задач вы навесите на иерархию, тем больше в ней будет нестыковок, костылей и компромиссов.
Идеально разнести задачи по разным классам или иерархиям. В этом случае понимание кода сильно упрощается.
S>А какой код и сколько нам потребуется в ShapeDrawer? Я же правильно понял, что в нём будет по методу на каждого потомка Shape?
Верно. Всё, что связано с рисованием будет в нём.
S>Простите, но такой код хорош только для списания затрат по time spent basis. S>Для реальной работы надо минимизировать усилия. В вашем коде стоимость добавления новой фигуры — запредельна.
Добавление одного метода из 10 строк для вас запредельная сложность?
Здравствуйте, Dufrenite, Вы писали: D>Даже не знаю что ответить. Чем вас паттерны настораживают?
Тем же самым — паттерн должен вводиться не как самоцель, а как решение какой-то задачи. Причём так, что "без паттерна" решение получается хуже по объективным характеристикам.
D>Вы всю логику хотите в 2 класса поместить? Видал я классы по 5000 строк, но уверяю что это неверный путь.
В данном случае двух классов вполне достаточно. В вашем решении банально больше строк — то есть больше объём работы по тестированию, больше шансов сделать ошиююку.
D>Логически подумайте. Чем больше разнообразных задач вы навесите на иерархию, тем больше в ней будет нестыковок, костылей и компромиссов.
Не вижу никакой логики, равно как и причин, по которым вы предлагаете мне навесить на единую иерархию множество разнообразных задач.
Проектирование от поведения совершенно не об этом.
D>Идеально разнести задачи по разным классам или иерархиям. В этом случае понимание кода сильно упрощается.
S>>А какой код и сколько нам потребуется в ShapeDrawer? Я же правильно понял, что в нём будет по методу на каждого потомка Shape?
D>Верно. Всё, что связано с рисованием будет в нём.
S>>Простите, но такой код хорош только для списания затрат по time spent basis. S>>Для реальной работы надо минимизировать усилия. В вашем коде стоимость добавления новой фигуры — запредельна. D>Добавление одного метода из 10 строк для вас запредельная сложность?
С чего это "одного"? В вашем решении мне нужно:
1. Добавить новый класс фигуры. Сколько в нём будет строк кода?
2. Добавить новый метод в IShapeVisitor
3. Добавить новый метод в каждую реализацию IShapeVisitor. В вашем примере их две.
В моём решении единственное, что потребуется добавить во весь проект — это как раз один метод.
Примерно вот так:
public static Path CreateRightAngleTriangle(Pen pen, Point corner, int height, int width)
{
return Path.CreateClosedPath(pen, corner, corner + new Offset(0, -height), corner + new Offset(width, 0));
}
Всё. А теперь приведите мне тот код, который потребуется написать в вашем проекте, чтобы заработали прямоугольные треугольники.
Если я попрошу вас научить вашу программу поворачивать Shape на произвольный угол, то вы мгновенно утонете в коде. А у меня добавится ровно один метод Path RotatePath(Path original, double angle). Никакого полиморфизма, никакого размазывания изменений по всем файлам проекта, минимум риска сделать ошибку.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Тем же самым — паттерн должен вводиться не как самоцель, а как решение какой-то задачи. Причём так, что "без паттерна" решение получается хуже по объективным характеристикам.
В данном случае паттерны сильно упрощают жизнь.
S>Не вижу никакой логики, равно как и причин, по которым вы предлагаете мне навесить на единую иерархию множество разнообразных задач. S>Проектирование от поведения совершенно не об этом.
Ну вы же не думаете, что развитие вашей программы ограничится простым отображением фигур на экране?
S>С чего это "одного"? В вашем решении мне нужно: S>1. Добавить новый класс фигуры. Сколько в нём будет строк кода? S>2. Добавить новый метод в IShapeVisitor S>3. Добавить новый метод в каждую реализацию IShapeVisitor. В вашем примере их две.
Вам в любом случае придётся как-то эту функциональность реализовать.
S>В моём решении единственное, что потребуется добавить во весь проект — это как раз один метод. S>Примерно вот так: S>
S>public static Path CreateRightAngleTriangle(Pen pen, Point corner, int height, int width)
S>{
S> return Path.CreateClosedPath(pen, corner, corner + new Offset(0, -height), corner + new Offset(width, 0));
S>}
S>
S>Всё. А теперь приведите мне тот код, который потребуется написать в вашем проекте, чтобы заработали прямоугольные треугольники. S>Если я попрошу вас научить вашу программу поворачивать Shape на произвольный угол, то вы мгновенно утонете в коде. А у меня добавится ровно один метод Path RotatePath(Path original, double angle). Никакого полиморфизма, никакого размазывания изменений по всем файлам проекта, минимум риска сделать ошибку.
Вы ошибаетесь. Я добавлю в класс Shape матрицу трансформации. Соответственно в методе DrawLines появляется ещё один параметр.
А теперь я вас попрошу внести в ваше решение маленькое изменение: пусть квадрат заливается текстурой, которую я назначил. А ещё я хочу, чтобы вокруг треугольника отображалось гало. А ещё хочу экспорт 3D моделей из 3D Studio Max. И ещё чтобы можно было крутить в трёх измерениях. И экспортировать в популярные форматы, включая PDF.
Здравствуйте, Dufrenite, Вы писали:
D>Вам в любом случае придётся как-то эту функциональность реализовать.
Функциональность — да. А вот весь код ради кода (т.е. визиторы, override, и прочий мусор) — нет, не придётся.
D>Вы ошибаетесь. Я добавлю в класс Shape матрицу трансформации. Соответственно в методе DrawLines появляется ещё один параметр.
Матрицу-то вы добавите. А как вы предполагаете её использовать и где? Пример кода — в студию.
Мой — вот он:
public static Path RotatePath(Path original, double angle)
{
var m = TransformMatrix.CreateRotationMatrix(angle);
var rotatatedSegments = from s in original.Segments select m.Transform(s);
return new Path(rotatedSegments);
}
подразумеваем, естественно, что мы написали хелпер-метод
public static PathSegment Transform(this TransformMatrix m, PathSegment segment)
{
var s = segment.Clone();
s.Point1 = m.Transform(s.Point1);
s.Point2 = m.Transform(s.Point2);
return s;
}
D>А теперь я вас попрошу внести в ваше решение маленькое изменение: пусть квадрат заливается текстурой, которую я назначил.
Без проблем. Мы просто добавим в наш единственный метод DrawPath(Path path) опциональный параметр Brush fill.
И забесплатно получим возможность заливать текстурами не только квадраты, а и треугольники, и прямоугольники, и все будущие фигуры.
D>А ещё я хочу, чтобы вокруг треугольника отображалось гало.
Подход — такой же. Придумываем параметры гало (скорее всего цвет, насыщенность, и поперечник), и добавляем метод, который их использует.
D>А ещё хочу экспорт 3D моделей из 3D Studio Max. И ещё чтобы можно было крутить в трёх измерениях.
Ну, для начала придётся перейти от Path к 3dSurface. Затем принять решение, что из данных 3DS нам будет интересно — там, вообще-то, дохрена всего. С учётом того, что это — параметрический 3d-аниматор, а не просто "рисовалка 3d моделей".
А уже затем мы напишем совершенно отдельный от всего код лоадера 3DS, который будет читать файлы и отдавать те объекты, которые нам интересны.
D>И экспортировать в популярные форматы, включая PDF.
Ну, экспорт в PDF нам будет доступен забесплатно, потому что есть готовые экспортилки, которые реализуют тот же самый Canvas (он же DeviceContext), который мы использовали в нашем методе DrawPath.
D>Дальше продолжать?
Да сколько угодно. Я только по-прежнему не понимаю, как тут поможет ваша иерархия Shape и иерархия Visitor.
Во всех этих задачах она будет только путаться под ногами. И будет существенно усложнять процесс добавления нового Shape в проект.
Если вы собираетесь мне возразить, то будьте любезны привести пример кода.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.