Стоит ли разбивать решение задачи на классы?
Я пишу лабораторные роботы в университет по дисциплине, которая совмещает в себе программирование и математику. Пишу в стиле ООП, и не понимаю, как корректнее, с точки зрения стандартов программирования, стоит реализовать задачу.
Допустим, есть определённый интеграл, и нужно найти площадь под графиком, зная левую и правую границу и количество разбиений. У меня есть четыре способа решения этой задачи: метод левых прямоугольников, метод правых прямоугольников, метод трапеции и метод парабол. У меня есть два варианта как это всё реализовать в коде.
Первый вариант - создать один класс Integral с методом Calculate, у которого, по мимо выше перечисленных параметров, ещё будет указываться способ интегрирования (это удобно реализовать через перечисления).
Второй варинт - создать интерфейс IIntegral с методом Calculate и реализовать его классом Integral с виртуальным методом Calculate, от последнего унаследовать четыре класса которые будут перегружать метод в зависимости от способа интегрирования.
С одной стороны удобней писать всё в одном классе, но меня терзает, что это как-то не в стиле ООП и, что следует неким образом применить наследование и полиморфизм.
Есть ли какой-то стандарт или правило как это правильно реализовывать?
Ответы (2 шт):
Ваша задача состоит из реализации 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 задача. Вся логика интегрирования должна быть инкапсулирована в одном классе.
Первый вариант следует реализовать так:
- Создать класс Integral
- Для каждого из 4х способов вычисления реализовать отдельный закрытый(private) метод с параметрами
- Создать открытый метод Calculate, принимающий Enum(метод вычисления) и аргументы. В нём, в зависимости от значения Enum, вызывать конкретные методы, передавая в них аргументы.