Upload
develcz
View
220
Download
4
Embed Size (px)
Citation preview
100 %
Code coverage
Jedinýdnesuznávanýzpůsob,jakmítspolehlivouaplikacibezchyb,je100%pokrytítesty.Žádnáreálnáaplikacetoovšemnesplňujeasnažitseo100%aninemáekonomickýsmysl.
Business logika
Wiring
* nezměřeno vědeckou metodou
Jakztohoven?Nevšechnyzdrojákyjsousirovnyaněcosevyplatítestovatvícaněcomíň.Jákódrozdělujinabusinesslogiku,kteroujedůležitétestovat,awiring(kteréhojevaplikacinadpolovičnívětšina*),kdetestynepotřebujemeaspolehlivostzajistímejinak.
Wiring=boilerplate.Controllery,fasády,vytahovánívýsledkůapřeposíláníjinam-domodelu,došablony.Gettery,settery,přiřazovánídoproperties.Čímsložitějšíarchitektura,tímvícewiringu.
Businesslogika=todůležité,coaplikacedělá.Omezeníhodnot,validace,filtrováníařazení,parsování,počítání,zaokrouhlování.Mělobynanijítpsátrychléunittesty.
Wiringsedátotižzažitýmipostupytestovatpouzeintegračně.Integračnítestyjsoupomalé,křehkéaneradjepíšu.Pokudbychomnawiringpsaliunittesty,takbychommuselipsátspoustumockůatotakyneníideální.Testysealeuwiringudajínahraditpořádnýmitypy.
Stringly–typed code
function foo(string $id, string $name, string $email, string $directory, string $filename, string $address, string $price, string $date ) { }
Pokudněkdonepíšesilnětypovanýkód,taktovypadánějaktakhle.Všechnojestring,případnějinéskalárnítypy.Pokudsiodmyslímetypehintyúplně,můženámvšudedorazitnull,cožznamenádalšíkontrolyamožnéchybynavíc.
Strongly–typed codefunction foo( Email $email, SplFileInfo $directory, Address $address, Money $price, DateTimeImmutable $date): FooBar { }
Coznamenápoužívatsilnétypy?Využívatnavšechnoconejpřesnějšítyp,objekt.Cotímzískám?Správnýobjektmůževzniknoutjediněkonzistentníazvalidovaný.Typehintemříkám,cojedinělzedometodypředat.Avneposlednířadě,vím,codanýobjektdokáže,pohledemnajehometody.Anezapomeňmenaconejpřesnějšíreturntypehinty.
Stringly–typed code
$container->get('fooService')->doFoo();
Zastringy-typedkódnepovažujipouzereprezentacivšehojakostringů,alejakékoliodkazovánínazákladěmagickýchstringů.Ažpřiběhuprogramumůžuzjistit,žepožadovanáservisaneexistuje.
Strongly–typed code
/** @var FooService */private $fooService;
…
$this->fooService->doFoo();
Mnohemlepšíjevyžádatsiservisupřeskonstruktorstypehintem,čímžzajistímainformujivývojáře/IDE/statickýanalyzátorotom,covdanémparametruapropertyje.ProtorádpoužívámDIivcontrollerech,protožesepřikompilacikontejnerudozvím,jestlijevšeOK.
Nadužívání polí
function foo(array $values) { … $values['name'] … }
Spořádnýmitypehintynelzemetoduzavolatšpatně,alevpolivždymůžechybětdůležitýklíč.Atakynevímetypyhodnotjednotlivýchklíčů(pokudsemezisebouliší).
Pole jako seznam hodnot ✅
/** * @param User[] $users */ function foo(array $users) { foreach ($users as $user) { } }
Použítpolejakokolekcihodnotstejnéhotypu,nadkterouiteruji,jevpořádku.Vtétoukázcesimohubýtjistýtím,cobudev$user.
"Umím zpracovat cokoli"/** * @param array|string $values */ function foo($values) { if (is_array($values)) { … } else { … } }
Metoda,copřijímávícerůznýchtypů,znamená,žemusímenapsatif-složitějšíkód,vícevětvíktestování.
function foo(array $values) { … }
function bar(string $value) { … }
"Umím zpracovat jeden typ"
Přitommůžemenapsatdvěfunkce,kterépřijímajíkonkrétnítypazkaždéhomístazavolattusprávnou.Tosaméplatípronávratovétypy-vždyvracetjedenkonkrétnítyp.
Boolean parameteryfunction foo($values, bool $force) { if ($force) { … } else { … } }
Booleanparametrvětšinouznamená,žemetodadělátrochuněcojiného.Opětznamenánapsatifavícevětvíktestování.
foo([1, 2, 3]); forceFoo([1, 2, 3]);
Rozdělení na více metod
Správnéřešenínamístobooleanparametrujeopětrozdělitnavícemetodazrůznýchmístzavolattusprávnou,copotřebuji.
Nullable parametry
function foo($a = null, $b = null, $c = null, $d = null, $e = null, $f = null, $g = null ) { }
Umetodsvětšímmnožstvímnullablečinepovinnýchargumentůvětšinouplatíjenněkterékombinace,např.prvnítřiparametrynenulovéspoluapod.Tonenínijakzanesenédotypovéhosystémuanavíctytokombinaceobvyklevyjadřujírůznéusecasy.Řešení-rozdělenínavícemetodbeznullableparametrů.Výsledek-mnohemrobustnějšíkód.
function foo( string $country, string $currency, string $errorCode )
Výčty – enumy
Pokudnějakýparametrpřijímáomezenýoborhodnot,kterýjepevnědanývkóduaplikace,použitískalárníchtypůnenívhodné,protožehodnotunijakneomezují.
Výčty – enumy
github.com/consistence/consistence
function foo( Country $country, Currency $currency, ErrorCode $errorCode )
Reprezentujtevýčtypomocíobjektů,např.skrzeknihovnuConsistence.Vyjádřítetím,covolajícímusídometodypředat,azajistítevaliditupředanéhodnoty.
ControllerWeak
HTTP request
Strong
ModelControllerHTTP response
Pokudnechátetypyprorůstvašíaplikací,budeceládalekospolehlivější,protožebudeteconejmíňvěcímít"mixed".Typyjsouidůvod,pročrádpoužívámORM.
Zpětná vazba od typů
Nevhodné interfaces
Naimplementovatinterfaceaupůlkymetodvyhazovatvýjimku-porušeníBarbaryLiskov,nevhodnýinterface.Musímenaslouchat,jakýnámkóddáváfeedbackonašichtypech.Pořádnýtypovýsystémjenemilosrdnějšínežtesty,hodnotí,covšelzeněkampředat,nejento,jakévstupyjsmeotestovali.
Zpětná vazba od typů
Využívání informace, která není v typech
Pokudněconenízanesenédotypůajendíkypředchozíkontrolečiproprietárnímznalostemvím,žemizvolanémetodypřijdenějakákonkrétnítřída,kteránenívtypehintu.
Statická analýza 🔎
Statickýanalýzahledáchybyvkódu,anižbyhospouštěla,pouzezkoumánímzdrojáků.Zkontroluje,žeaplikacenespadnenaněčemnedefinovaném,ževšudepředávámsprávnétypy,ževracím,cojsemslíbilatd.
První spuštění
• Parse errory • Třídy, které nejdou vůbec načíst • Špatně nastavený autoloading
Projekt,kterýjejižnějakoudobuvyvíjenbezstatickéanalýzy,naakumulujesoubory,kterétřebaaninejdounačíst,takžesenedivte,kdyžtakovéPHPStanuvásnajde.
Levely v PHPStanu
$%&'()
Abychomezilmnožstvíchyb,kteréPHPStanponainstalovánízačnehlásit,zavedljsemumělélevely.Začnětehopoužívatnalevelu0aopravtetěchpárchyb,abystemělizelenýbuild.Aažbudetemítpříštěčas,navyštelevelaopravtedalšíchyby.
if ($foo instanceof Foo)
catch (FooException $e)
Foo::class
function foo(Bar $bar)
PHPsamotnémunevadí,pokudsevtěchtopřípadechodkazujetenaneexistujícítřídy.PHPStantakovépřípadynajdeadonutívásjeopravit.
Foo::NONEXISTENT_CONSTANT
Foo::$nonexistentProperty
$this->nonexistentProperty
$this->nonexistentMethod()
nonexistentFunction()
Na vyšších levelech• Nejen na $this
• Předávané typy, nejen počty • Návratové hodnoty • Nedefinované proměnné • …a řada dalších kontrol
PHPStannalevelu0hledáchybynastatickýchvoláníchana$this.Tamsimůžebýtjistýtypem.Navyššíchlevelechhledáchybynavšem,aleužpřitommusíčístaspoléhatsenaphpDocy,vekterýchmůžebýttakéchyba,kterouvámochotněnahlásí.
vs. PHPStan?
PročpoužívatPHPStan,kdyžmámPhpStorm?PHPStanbysteměliintegrovatapouštětvrámciCIbuildu(Travis,TeamCity,Jenkins,GitLabCI…).NevšichnivývojářipoužívajíPhpStormamajíhostejněnakonfigurovaný,anevšimnousikaždéchyby,coIDEpodtrhne.
youtu.be/h5jC7l0-jRI 👉
ProvíceinformacíoPHPStanu,covšechnoumíajakémožnostikonfiguracearozšířenískýtá,mrknětenazáznamzPoslednísoboty.