Czym dokładnie jest programowanie proceduralne? Czym dokładnie różni się od OOP? Czy to to samo, co programowanie funkcjonalne?

32

Programuję w Javie w bardzo obiektowym stylu (OO). OOP przychodzi mi bardzo intuicyjnie, ale mam bardzo małą wiedzę na temat innych rodzajów programowania.

Czym dokładnie jest programowanie proceduralne ? Czym dokładnie różni się od OOP? Czy to to samo, co programowanie funkcjonalne ?

Kiedyś myślałem, że wszystkie programy, które nie są OO, są proceduralne. Ale zaczynam myśleć, że to nieprawda.

Aviv Cohn
źródło
9
Udostępnianie badań pomaga wszystkim. Powiedz nam, co próbowałeś i dlaczego nie spełnia twoich potrzeb. To pokazuje, że poświęciłeś trochę czasu, aby spróbować sobie pomóc, oszczędza nam to powtarzania oczywistych odpowiedzi, a przede wszystkim pomaga uzyskać bardziej konkretną i odpowiednią odpowiedź. Zobacz także How to Ask
komara
2
Programowanie proceduralne to nie to samo, co programowanie funkcjonalne; jest to właściwie to samo, co programowanie obiektowe, pomniejszone o obiekty i klasy.
Mason Wheeler
1
Imperative OOP to tak naprawdę programowanie proceduralne, więc jest to dokładnie to, co robisz cały czas ...
Ingo

Odpowiedzi:

68

Wikipedia ma dobre wyjaśnienia dla tych terminów. Bez względu na to, oto podsumowanie:


  • Programowanie deklaratywne jest przeciwieństwem programowania imperatywnego - określa, co należy obliczyć, a nie jak (np. SQL, wyrażenia regularne).

  • Obliczenia modeli programowania funkcjonalnego jako wyrażeń, które (mogą) dawać wartości. Funkcje są wartościami i mogą być przekazywane lub zwracane z innych funkcji. Mutacja jest odradzana; wszystkie zmienne są domyślnie niezmienne. W rezultacie jest bardziej deklaratywny niż imperatywny, ponieważ podkreśla to, co jest obliczane, a nie sekwencję zmian stanu niezbędnych do jego osiągnięcia.

  • Czysto funkcjonalne programowanie całkowicie wyklucza mutację (choć wbrew powszechnemu przekonaniu wciąż ma mechanizmy osiągania efektów ubocznych).
  • Całkowite programowanie funkcjonalne dodatkowo zabrania wyjątków i nieskończonej pętli. (Całkowita funkcja w matematyce to funkcja, która zwraca wartość dla wszystkich swoich danych wejściowych.)

Ich relacje są nieco skomplikowane, ponieważ OOP jest dość obciążonym terminem. Możesz używać obiektów zarówno w językach funkcjonalnych, jak i językach proceduralnych, ale języki reklamujące się jako OO są proceduralne. Aby dodatkowo pomieszać problem:

  • Większość ludzi nie zna różnicy między obiektem a abstrakcyjnym typem danych
  • Języki OOP głównego nurtu nie wspominają o ADT, zapewniają bardzo słabą obsługę i reklamują obiekty jako The One True Way.
  • Nikt nie mówi o programowaniu abstrakcyjnym zorientowanym na typy danych (bo byłoby głupotą; potrzebujesz zarówno narzędzi ADT, jak i obiektów).

To powoduje, że ludzie myślą, że OOP jest jedynym sposobem na uzyskanie abstrakcji, a programowanie funkcjonalne i OOP są w jakiś sposób przeciwieństwami lub wykluczają się wzajemnie. Wiele osób uważa również, że wszystkie języki funkcjonalne są czyste i nie pozwalają na mutację.

Dodatkowo, ludzie przerzucają się imperatywnie / proceduralnie zamiennie, czasami porównując go z OOP (implikując kod pozbawiony abstrakcji, ogólnie C), a czasem porównując go z programowaniem funkcjonalnym. O ile mogę powiedzieć, pojęcie programowania strukturalnego w większości przestało być używane (prawdopodobnie dlatego, że w tym momencie większość ludzi przyjmuje za pewnik, że goto i globale są uważane za szkodliwe).

Doval
źródło
3
„zabrania skakania” jest raczej ogólne; w tym jeśli / while / etc .. może „zabrania arbitralnych skoków”?
Izkata
@Izkata Dobry punkt, zmieniony.
Doval
1
Być może warto linkować do wpisów na Wikipedii.
haylem
I dlatego nazywa się Obiekt „Zorientowany”, a nie Tylko Obiekt.
JeffO
1
@OrangeDog Jak to się różni od abstrakcyjnego typu danych, który również określa hermetyczną zbiór danych i funkcji, które mogą działać na nim? Co więcej, możesz mieć niezmienne obiekty, więc w takim razie jaki stan ?
Doval
12

Programowanie proceduralne jest podejściem do programowania, które jest jednym z podstawowych elementów składowych wielu innych projektów językowych (funkcjonalność nie jest jednym).

