Jak profesjonalni programiści oceniają, czy wybrać OOP, czy nie? Byłoby to dla mnie bardzo pomocne.
Dla mnie są dwa punkty decyzji. Po pierwsze, czasami będzie to oczywiste na początku. Będzie wiele podobnych typów, z których wszystkie mają wspólne metody, które różnią się znacznie szczegółami ich implementacji. Na przykład budowałem system przepływu pracy i potrzebowałem umiejętności realizacji dowolnych zadań. Aby uruchomić zadanie, zaimplementowałem klasę podstawową, z której każde zadanie dziedziczyło, za pomocą Execute()metody abstrakcyjnej. Klasy dziedziczące dostarczyły implementację, ale system przepływu pracy mógł rozpocząć wykonywanie, nie wiedząc nic o rodzaju wykonywanego zadania.
Większość projektów nie jest jednak tak jednoznaczna. Drugi punkt decyzji ma miejsce, gdy podzbiór projektu urósł do ogromnej plątaniny instrukcji if-then lub instrukcji case-switch, a zwłaszcza gdy te instrukcje if-then wymagają dużej ilości kodu instalacyjnego do poprawnego działania. Czuję, że zaczynam tracić logikę tego, co próbuję osiągnąć, a kod zaczyna być kruchy. W tym momencie zwykle jest to znak, że nadszedł czas, aby przefakturować kod na klasy podstawowe z konkretnymi implementacjami.
Dużą częścią przejścia na styl obiektowy w przeciwieństwie do stylu funkcjonalnego jest przekształcanie instrukcji if-then w instrukcje „uruchom tę akcję”. Zamiast ogromnego zestawu instrukcji „jeśli-to”, po prostu mówisz kodowi, aby uruchomił swoją akcję. To, które działanie jest faktycznie wykonywane, zależy od dostarczonej implementacji.
Na przykład, oto funkcjonalny styl w pseudokodzie w stylu 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);
}
...
Ale może mógłbyś przepisać to na coś takiego:
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
}
}
A potem sam kod:
// 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);
Teraz, gdy w kodzie if-wtedy jest bardzo mało kodu, wygląda to na dużo pracy, która nie przynosi korzyści. A kiedy w kodzie if-wtedy jest bardzo mało kodu, jest to poprawne: jest to dużo pracy dla kodu, który jest trudniejszy do zrozumienia.
Ale styl zorientowany obiektowo naprawdę świeci, gdy masz więcej niż jedną akcję, niż tylko Confirm()metodę, którą należy wykonać. Być może masz procedurę inicjalizacji, trzy lub więcej metod działania, które można uruchomić, oraz Cleanup()metodę. Algorytm podstawowy jest identyczny, z tym wyjątkiem, że wywołuje wywołania w odpowiednie obiekty, które implementują wspólną klasę podstawową. Teraz zaczynasz dostrzegać prawdziwą korzyść ze stylu obiektowego: algorytm bazowy jest znacznie łatwiejszy do odczytania, niż gdyby sprawdzał instrukcje „jeśli-to” na każdym etapie.