Języki OO mogą być czasami używane zamiast języków niskiego poziomu do bezpośredniego połączenia z maszyną. C ++ Na pewno, ale nawet dla C # istnieją adaptery i tym podobne. Chociaż pisanie kodu do sterowania częściami mechanicznymi i drobnej kontroli nad pamięcią jest najlepiej utrzymywane jak najbliżej niskiego poziomu, jak to możliwe. Ale jeśli to pytanie jest związane z obecnym oprogramowaniem obiektowym, takim jak linia biznesu, aplikacje internetowe, IOT, usługi sieciowe i większość masowo używanych aplikacji, to ...
Odpowiedz, jeśli dotyczy
Czytelnicy mogą próbować pracować z architekturą zorientowaną na usługi (SOA). To znaczy, DDD, N-warstwowe, N-wielowarstwowe, sześciokątne, cokolwiek. Nie widziałem, aby aplikacja dla dużych firm efektywnie korzystała z „tradycyjnego” OO (Active-Record lub Rich-Models), jak to opisano w latach 70. i 80. w ostatniej dekadzie +. (Patrz uwaga 1)
Błąd nie dotyczy OP, ale z tym pytaniem wiąże się kilka problemów.
Podany przykład to po prostu demonstracja polimorfizmu, nie jest to kod produkcyjny. Czasami dokładnie takie przykłady są brane dosłownie.
W FP i SOA dane są oddzielone od logiki biznesowej. Oznacza to, że dane i logika nie idą w parze. Logika przechodzi do usług, a dane (modele domenowe) nie zachowują się polimorficznie (patrz uwaga 2).
Usługi i funkcje mogą być polimorficzne. W FP często przekazujesz funkcje jako parametry do innych funkcji zamiast wartości. Możesz zrobić to samo w OO Languages z typami takimi jak Callable lub Func, ale nie działa on gwałtownie (patrz Uwaga 3). W FP i SOA twoje modele nie są polimorficzne, tylko twoje usługi / funkcje. (Patrz uwaga 4)
W tym przykładzie występuje zły przypadek kodowania. Nie mówię tylko o czerwonym sznurku „pies szczeka”. Mówię też o samych modelach CatModel i DogModel. Co dzieje się, gdy chcesz dodać owcę? Musisz wejść do swojego kodu i utworzyć nowy kod? Czemu? W kodzie produkcyjnym wolałbym zobaczyć tylko AnimalModel z jego właściwościami. W najgorszym przypadku AmphibianModel i FowlModel, jeśli ich właściwości i obsługa są tak różne.
Oto, czego oczekiwałbym w obecnym języku „OO”:
public class Animal
{
public int AnimalID { get; set; }
public int LegCount { get; set; }
public string Name { get; set; }
public string WhatISay { get; set; }
}
public class AnimalService : IManageAnimals
{
private IPersistAnimals _animalRepo;
public AnimalService(IPersistAnimals animalRepo) { _animalRepo = animalRepo; }
public List<Animal> GetAnimals() => _animalRepo.GetAnimals();
public string WhatDoISay(Animal animal)
{
if (!string.IsNullOrWhiteSpace(animal.WhatISay))
return animal.WhatISay;
return _animalRepo.GetAnimalNoise(animal.AnimalID);
}
}
Jak przechodzisz od zajęć w OO do programowania funkcjonalnego? Jak powiedzieli inni; Możesz, ale tak naprawdę nie. Chodzi o to, aby zademonstrować, że nie powinieneś nawet używać klas (w tradycyjnym znaczeniu tego słowa) podczas programowania w Javie i C #. Kiedy już zaczniesz pisać kod w architekturze zorientowanej na usługi (DDD, warstwowe, warstwowe, heksagonalne, cokolwiek), będziesz o krok bliżej do funkcjonalności, ponieważ oddzielasz swoje dane (modele domen) od funkcji logicznych (usługi).
Język OO o krok bliżej do FP
Możesz nawet pójść o krok dalej i podzielić swoje usługi SOA na dwa typy.
Opcjonalna klasa typu 1 : Wspólne usługi implementujące interfejs dla punktów wejścia. Byłyby to „nieczyste” punkty wejścia, które mogą wywoływać inne „czyste” lub „nieczyste” funkcje. Mogą to być Twoje Punkty wejścia z API RESTful.
Opcjonalna klasa typu 2 : czyste usługi logiki biznesowej. Są to klasy statyczne, które mają funkcjonalność „czystą”. W FP „Pure” oznacza, że nie ma żadnych skutków ubocznych. Nigdzie nie ustawia on wyraźnie stanu ani trwałości. (Patrz uwaga 5)
Kiedy więc pomyślisz o klasach w językach zorientowanych obiektowo, które są używane w architekturze zorientowanej na usługi, nie tylko przynosi to korzyści Twojemu kodowi OO, ale sprawia, że programowanie funkcjonalne wydaje się bardzo łatwe do zrozumienia.
Notatki
Uwaga 1 : Oryginalny, zorientowany obiektowo obiekt „Rich” lub „Active-Record” jest nadal dostępny. W przeszłości, gdy ludzie „robili to dobrze” dekadę lub więcej temu, istnieje wiele takich starszych kodów. Ostatni raz widziałem tego rodzaju kod (poprawnie wykonany) z gry wideo Codebase w C ++, w którym dokładnie kontrolują pamięć i mają bardzo ograniczoną przestrzeń. Nie wspominając, że FP i architektury zorientowane na usługi są bestiami i nie powinny brać pod uwagę sprzętu. Ale priorytetem jest możliwość ciągłej zmiany, utrzymania, zmiany wielkości danych i innych aspektów. W grach wideo i sztucznej inteligencji maszyn bardzo precyzyjnie kontrolujesz sygnały i dane.
Uwaga 2 : Modele domen nie mają zachowania polimorficznego, ani nie mają zależności zewnętrznych. Są „odizolowane”. To nie znaczy, że muszą być w 100% anemiczne. Mogą mieć wiele logiki związanej z ich budową i zmiennymi zmianami właściwości, jeśli ma to zastosowanie. Zobacz DDD „Obiekty wartości” i jednostki autorstwa Erica Evansa i Marka Seemanna.
Uwaga 3 : Linq i Lambda są bardzo powszechne. Ale kiedy użytkownik tworzy nową funkcję, rzadko używa Func lub Callable jako parametrów, podczas gdy w FP byłoby dziwnie widzieć aplikację bez funkcji zgodnych z tym wzorcem.
Uwaga 4 : Nie mylić polimorfizmu z dziedziczeniem. Model CatModel może odziedziczyć AnimalBase, aby określić, jakie właściwości zwierzę zwykle ma. Ale jak pokazuję, takie modele to Zapach Kodowy . Jeśli zobaczysz ten wzorzec, możesz rozważyć jego rozbicie i przekształcenie w dane.
Uwaga 5 : Funkcje Pure mogą (i wykonują) akceptować funkcje jako parametry. Funkcja przychodząca może być nieczysta, ale może być czysta. Do celów testowych zawsze byłby czysty. Ale w produkcji, chociaż jest traktowany jako czysty, może zawierać skutki uboczne. To nie zmienia faktu, że czysta funkcja jest czysta. Chociaż funkcja parametru może być nieczysta. Nie mylące! :RE