Pytanko kierowane głównie do ludzi, którzy znają różnice pomiędzy paradygmatami obiektowymi, funkcyjnymi i pozostałymi; średnio interesuje mnie opinia ludzi w stylu "Piszę w OOP ale czasem zrobię zmienną globalną".
A więc tak, mam kilka projektów, które napisałem całkowicie obiektowo w TDD; język nie istotny. I zrobiłem to najbardziej obiektowo jak mogłem; czyli:
- Zero zmiennych i metod statycznych, brak zmiennych globalnych
- Prawie wszystkie obiekty są immutable (kolekcje, parsery, etc.), oprócz kilku które dotykają IO, bo się nie dało
- Każdy obiekt coś enkapsuluje, i ma swoją tożsamość.
- Nie ma getterów, obiekty rodzą tylko inne obiekty
- Wszystkie klasy są krótsze niż 100 linijek
- Wszystkie funkcje są krótsze niż 6-7 linijek, większość 2-4.
- Nie ma żadnych service'ów, singletonów, etc.
- Nie mam obiektów typu Manager, Producer, Parser, Controller, Sender, Fetcher, Reader, tylko prawdziwie obiektowe nazwy jak np Subpattern, SentMail, FilePermission, ClassName, etc.
Zrobiłem sobie to jako taki exercise czy się da, bo sądziłem że się da, i się da. Wydaje mi się że cały projekt jest obiektowy.
I teraz doszedłem do dziwnego przypadku. Mam sparsować string; string którego format jak 150 jest zbudowany tak żeby dało się go łatwo i iteratywnie parsować w C.
Zasady jakimi rządzi się parsowanie tego stringa to:
- Możę zawierać cyfty, litery a-z, i kilka znaków specjalnych, ale nie może zacząć się od cyfry
- Znaki na początku muszą być z małej litery, potem, po pewnym znaku specjalnym muszą być od wielkiej
- jest też jeden znak który jest takim "wildcard"em i znaczy to samo co wszystkie wielkie litery
Muszę też ogarnąć przypadki żeby program się wywalił jak jest więcej niż jeden znak specjalny, i jeśli znak specjalny wystąpi po wildcardzie. Iteratywnie to jest mega prosto zrobić, zresztą po samym zadaniu to widać "po", "więcej niż jeden", "na początku", etc.
I teraz; na początku zrobiłem pod to testy i napisałem całość całkowicie immutable, czyli split najpierw całego stringa po tym znaku specjalnym, + wyjątek jak jest ich więcej, potem split po wildcardzie, potem parsowanie liter najpierw dużych i małych, straszny burdel się z tego zrobił. Całość faktycznie moim zdaniem wyglądała na obiektową, bo wszystko było immutable, wszystkie funkcje były bez stanowe, takie "pure", i próbowałem to potem zrefaktorować, bo idea tego kodu jest prosta; wydawałoby się że powinno się to móc łatwo sparsować, ale maksymalnie mi się to udało zrefaktorować do 6 funkcji po 3-4 linijki.
Potem stwierdziłęm, jak by to wyglądało proceduralnie. Czyli zrobiłem sobie stanowy obiekt, coś jak StringBuilder
, tylko dopasowany pod ten string, i zrobiłęm fora. For leciał po każdym znaku, i zmieniał stan. I co :o Cały algorytm w jednej funkcji na 8 linijek, bo to był for, z trzema ifami który wołał metody tego mutable buildera.
No właśnie, tylko builder był mutable. Tak to wyglądało
private function parsedSet(string $flagString): Set
{
$syntax = new ConnectionStringSyntax($this->flags);
foreach (\str_split($flagString) as $letter) {
if ($letter === '|') {
$syntax->wildcardAllUppercase();
} else if ($letter === '>') {
$syntax->onlyUppercase();
} else {
$syntax->addNextLetter($letter); // ten dodaje uppercase lub lowercase zależnie od tego czy ->onlyUppercase() było już zawołane
}
}
return $syntax->entities();
}
Po rozważaniach zrozumiałem: tak się dzieje dlatego że format tego stringa został stworzony z myślą o tym, żeby go iteratywnie parsować, jak w C; a nie z myślą o tym żeby osobnymi funkcjami dało się łatwo coś z niego wyciągnąć.
I tu pytanie o waszą opinie:
- Z jednej strony,
mutable w OOP złe.OOP nie dopuszczam mutowalności. - Z drugiej jednak, cała "mutowalność" tego
ConnectionStringSyntax
jest zamknięta w tej jednej funkcjiparsedSet()
- Z trzeciej jednak, żeby to podzielić bardziej na funkcyjki należałoby i tak "rozprzestrzenić" tą mutowalność na więcej funkcji, co mi się wydaje nie do końca dobre.
- Z czwartej jednak, nie po to się pisze w OOP żeby mieć mutowalność gdziekolwiek
- Z piątej jednak; kod iteratywny jest 3-4 razy krótszy
- Z szósetej zaś; może jest jakiś sposób żę da się sparsować całkowicie immutable ten string, tylko nie wpadłem na to i to jest okazja dla mnie żeby się czegoś nauczyć?
I proszę mi nie wyjeżdżać z żadnymi "pragmatyzm vs puryzm", uprzejmie dziękuję.
Wszelakim głosicielom "hybrydowych paradygmatów" też dziękuję bo nie tego tyczy się wątek.
Mam inne projekty których nie pisze w zgodzie z jednym paradygmatem, ale ten wątek i ten projekt jest o całkowicie obiektowym kodzie, więc proszę nie schodzić na off-top i odradzać takie podejście w tym wątku, dziękuję.
Podsumowanie wątku
-
Argumenty za:
- @Afish: złamanie paradygmatu nie budzi wtf'ów
-
Argumenty przeciw:
- soon