Стоит ли разбивать решение задачи на классы?

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

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

Первый вариант - создать один класс Integral с методом Calculate, у которого, по мимо выше перечисленных параметров, ещё будет указываться способ интегрирования (это удобно реализовать через перечисления).

Второй варинт - создать интерфейс IIntegral с методом Calculate и реализовать его классом Integral с виртуальным методом Calculate, от последнего унаследовать четыре класса которые будут перегружать метод в зависимости от способа интегрирования.

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

Есть ли какой-то стандарт или правило как это правильно реализовывать?


Ответы (2 шт):

Автор решения: iKuzmychov

Ваша задача состоит из реализации 4-х различных методов подсчёта интеграла. Интеграл, в свою очередь, - это просто символ, которым обозначается функция интегрирования, это нельзя назвать объектом, как я считаю.

Основываясь на вышесказанном, я бы реализовал это в виде статического класса:

public static class Integral
{
    public static int Calculate1(...) => ...; // 1й метод
    public static int Calculate2(...) => ...; // 2й метод
    public static int Calculate3(...) => ...; // 3й метод
    public static int Calculate4(...) => ...; // 4й метод
}

Почему здесь излишни интерфейсы?

Интерфейс - это контракт. Интерфейсы нужны тогда, когда вы хотите гарантировать, что разные объекты или типы будут иметь некоторый общий функционал (методы и свойства), которым можно будет воспользоваться не зная о его реализации.

Так как интеграл это не объект, он не предпалагает другие классы, расширяющие его функционал. Следовательно и интерфейс было бы создавать излишне.

Вы можете сказать, что интерфейс был бы не излишним, так как каждый метод интегрирования был бы реализован отдельным классом.

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

P.S.

К слову о вашем втором варианте решения задачи. Если уж и создавать интерфейс IIntegral, то стоит от него напрямую реализовывать 4 класса с реализацией метода Calculate. Прослойка в виде некоторого класса Integral с виртуальным методом Calculate будет излишеством в квадрате.

→ Ссылка
Автор решения: Виталий Злобин

Второй вариант я бы сразу отбросил, т.к. плодить классы, просто потому-что у них разные способы вычисления - не круто. Тут усматриваю нарушение принципа единственной ответственности: 1 задача - 1 класс и наоборот 1 класс - 1 задача. Вся логика интегрирования должна быть инкапсулирована в одном классе.


Первый вариант следует реализовать так:

  1. Создать класс Integral
  2. Для каждого из 4х способов вычисления реализовать отдельный закрытый(private) метод с параметрами
  3. Создать открытый метод Calculate, принимающий Enum(метод вычисления) и аргументы. В нём, в зависимости от значения Enum, вызывать конкретные методы, передавая в них аргументы.
→ Ссылка