Jak pisać dobry kod w PHP?

0

Witam
Jestem osobą dość zaawansowaną w PHP. Znam dobrze obiektówkę, uczyłem się Slima, Silexa, Symfony, Laravela... Ogarniam wzorce jak np. MVC. I teraz chciałbym was zapytać jak powinna być dobrze zaprojektowana aplikacja, z tym zawsze mam problem. Wiem że są takie rzeczy jak logika, logika biznesowa, model biznesowy i masa takich pojęć, ale nie odnajduję się w tym. Jak to powinno być zrobione? Jak wyglądają profesjonalne aplikacje? Jak to dzielić?
Poradźcie coś, bo znam wszystko fajnie w teorii z PHPa, ale nie wiem jak napisać kod, aby był naprawdę dobry :(

0
  1. Przeczytaj Domain-Driven Design: Tackling Complexity in the Heart of Software (Eric Evans)
  2. Przeczytaj Implementing Domain-Driven Design (Vaughn Vernon)
  3. Powtarzaj N razy dopóki nie zrozumiesz o co chodzi.

Ja jestem w trakcie realizacji 1 kroku - także nie powiem Ci z doświadczenia jak to wyglada, ale słyszałem od mocno doświadczonych PHP-owców, że te 2 książki to podstawa.

Poza tym wzorce, dużo wzorców - sam MVC nie wystarczy - https://sourcemaking.com/

Też słyszałem takie opinie, że bez TDD nie ma co się brać do wzorców - jak znasz TDD łatwiej Ci jest to ogarnąć bo zanim coś napiszesz to musisz wiedzieć jak kod dokładnie ma się zachowywać.

Dodatkowo polecam YouTube "phpers" i oglądać prezentacje - dużo można się z nich dowiedzieć + czytać książki nt. programowania.

Dodatkowo szukaj informacji i książek o: SOLID DRY GRASP KISS TDD CQRS DDD EventSourcing

1

Najlepiej nauczyć się w praktyce. Za każdym razem gdy masz problem ze zrozumieniem własnego kodu (zwłaszcza wracając do niego po czasie) spróbuj dojść do tego co sprawia, że tak jest. Oczywiście jest parę gotowych praktyk, które warto rozważyć:
DRY – don't repeat yourself: unikaj klepania tego samego wiele razy, znajdź sposób, by zrobić to raz, a potem mieć ten sam wynik z automatu. Dotyczy to zarówno wyodrębniania procedur, ale również często wykonywania innych zadań automatycznie, czy to testów, debugowania, a nawet tworzenia kodu samego w sobie (np. pisząc generatory, czy stosując wysoko dostosowywalne edytory takie jak vim czy emacs). Dlatego też warto pomyśleć nad zaprzyjaźnieniem się z powłoką. Presja czasu to utrudnia, ale zdecydowanie warto, zwraca się. :)
KISS – keep it simple stupid: Rozwiązuj rzeczy tak prosto jak się da, nie martw się na zapas. Rozwiązuj problemy dopiero gdy wystąpią. Wiąże się to z takimi problemami jak przedwczesna optymalizacja czy stosowanie bez potrzeby przekombinowanej architektury. Najpierw skup się na rozwiązaniu problemu, gdy zadziała, dopieszczaj.
Spike-owanie – czyli pisanie kodu przez określony czas z zamierzeniem wyrzucenia go po tym czasie. Praktyka ma na celu skupienie się na lepszym zrozumieniu problemu. Tym barziej, że dobry kod rzadko kiedy powstaje w pierwszym podejściu. Cżesto najlepszą rzeczą jaką można zrobić z programem to przepisać go, będąc już bogatrzym o doświadczenia z poprzedniego podejścia. Odradzam opóźnianie tego, nie warto. Natomiast warto pisać kod tak, żeby możliwie małe kawałki kodu były od siebie mało zależne (tak by przepisanie modułu A nie wymuszało zmiany modułu B).
Kontrola wersji – używaj kontroli wersji nie tylko do współpracy, ale też do łatwości przeglądania tego jak zmieniałeś progam w przeszłości i łatwego przywracania wcześniejszych wersji (bo czasem tak trzeba).
Prototypowanie: czasem warto zostawić z boku założenia co od technologii i najpierw rozwiązać program na pałę, przy pomocy najprostrzych sposobów by dobrze zrozumieć problem.
TDD, Rób jedną małą użyteczną rzecz na raz i potem popatrz co dalej.

Sam zwykle przestrzegam zasady by NIGDY nie automatyzować czegoś czego dostatecznie wiele razy nie zrobiłem na piechotę. Dzięki temu robię rzeczy, które są bardziej użyteczne i lepiej przemyślane.

Wreszcie co do samego kodu: niech go będzie tak mało jak się da, niech nazwy dobrze opisują zmienie i funkcje. Polecam trzymać ograniczenia szerokości linii (do 60-80 znaków) i wcięcia. A poza tym podstawy obiektówki – najlepiej metoda ma jeden (ewentualnie 2) parametr, Jeśli jakieś pole jest używane tylko przez część metod to możliwe, że należy tę klasę podzielić. I tak dalej i tak dalej, znajdziesz to w książkach jeśli jeszcze nie wiesz. Najlepsza jest praktyka. :)

