Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   ООП. Нужен совет. (https://javascript.ru/forum/misc/85843-oop-nuzhen-sovet.html)

firep91613 11.04.2024 17:59

ООП. Нужен совет.
 
Делаю рисовалку на SVG. Сейчас у меня в файле класса рисовалки почти 300 строк кода. Я уже путаюсь что и где. Решил сделать отдельные классы для каждого элемента. Думаю, еще классы раскидать по разным файлам. До этого эти классы были методами класса рисовалки.

Пример:
class Circle {
  constructor(x, y, r = 20, c = '#7F6565') {
    this.x = x;
    this.y = y;
    this.radius = r;
    this.color = c;
  }

  create() {
    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    circle.setAttribute('r', this.radius);
    circle.setAttribute('cx', this.x);
    circle.setAttribute('cy', this.y);
    circle.setAttribute('fill', this.color);
    circle.setAttribute('stroke-width', 1);
    return circle;
  }
}

class Line {
  constructor(x1, y1, x2, y2, c = 'black') {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.color = c;
  }

  create() {
    const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    line.setAttribute('x1', this.x1);
    line.setAttribute('y1', this.y1);
    line.setAttribute('x2', this.x2);
    line.setAttribute('y2', this.y2);
    line.setAttribute('stroke', this.color);
    return line;
  }
}

class Arrow {
  constructor(x1, y1, x2, y2, c = 'black') {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.color = c;
  }

  create() {
    const lineLength = (Math.abs(this.x1 - this.x2) ** 2 + Math.abs(this.y1 - this.y2) ** 2) ** 0.5;
    const cos = (this.x2 - this.x1) / lineLength;

    const angle = (this.y1 >= this.y2) ? Math.acos(cos) : Math.PI + (Math.PI - Math.acos(cos));
    const arrowLength = 15;
    const arrowAngle = Math.PI / 12;

    const moreAngle = angle + arrowAngle;
    const moreAngleX = this.x2 - Math.cos(moreAngle) * arrowLength;
    const moreAngleY = this.y2 + Math.sin(moreAngle) * arrowLength;
    const moreAngleLine = new Line(this.x2, this.y2, moreAngleX, moreAngleY);

    const lessAngle = angle - arrowAngle;
    const lessAngleX = this.x2 - Math.cos(lessAngle) * arrowLength;
    const lessAngleY = this.y2 + Math.sin(lessAngle) * arrowLength;
    const lessAngleLine = new Line(this.x2, this.y2, lessAngleX, lessAngleY);

    return {
      moreAngleLine: moreAngleLine.create(),
      lessAngleLine: lessAngleLine.create()
    };
  }
}

На сколько оправдан такой код с точки зрения ООП? И как лучше сделать?

voraa 12.04.2024 08:11

С точки зрения ООП, главное - как это потом будет использоваться. Какие будут объекты и какие действия (методы) с ними будут производиться.

Например. Предполагается ли у этих объектов метод перемещения объекта (move)? или изменение цвета (color)?
Например
const c = new Circle(100, 200, 50);
c.move(200, 300).color('red')


А как вы реализуете эти методы? Просто поменять координаты в объекте ничего не даст. Надо менять атрибуты у элемента. А где у вас связь между объектом и элементом? У какого элемента менять, если он никак не запомнен в объекте.

В чем смысл метода create?
Что дает просто создание объекта (new Line (100, 200, 200, 300);) ,без вызова create()?
А если вызвать create много раз?
const l = new Line (100, 200, 200, 300);
l.create();
l.create();
l.create();

Это так и задумывалось, что будут созданы 3 элемента?

Какой вообще смысл хранить координаты и прочие свойства элемента, если их всегда можно получить из атрибутов? Ведь при выполнении каких то действий с объектом их надо будет синхронизировать - менять и там и там. Легко сделать ошибку.

Ну вот такие мысли.
Главное - как использовать. От этого зависит, что и как делать.

voraa 12.04.2024 08:23

ЗЫ Для стрелок, обычно элемент <marker> используют
https://developer.mozilla.org/en-US/...Element/marker

roland 12.04.2024 14:07

Я вижу здесь проблему в мотивации рефакторинга. Человек сразу обозначает свою проблему:
Цитата:

Сообщение от firep91613 (Сообщение 555113)
Сейчас у меня в файле класса рисовалки почти 300 строк кода. Я уже путаюсь что и где.


И то, как пытается свою проблему решить:
Цитата:

Сообщение от firep91613 (Сообщение 555113)
Решил сделать отдельные классы для каждого элемента. Думаю, еще классы раскидать по разным файлам.


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

Проблема не в ООП, а в удобстве чтения кода в одном классе. Это вопрос относится к знанию своего редактора кода и навыкам навигации по коду.

Конечно, это не исключает "странностей" в виде функций create, названия методов или функциональности класса Arrow, который возвращает объект с составными частями элемента, а не единый цельный элемент, но эти проблемы не исправить оборачиванием методов в классы.

firep91613 12.04.2024 16:17

voraa,
перемещение и изменение цвета не предполагается. Координаты считаются в зависимости от количества элементов и т.д.
Цитата:

Сообщение от voraa
ЗЫ Для стрелок, обычно элемент <marker> используют
https://developer.mozilla.org/en-US/...Element/marker

Как все просто :D

Цитата:

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

То есть все методы оставить в классе рисовалки?

Цитата:

Сообщение от roland
Проблема не в ООП, а в удобстве чтения кода в одном классе. Это вопрос относится к знанию своего редактора кода и навыкам навигации по коду.

Я просто занимаюсь этим не каждый день. И потом чтобы вспомнить, что там навоял приходится скролить, смотреть, что и как.

Просто я устал скролить по всему этому коду. Вот и хочу вынести в отдельные файлы с классами отдельных элементов.

voraa 12.04.2024 16:58

Цитата:

Сообщение от firep91613
Как все просто

Это действительно не сложно. Сделал один маркер и используешь везде, где нужно.
Цитата:

Сообщение от firep91613
То есть все методы оставить в классе рисовалки?

Самой рисовалки не видно. Нет методов, которые добавляют эти элементы в DOM.
Цитата:

Сообщение от firep91613
перемещение и изменение цвета не предполагается.

А какой смысл тогда хранить в объекте эти координаты, если после создания элемента они больше никак не используются?
Если с созданными объектами не предполагается производить какие то действия, то зачем тут вообще ООП?
Сделайте просто функции, которые создают элемент
function Circle (x, y, r = 20, c = '#7F6565') {
    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    circle.setAttribute('r', r);
    circle.setAttribute('cx', x);
    circle.setAttribute('cy', y);
    circle.setAttribute('fill', c);
    circle.setAttribute('stroke-width', 1);
    return circle;
}

firep91613 12.04.2024 17:48

Цитата:

Сообщение от voraa
А какой смысл тогда хранить в объекте эти координаты, если после создания элемента они больше никак не используются?
Если с созданными объектами не предполагается производить какие то действия, то зачем тут вообще ООП?
Сделайте просто функции, которые создают элемент

Ну да, вы правы. Пожалуй так и сделаю. Спасибо.


Часовой пояс GMT +3, время: 20:07.