Как профессиональные программисты выносят суждение о том, идти ли на ООП или нет? Это было бы очень полезно для меня.
Для меня есть два решения. Во-первых, иногда это будет очевидно в начале. Будет много похожих типов, которые имеют общие методы, которые сильно различаются по деталям реализации. Например, я строил систему документооборота, и мне нужна была возможность выполнять произвольные задачи. Чтобы выполнить задачу, я реализовал базовый класс, от которого унаследована каждая задача, с помощью Execute()
абстрактного метода. Унаследованные классы обеспечивали реализацию, но система рабочего процесса могла начать выполнение, не зная ничего о том, какую задачу выполняли.
Хотя большинство проектов не так однозначно. Второй момент принятия решения - когда подмножество проекта переросло в огромную путаницу операторов if-then или операторов switch-case, и особенно когда эти операторы if-then требуют большого количества кода для корректной работы. Я чувствую, что начинаю терять логику того, чего я пытаюсь достичь, и код начинает чувствовать себя хрупким. В этот момент, как правило, это признак того, что пришло время преобразовать код в базовые классы с конкретными реализациями.
Большая часть перехода к объектно-ориентированному стилю в противоположность функциональному стилю заключается в преобразовании операторов if-then в операторы «run this action». Вместо огромного набора операторов if-then вы просто указываете коду выполнить его действие. Какое действие на самом деле выполняется, зависит от реализации, которую вы предоставили.
Например, вот функциональный стиль в псевдокоде в стиле C #:
if ( action == "email" ) {
callEmailFunction(userInfo);
}
else if ( action == "sms" ) {
callSmsFunction(userInfo);
}
else if ( action == "web" ) {
endpoint = "http://127.0.0.1/confirm";
confirmWeb(endpoint, userinfo);
}
...
Но, возможно, вы могли бы переписать это примерно так:
interface IConfirmable {
void Confirm(UserInfo userinfo);
}
public class ConfirmEmail : IConfirmable {
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via email
}
}
public class ConfirmSms : IConfirmable {
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via email
}
}
public class ConfirmWeb : IConfirmable {
// this is a constructor
public ConfirmWeb(string endpoint) {
...
}
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via web
}
}
А потом сам код:
// An implementation that decides which implementation of the base class to use
// This replaces the if-then statements in the functional programmming.
IConfirmable confirmer = ConfirmerFactory.GetConfirmer();
// get the userinfo however you get it,
// which would be the same way you get it in the functional example.
UserInfo userinfo = ...;
// perform the action.
confirmer.Confirm(userinfo);
Теперь, когда внутри if-then очень мало кода, это выглядит как большая работа, которая не приносит никакой пользы. И когда в if-then очень мало кода, это правильно: это большой труд для кода, который сложнее понять.
Но объектно-ориентированный стиль действительно сияет, когда у вас есть несколько действий, а не только Confirm()
метод, который необходимо выполнить. Возможно, у вас есть подпрограмма инициализации, три или более методов действия, которые можно запустить, и Cleanup()
метод. Базовый алгоритм идентичен, за исключением того, что он обращается к соответствующим объектам, которые реализуют общий базовый класс. Теперь вы начинаете видеть реальную выгоду для объектно-ориентированного стиля: базовый алгоритм гораздо легче читать, чем если бы он проверял операторы if-then на каждом этапе пути.