1

Wiem że są takie rzeczy jak logika, logika biznesowa, model biznesowy i masa takich pojęć,
ale nie odnajduję się w tym. Jak to powinno być zrobione? Jak wyglądają profesjonalne aplikacje?
Jak to dzielić?

Nie wiem czy pracowałeś kiedyś komercyjnie, ale jest tak, że jak pracujesz, to co chwila się zmieniają wymagania w projekcie ("nawet na późnym etapie jego rozwoju"), coś, co wczoraj miało kwakać po naciśnięciu ikonki kaczki, jutro już może zostać zmienione i klient sobie zażyczy, żeby miauczało i nie po naciśnięciu przycisku, ale po zalogowaniu użytkownika, ale tylko pod warunkiem, że użytkownik jest kotem.

I teraz tak. Jak nie myślisz o architekturze, całościowym designie, tylko piszesz na żywca, to po każdej malutkiej zmianie wymagań od klienta, okaże się, że trzeba połowę projektu przepisywać żeby zmienić coś z kwakania na miauczenie.

Do tego między innymi właśnie potrzebna jest architektura w projekcie.

Poza tym - jak pracujesz w kilka osób, to też ważne jest to, żeby to co robisz ty, nie konfliktowało się z tym, co robi inny programista* (np. w realnej sytuacji ty mógłbyś implementować kwakanie, miauczenie i inne odgłosy, a już przyciski czy logowanie by implementował ktoś inny). Dobra architektura to ułatwia, zła architektura powoduje konflikty.

I teraz chciałbym was zapytać jak powinna być dobrze zaprojektowana aplikacja, z tym zawsze mam problem.

Powinna być odporna na zmiany założeń. Jeśli klient powie "zamiast kwakania zrób miauczenie", to łatwo to zrobisz, ponieważ projekt będzie wystarczająco elastyczny i poszczególne moduły będą odpowiednio odseparowane, że można będzie je stopniowo przepisywać bez naruszenia całości. **

I na pewno mnóstwo innych rzeczy, ale myślę, że ważniejsze od przyjęcia jakichś teorii na wiarę jest to, żeby wiedzieć dlaczego architektura jest dobra. Żebyś sam mógł ocenić czy dany projekt jest dobrze czy źle zaprojektowany (do tego niestety najlepiej albo popełnić samemu mnóstwo błędów, albo uczestniczyć w paru gównianych projektach - bo dopiero potem będziesz mógł docenić zasady typu DRY czy SOLID).

* być może piszę o rzeczach oczywistych, ale twoje pytanie brzmi trochę jakbyś poczytał coś o wzorcach i teorii, natomiast brak byłoby ci szerszego kontekstu - dlaczego to jest ważne. A przecież nie chodzi o to, żeby zrobić "dobry kod" czy "profesjonalną aplikację", ale o to, żeby rozwiązywać problemy biznesowe w sprawny sposób, i dobrze porozumieć się z innymi programistami za pomocą kodu

*** Ale z drugiej strony tu też można trochę przesadzić i zrobić aplikację zbyt elastyczną, kosztem prostoty (tzw. overengineering), to jest akurat złe.
*

0

@Markuz: dzięki za te sugestie, zainteresuję się tymi książkami.
PHPersów obserwuje.

