После статьи «ООП не мертво. Вы просто пользуетесь им как молотком по клавиатуре» комментарии кипели
Кто-то звал Smalltalk, кто-то бросал в нас Haskell, кто-то доставал из-под кровати подшивку статей «ECS лучше всего» — и всё это с праведной уверенностью.
Что ж…
Пора прекратить спор на словах. И начать спор в коде.
Code-Battle: MVP графического редактора
Задача: реализовать базовый графический редактор
Фигуры: точка, линия, круг, квадрат, прямоугольник, треугольник, ромб, овал
Функциональность: добавление фигур на канвас, отрисовка
Правила:
Один .cpp / .py / .exs / .c / .rs / .lisp / whatever файл
Язык и подход — любой
Главное: читаемость, понятность, архитектурная целостность
Пишите максимально просто, если надо - используйте псевдокод
MVP сейчас — фичи потом
Все решения оформляются одним Merge Request
В конце — разбор решений, сравнение подходов, и, как обычно: наказание невиновных и награждение непричастны
Для затравки: C++ / ООП реализация (v1)
В качестве точки отсчёта — наш базовый вариант.
ООП, без усложнений.
Всё в одном файле.
#include <iostream>
#include <string>
#include <vector>
class Shape {
public:
virtual void draw() const = 0;
virtual std::string name() const = 0;
virtual ~Shape() {}
};
class Point : public Shape {
int x, y;
public:
Point(int x, int y) : x(x), y(y) {}
void draw() const override {
std::cout << «Drawing Point at (« << x << «, « << y << «)\\n»;
}
std::string name() const override { return «Point»; }
};
class Circle : public Shape {
int x, y, r;
public:
Circle(int x, int y, int r) : x(x), y(y), r(r) {}
void draw() const override {
std::cout << «Drawing Circle at (« << x << «, « << y << «), r = « << r << «\\n»;
}
std::string name() const override { return «Circle»; }
};
class Rectangle : public Shape {
int x, y, w, h;
public:
Rectangle(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {}
void draw() const override {
std::cout << «Drawing Rectangle at (« << x << «, « << y
<< «), « << w << «x» << h << «\\n»;
}
std::string name() const override { return «Rectangle»; }
};
class Canvas {
std::vector<Shape*> shapes;
public:
void add(Shape* s) { shapes.push_back(s); }
void render() const {
for (auto s : shapes) s->draw();
}
~Canvas() {
for (auto s : shapes) delete s;
}
};
int main() {
Canvas canvas;
canvas.add(new Point(1, 1));
canvas.add(new Circle(5, 5, 3));
canvas.add(new Rectangle(0, 0, 6, 3));
canvas.render();
return 0;
}
Теперь — вы.
Реализуйте то же самое:
На любом языке и в любой парадигме
В своей манере — функциональной, процедурной, декларативной, минималистской
Без фреймворков. Без магии. Только архитектура
Это только начало.
Следующая итерация уже в пути. Требования изменятся. Канвас расширится. Архитектура проявит себя.
А мы, разберём каждую реализацию — и, возможно, найдём ответ на вопрос:
«To OOP or not to OOP — вот в чем загвоздка”.