Większość języków mieści się w zestawie „Programowania proceduralnego” i jest to prawdopodobnie najbardziej naturalne podejście do projektowania dla większości ludzi (jeśli myślisz o OO, to powiedziałbym, że jesteś w mniejszości).

BASIC ma charakter proceduralny.

Jak powiedzieli inni, jest to mechanizm do sekwencjonowania programów.

  • Najpierw robię x
  • Po drugie, robię to
  • Po trzecie, robię Z

Wymaga mechanizmu do definiowania „procedur” - bloków o nazwanym kodzie podobnym do metod OO, które mogą przyjmować od zera do wielu parametrów i opcjonalnie zwracać wartość (która wówczas byłaby na ogół nazywana funkcją - prawdopodobnie prowadząc do pomylenia z językami funkcjonalnymi )

Paradygmat nie dyktuje, jakie będą twoje rzeczy ani sposób, w jaki rzeczy będą przekazywane.

Po prostu opisuje, że program będzie się składał z szeregu procedur (lub funkcji), które działają sekwencyjnie. Dane są następnie definiowane niezależnie od procedur.

Różni się to od programowania obiektowego, które konstruuje program wokół zbiorów danych i metod (nie funkcji), które działają na tych danych.

Jednym ze sposobów myślenia o tym jest zakres danych.

W języku proceduralnym ustalanie zakresu jest dość proste. Zmienna może znajdować się w zakresie danej procedury (deklarowana lokalnie), aż do poziomu najważniejszej rzeczy wywołującej (deklarowanej globalnie), z zasięgami zagnieżdżonymi pomiędzy.

W języku obiektowym dodajesz nowy kontekst zakresu, będący kontekstem aktualnie używanego obiektu, który jest prostopadły do ​​powyższego.

Innym sposobem myślenia proceduralnego w porównaniu do obiektowego jest rozważenie języka zorientowanego obiektowo, w którym wszystkie metody muszą być zadeklarowane jako statyczne. Rezultatem jest język proceduralny, w którym klasy mogą być używane do grupowania procedur razem.

Rob Baillie
źródło
5

Programowanie proceduralne zdecydowanie nie jest programowaniem funkcjonalnym.

Programowanie proceduralne ma miejsce, gdy masz w głowie model komputera jako maszyny i zastanawiasz się, jak modyfikuje on dane w pamięci. Najpierw ustaw Awartość 3, a następnie dodaj 1 i zapisz ją Aponownie w pamięci (nadpisując poprzednią wartość).

Programowanie funkcjonalne powiedziałoby, że Ajest 3, i Bjest A + 1, a następnie pozwala komputerowi wymyślić, jak obliczyć B. Po zdefiniowaniu Ato powinna być niezmienna (nie zmienia). Funkcjonalność pozwala również na wykonywanie takich czynności, jak przekazywanie funkcji jako wartości pierwszej klasy (funkcja może przyjmować funkcję jako argument).

Programowanie obiektowe często łączy oba te elementy i jest swego rodzaju ortogonalne dla obu. Możesz użyć programowania funkcjonalnego i zwrócić niezmienny obiekt, a ten obiekt może mieć metodę, która zwraca pewną obliczoną wartość, a nawet zrobić to leniwie - jest to programowanie obiektowe funkcjonalne. Możesz również mieć obiekt reprezentujący „repozytorium” (abstrakcyjną wersję bazy danych), możesz „zapisywać” rzeczy w repozytorium i „pobierać” rzeczy z powrotem, a ten obiekt może obsłużyć wszystkie szczegóły tego, jak to się robi . Zasadniczo jest to programowanie proceduralne zorientowane obiektowo.

Scott Whitlock
źródło
0

OOP to nic innego jak nieco wyrafinowana forma programowania proceduralnego, która ponownie należy do większej rodziny programowania imperatywnego. Dowodem tego twierdzenia jest to, że wielu programistów C # / Java ma tendencję do „robienia czegoś” i woli metody takie jak:

void doThisAndThat(....) { ... do something ... }

Tak więc program składający się z kilku metod void (wcześniej znanych jako procedury (sic!)) I kodu takiego jak:

doThis();
if (state is that) doSomethingElse();
doThat();

to idealne programowanie proceduralne.

Ingo
źródło
doThisAndThat (....) oznacza, że ​​metoda zrobi więcej niż jedną rzecz, co nie jest ogólnie dobrą praktyką. Programiści Java i C # w większości przestrzegają zasady pojedynczej odpowiedzialności. Myślę, że twoja analogia jest błędna. objectmentor.com/resources/articles/srp.pdf
JohnK
@JohnK Wiem, że to nie jest dobra praktyka. Ale powszechny. Zwłaszcza wśród programistów Java, jeśli można ocenić na podstawie tego, co widzi się codziennie na SO.
Ingo
@JohnK Programiści Java i C # w większości przestrzegają zasady pojedynczej odpowiedzialności - usługi warg ?
Ingo
Programiści Java w większości przestrzegają zasady pojedynczej odpowiedzialności? Gdyby tylko tak było w prawdziwym życiu ...
Sridhar Sarnobat