@elwis: hmm, chyba raczej nie mam aż takich problemów ze zrozumieniem swojego kodu. Bardziej mam taki problem, że gdy piszę kod ciągle zastanawiam się, czy na pewno tą klasę nazwać tak, czy na pewno tą metodę umieścić tu, czy na pewno to ma być tak... Rozumiesz pewnie. I to pewnie przychodzi coraz bardziej z doświadczeniem, dlatego też pytam jak dalej robić, żeby było dobrze.

Wreszcie co do samego kodu: niech go będzie tak mało jak się da, niech nazwy dobrze opisują zmienie i funkcje. Polecam trzymać ograniczenia szerokości linii (do 60-80 znaków) i wcięcia. A poza tym podstawy obiektówki – najlepiej metoda ma jeden (ewentualnie 2) parametr, Jeśli jakieś pole jest używane tylko przez część metod to możliwe, że należy tę klasę podzielić.
O tym mniej więcej myślę, że wiem. Przestrzegam PSR-2, zwracam uwagę aby klasa robiła konkretną rzecz, a nie była do wszystkiego.

@LukeJL: pracuję jako junior PHP. Rozumiem, że aplikacja powinna być odporna na zmiany, ale też jak sam napisałeś nie mogę napisać beznadziejnego kodu, bo potem się w nim pogubię.

Powinna być odporna na zmiany założeń. Jeśli klient powie "zamiast kwakania zrób miauczenie", to łatwo to zrobisz, ponieważ projekt będzie wystarczająco elastyczny i poszczególne moduły będą odpowiednio odseparowane, że można będzie je stopniowo przepisywać bez naruszenia całości. **

Rozumiem, tu też pewnie trzeba dużo praktyki :P

A jak jest panowie czysto od strony kodu z tą logiką biznesową? Piszę sobie np. w Laraverze (tak, wiem, bez hejtów proszę :P) i jak powinienem ułożyć logikę biznesową? Czy to powinno być gdzieś kompletnie wyseparowane? Czy wtedy taka logika ma się odwoływać do bazy danych, czy też kontroler powinien dawać model do logiki, a logika coś tam sobie robić? Napisaliście mi sporo ogólnych wskazówek i za to jestem wdzięczny, ale brakuje mi właśnie takiego praktycznego wytłumaczenia np. jak dobrze wydzielić logikę w aplikacji, aby nie była w kontrolerach.

0

Bardziej mam taki problem, że gdy piszę kod ciągle zastanawiam się, czy na pewno tą klasę nazwać tak,
czy na pewno tą metodę umieścić tu, czy na pewno to ma być tak...

Nazywanie zmiennych to jedna z dwóch trudnych rzeczy w programowaniu* i to raczej tak łatwo nie zniknie, co najwyżej z biegiem czasu możesz wyrobić w sobie intuicję, smak (w sensie gustu), wyczucie konwencji językowych itp.. Albo samemu będziesz mógł uargumentować dlaczego coś powinno być w tym miejscu, a nie w innym.

Tu nie ma jakichś żelaznych zasad, tylko raczej to jest kwestia logicznego uzasadnienia czemu coś powinno tak, a nie inaczej wyglądać.

W necie jest dużo bardziej konkretnych wskazówek (podpowiedzi do wygooglowania: clean code (jest też cała ksiązka Roberta Martina o tym), MVC, SOLID, DRY, YAGNI, (scalable) software architecture, i parę innych fraz do wyszukiwania by się znalazło), ale koniec końców trzeba mieć własny rozum i nauczyć się samemu rozsądzać.

I trzeba mieć wyobraźnię, a jeśli się nie ma, to warto sobie narysować na kartce jakieś rozwiązanie, albo zrobić prosty prototyp i zobaczyć w praktyce czy coś ma sens czy nie ma.

Mam wrażenie, że za dużo razy używasz słowa "powinien", "powinno" itp. To tak nie działa. Raczej to jest coś jak "opłaca się z powodu X / w sytuacji X" / "nie opłaca się z powodu Y/ w sytuacji Y" (np. opłaca się pisać spaghetti kod, jak prototypujesz, albo jak chcesz zrobić coś jak najszybciej, ale się nie opłaca pisać spaghetti kodu, jeśli jakiś projekt masz utrzymywać przez lata). To rachunek korzyści i strat, a nie jakieś dogmaty.

  • "There are only two hard things in Computer Science: cache invalidation and naming things." ;)
0

Hmm, okej. No to biorę się do dalszego pisania, chyba nie ma lepszego sposobu na rozwój ;)
Dzięki za pomoc, panowie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1