{"tag":"kod","articles":{"blog\/technology\/czysty-kod-w-praktyce-autoloader-w-php":{"key":"blog\/technology\/czysty-kod-w-praktyce-autoloader-w-php","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:30+02:00","publishedAt":"2015-04-06T19:40:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"czysty-kod-w-praktyce-autoloader-w-php"},"content":{"pl":{"slug":"czysty-kod-w-praktyce-autoloader-w-php","title":"\u201cCzysty kod\u201d w praktyce \u2013 Autoloader w PHP","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAkCAYAAAB8DZEQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHFUlEQVRIibWWy49dRxHGf9Xd55z7vnfGM\/Z4cCY2xA62ZBCWsyCOxQKRVaygOJHYskAsEH8AOzbAEikII3ZsvGHBBqRIYYEwSBYQSHBisLHj1\/jaM+N53vd5dBeLM7Fn\/AhCiE86On1Kp+urqq6uKnHfeFt1bQkzfxB\/7zbUWojPkFobTSpgE0gzUAURGG5Sfe8c4jPqtRpplpEXBc4YojgiiWI2+30qSUy6vc\/p\/euEpEkoBDnyEhiLOodmOYigkxSptAihJJHWDNmRV4mv\/IajR16gWqmQZhmD0Yg7i3c5+\/oZ7i8tAdC9v8Sly\/9A3LfPq8Yt1FoIigSPisEYwYtgfMCrlp4AxhjwGebBDbQUIKqAAApphsQRr37xAFfvbXH7+m2cDlK0mqG2VEgcEbWraJbjJxmSROyzMC4C3lqsKhEVsr2HUe8ZiAFguuKw1qJZjrOGcXMGpnr4juDoLyNBMTN7UVNu8MMx6gNUYqoGXOyYqQpYQ+6VucQyzDz9UcqgPwExNCJHM7aMKxH1imNrbcDKMMM0azgabUJrD7VKzELFEDYHdG3MkdkW66mnHRuSakwalPupJzfKnSB4DCGK6DSF4ANDHxjnQjCG9VFBOslx1hJZg1NiJMuZiuvkvTG16RbzCHFkmbEGDcok8wRnEQVnDWmAQoSaM4wzaMSOXh4woUzAQVZgnaXICsQ5XNxukC4u0vU59dlpkt6EOLIspgGngbo15AK9AM0kouospvBsjQscSiQQO0MQgxhhmHmMCM5ZPKCbE0x26QLR84eQ6SmGmccHJbOWPARGQRn7gPdKoeBDQADvA5rm6CRHjGGEYK2h4gyRAQ0BP5ogaY5WEwyHThKiGIwgkxStJhRFwOcFVaCKoqoQFFXwWUHIPSioM6gRYiDNCjaGGUXmCapIHKGALq\/iSDOCgq71kHaDce6ZFaVai7F5wUaudKoRFcBZYeADMcpsxZIAq5knUmXWCRpgrLA5yrGRo3AG027iIEdvfowe+hzGe4os455XNPEYlCCG8SiDOEJ9gYiAArkHVQRY8xAmGRoUC9gkIss9OhzB+jqOtbtw9BSSe0LwSF5AFCFrGzDV5qUDDb51aoEPV0a8MFOjGlsu3esTGeFQp8LaOGc4zjn92Sku3+vxzrV1vnKow48u3EGLgOl0MCR1zGgC1sBwBJ1WaWnICCFwtO04\/5cuP7l4l6FX3v79LU4caNFJLO2q43K3x7kLN7m9PuIHv7vFD197kSvdHloENMvQfh\/HaJNggdX7aKONpiniU3ARMpqg6YTaMOd5zZm2cHV9zB9vbPCvpT7v3drg3Nlj\/LO7hRQFk5VNLl9b5td\/uIqiUIxhsoWVhRPf5+b7EEUYiSFLYfVOWeKDZ2VpjTMn9rPQdARjaPiCq0s9ltf6vPGFOcIk5d3371DHs7K6ii0mXOmu47Mhpr8K6QZijn9dw\/Jt5NhpJICONiEdwtxhJB2BceAq6KQPU\/NQiaAINOtVvnzyGNPTbaxA4hQxMXc\/vk67EfPLn\/4Mam2kGOL0yp9gahb92ztoow3DHtRbsLaI5ilUalDkpYd79kEI4BxUEw6ffYVrf77I9NwcqRUa07Nc+tUvePnNN9H71yF4KFIcGmB9pewXw37ZEwY9SnzSJ7ax9eDhUmf3cO3Cb5man2d6bh93\/v5Xqo0Gh459HmdtaSyAAZFon6rKkwrLlrRDtqMxAcY52rN7sVHEzMIC436fraUlOvPzrC0u0l9dLXeL4ngm5Bnf5bsSOb526ksYEbZ6PUyzw6AV0W61eBApFx+sPtzinlSyG85arBVAMEYIIeCDUqtVGA4GLCx8hjxPmZmZpttdYmZPh\/F4vFvH7tA8idOvnOS73\/km\/X4fYyzLy8t8+NEVTp9+mU67Sbfb5fjxo9RrVfI854MPPqLeqLNT7\/aZPDtoRgwilJMKoFpWY4SyjsHDcUmAELSsvqqAIvLQk6cdfGlJUN02KOyQCw+ZdkXi8SQp9bptf0BMeQeeCN3TyXe\/H5fvXpfjyVffglOvlWS6bYHuXPPoe6d818Nj60eelWey8CJsrUJrqrSgUod0BHkOSRWyCRhTeitSPiGAi8B72HgAvU2eBhHdJgnC1FST2ZkOaZpRr1VJ07Ts5aokSYL3Aecsw9GYdqvB+kaPpeW1MpgiqAaedka7SA4e3M\/CgX0kSYwq5HlOUXji2JHEMS5yDPpDKtUKRVEwmUyo1+uEEOh2V5ikOSLC4t0lsrx4uidiSgOsNYRQDlDGSJlEqrjI4QtP0IBsW6zbqWutoch9OT+H3cnwiORT7sn\/CpFPsus\/\/\/pfK3\/uwH7arSbwkGR38XsyFR8n\/JSUFYsA3\/vxOc688TrwRO161iXbiadfOADiGsw8h6YD3j3\/c65fu1FSm3huu5\/8fyCi\/BsCrKXMv6hFYQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAkCAYAAAB8DZEQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHFUlEQVRIibWWy49dRxHGf9Xd55z7vnfGM\/Z4cCY2xA62ZBCWsyCOxQKRVaygOJHYskAsEH8AOzbAEikII3ZsvGHBBqRIYYEwSBYQSHBisLHj1\/jaM+N53vd5dBeLM7Fn\/AhCiE86On1Kp+urqq6uKnHfeFt1bQkzfxB\/7zbUWojPkFobTSpgE0gzUAURGG5Sfe8c4jPqtRpplpEXBc4YojgiiWI2+30qSUy6vc\/p\/euEpEkoBDnyEhiLOodmOYigkxSptAihJJHWDNmRV4mv\/IajR16gWqmQZhmD0Yg7i3c5+\/oZ7i8tAdC9v8Sly\/9A3LfPq8Yt1FoIigSPisEYwYtgfMCrlp4AxhjwGebBDbQUIKqAAApphsQRr37xAFfvbXH7+m2cDlK0mqG2VEgcEbWraJbjJxmSROyzMC4C3lqsKhEVsr2HUe8ZiAFguuKw1qJZjrOGcXMGpnr4juDoLyNBMTN7UVNu8MMx6gNUYqoGXOyYqQpYQ+6VucQyzDz9UcqgPwExNCJHM7aMKxH1imNrbcDKMMM0azgabUJrD7VKzELFEDYHdG3MkdkW66mnHRuSakwalPupJzfKnSB4DCGK6DSF4ANDHxjnQjCG9VFBOslx1hJZg1NiJMuZiuvkvTG16RbzCHFkmbEGDcok8wRnEQVnDWmAQoSaM4wzaMSOXh4woUzAQVZgnaXICsQ5XNxukC4u0vU59dlpkt6EOLIspgGngbo15AK9AM0kouospvBsjQscSiQQO0MQgxhhmHmMCM5ZPKCbE0x26QLR84eQ6SmGmccHJbOWPARGQRn7gPdKoeBDQADvA5rm6CRHjGGEYK2h4gyRAQ0BP5ogaY5WEwyHThKiGIwgkxStJhRFwOcFVaCKoqoQFFXwWUHIPSioM6gRYiDNCjaGGUXmCapIHKGALq\/iSDOCgq71kHaDce6ZFaVai7F5wUaudKoRFcBZYeADMcpsxZIAq5knUmXWCRpgrLA5yrGRo3AG027iIEdvfowe+hzGe4os455XNPEYlCCG8SiDOEJ9gYiAArkHVQRY8xAmGRoUC9gkIss9OhzB+jqOtbtw9BSSe0LwSF5AFCFrGzDV5qUDDb51aoEPV0a8MFOjGlsu3esTGeFQp8LaOGc4zjn92Sku3+vxzrV1vnKow48u3EGLgOl0MCR1zGgC1sBwBJ1WaWnICCFwtO04\/5cuP7l4l6FX3v79LU4caNFJLO2q43K3x7kLN7m9PuIHv7vFD197kSvdHloENMvQfh\/HaJNggdX7aKONpiniU3ARMpqg6YTaMOd5zZm2cHV9zB9vbPCvpT7v3drg3Nlj\/LO7hRQFk5VNLl9b5td\/uIqiUIxhsoWVhRPf5+b7EEUYiSFLYfVOWeKDZ2VpjTMn9rPQdARjaPiCq0s9ltf6vPGFOcIk5d3371DHs7K6ii0mXOmu47Mhpr8K6QZijn9dw\/Jt5NhpJICONiEdwtxhJB2BceAq6KQPU\/NQiaAINOtVvnzyGNPTbaxA4hQxMXc\/vk67EfPLn\/4Mam2kGOL0yp9gahb92ztoow3DHtRbsLaI5ilUalDkpYd79kEI4BxUEw6ffYVrf77I9NwcqRUa07Nc+tUvePnNN9H71yF4KFIcGmB9pewXw37ZEwY9SnzSJ7ax9eDhUmf3cO3Cb5man2d6bh93\/v5Xqo0Gh459HmdtaSyAAZFon6rKkwrLlrRDtqMxAcY52rN7sVHEzMIC436fraUlOvPzrC0u0l9dLXeL4ngm5Bnf5bsSOb526ksYEbZ6PUyzw6AV0W61eBApFx+sPtzinlSyG85arBVAMEYIIeCDUqtVGA4GLCx8hjxPmZmZpttdYmZPh\/F4vFvH7tA8idOvnOS73\/km\/X4fYyzLy8t8+NEVTp9+mU67Sbfb5fjxo9RrVfI854MPPqLeqLNT7\/aZPDtoRgwilJMKoFpWY4SyjsHDcUmAELSsvqqAIvLQk6cdfGlJUN02KOyQCw+ZdkXi8SQp9bptf0BMeQeeCN3TyXe\/H5fvXpfjyVffglOvlWS6bYHuXPPoe6d818Nj60eelWey8CJsrUJrqrSgUod0BHkOSRWyCRhTeitSPiGAi8B72HgAvU2eBhHdJgnC1FST2ZkOaZpRr1VJ07Ts5aokSYL3Aecsw9GYdqvB+kaPpeW1MpgiqAaedka7SA4e3M\/CgX0kSYwq5HlOUXji2JHEMS5yDPpDKtUKRVEwmUyo1+uEEOh2V5ikOSLC4t0lsrx4uidiSgOsNYRQDlDGSJlEqrjI4QtP0IBsW6zbqWutoch9OT+H3cnwiORT7sn\/CpFPsus\/\/\/pfK3\/uwH7arSbwkGR38XsyFR8n\/JSUFYsA3\/vxOc688TrwRO161iXbiadfOADiGsw8h6YD3j3\/c65fu1FSm3huu5\/8fyCi\/BsCrKXMv6hFYQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E\n\u003Cp\u003ETylko najpierw kr\u00f3tki wst\u0119p, co to w og\u00f3le jest \u201cautoloader\u201d. Ot\u00f3\u017c: przy ka\u017cdym \u017c\u0105daniu do serwera uruchamiana jest nowa instancja interpretera PHP. Aby nie musia\u0142 on \u0142adowa\u0107 wszystkich plik\u00f3w .php obecnych w projekcie (a potrafi\u0105 ich by\u0107 tysi\u0105ce), lecz tylko te, z kt\u00f3rych akurat w tym \u017c\u0105daniu skorzysta, u\u017cywany jest mechanizm auto\u0142adowania. Dzia\u0142a to tak, \u017ce kiedy interpreter PHP trafi na u\u017cycie klasy, kt\u00f3rej nie zna, odpyta o ni\u0105 po kolei autoloadery, kt\u00f3re ma zarejestrowane. Je\u015bli kt\u00f3ry\u015b z nich zwr\u00f3ci true, oznacza to, \u017ce znalaz\u0142 on plik, w kt\u00f3rym dana klasa powinna si\u0119 znajdowa\u0107, i do\u0142\u0105czy\u0142 go. W przeciwnym razie interpreter pyta kolejnego autoloadera w kolejce, a dopiero je\u015bli wszystkie zawiod\u0105 \u2013 wyrzuca fatal error \u201cClass not found\u201d.\u003C\/p\u003E\n\u003Cp\u003ENapisa\u0142em sobie kiedy\u015b ma\u0142\u0105 klas\u0119 autoloadera, a raczej poprzerabia\u0142em jak\u0105\u015b znalezion\u0105 na necie. Wygl\u0105da\u0142a tak:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EAutoloader\u003C\/span\u003E \u003C\/span\u003E{\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $namespace;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $path;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $valid = \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($namespace, $path = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\u0027\u003C\/span\u003E)\u003C\/span\u003E \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace = $namespace;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path = $path;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;valid = \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eautoload\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ is this autoloader responsible for that particular class?\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (substr($className,\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E,strlen(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace)) === \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace) {\n            $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path . str_replace(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E, ltrim( $className, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E)) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.php\u0027\u003C\/span\u003E;\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n            } \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E {\n                \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ if not straightforward, maybe try \u0022common\u0022 class files\u003C\/span\u003E\n                \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ eg. \u0022Exceptions\u0022 for \u0022NotFoundException\u0022;\u003C\/span\u003E\n                $slashPos = strrpos($className,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E;\n                $base = substr($className,\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E,$slashPos);\n                $classPure = substr($className,$slashPos);\n                preg_match_all(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/(?:^|[A-Z])[a-z]+\/\u0027\u003C\/span\u003E,$classPure,$matches);\n                $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path . str_replace(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E, ltrim( $base . end($matches[\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E]) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027s\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E)) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.php\u0027\u003C\/span\u003E;\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n                    \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n                    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n                } \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E {\n                    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ damn, maybe other autoloaders will find something\u003C\/span\u003E\n                }\n            }\n        } \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ no, let the other autoloaders handle that\u003C\/span\u003E\n        }\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eregister\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;valid) {\n            spl_autoload_register(\u003Cspan class=\u0022hljs-keyword\u0022\u003Earray\u003C\/span\u003E(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027autoload\u0027\u003C\/span\u003E));\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;valid = \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/in order not to register it twice\u003C\/span\u003E\n        }\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EPrzyk\u0142adowe u\u017cycie mojego autoloadera wygl\u0105da nast\u0119puj\u0105co:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n$autoloader = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Autoloader(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Micrus\\\\\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-keyword\u0022\u003E__DIR__\u003C\/span\u003E . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/vendor\/\u0027\u003C\/span\u003E);\n$autoloader-\u0026gt;register();\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETworzymy nowy autoloader maj\u0105cy obs\u0142ugiwa\u0107 wszystkie klasy w przestrzeni nazw \u201cMicrus\u201d i szukaj\u0105cy ich w katalogu \u201cvendor\u201d, gdzie klasy s\u0105 umieszczone w podfolderach zgodnie ze swoj\u0105 przestrzeni\u0105 nazw. Oznacza to, \u017ce je\u015bli gdzie\u015b w kodzie b\u0119dziemy chcieli stworzy\u0107 nowy obiekt klasy \u003Ccode\u003EMicrus\\Foo\\Bar\\MyClass\u003C\/code\u003E, to powinna si\u0119 ona znajdowa\u0107 w pliku \u003Ccode\u003E\/vendor\/Micrus\/Foo\/Bar\/MyClass.php\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EDo tego dochodzi jeszcze pewien ma\u0142y feature (niezgodny z \u003Ca href=\u0022http:\/\/www.php-fig.org\/psr\/psr-4\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PSR-4\u003C\/a\u003E). Ot\u00f3\u017c je\u015bli chcemy zgrupowa\u0107 kilka podobnych klas w jednym pliku, mo\u017cemy zrobi\u0107 to w bardzo prosty spos\u00f3b. Mamy na przyk\u0142ad klasy wyj\u0105tk\u00f3w, kt\u00f3re potrafi\u0105 by\u0107 naprawd\u0119 malutkie i czasem niewygodnie jest rozbija\u0107 je na osobne pliki. Nazywamy je wszystkie u\u017cywaj\u0105c \u003Ca href=\u0022http:\/\/pl.wikipedia.org\/wiki\/PascalCase\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PascalCase\u003C\/a\u003E z \u201cException\u201d jako ostatnim s\u0142owem i umieszczamy w pliku \u003Ccode\u003EExceptions.php\u003C\/code\u003E (z dodatkowym -s). M\u00f3j autoloader obs\u0142u\u017cy taki przypadek.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Enamespace\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EMicrus\u003C\/span\u003E;\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EConfigFileException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ENotFoundException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprotected\u003C\/span\u003E $code = \u003Cspan class=\u0022hljs-number\u0022\u003E404\u003C\/span\u003E; }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ECacheException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ERouteNotFoundException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprotected\u003C\/span\u003E $code = \u003Cspan class=\u0022hljs-number\u0022\u003E404\u003C\/span\u003E; }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EInvalidArgumentException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EUnauthorisedException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprotected\u003C\/span\u003E $code = \u003Cspan class=\u0022hljs-number\u0022\u003E403\u003C\/span\u003E; }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EArgvException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EDatabaseException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EKod autoloadera nie wygl\u0105da \u017ale (a przynajmniej widzia\u0142em gorsze). Ale pierwsze spojrzenie na metod\u0119 \u201cautoload\u201d potrafi przerazi\u0107. Jest okropnie nieczytelna, mimo \u017ce komentarze obja\u015bniaj\u0105 jej dzia\u0142anie. Potrzeba troch\u0119 wysi\u0142ku, \u017ceby dowiedzie\u0107 si\u0119, co konkretnie robi.\u003C\/p\u003E\n\u003Cp\u003EWszyscy ucz\u0105, zeby pisa\u0107 komentarze do kodu. Du\u017co komentarzy. Nawet je\u015bli wydaje ci si\u0119 to bezsensowne, bo przecie\u017c rozumiesz, co napisa\u0142e\u015b, to musisz bra\u0107 pod uwag\u0119, \u017ce je\u015bli kod trafi w r\u0119ce kogo innego, albo i ty sam zajrzysz do niego rok czy dwa p\u00f3\u017aniej, to rozszyfrowanie go mo\u017ce ju\u017c nie by\u0107 takie proste.\u003C\/p\u003E\n\u003Cp\u003EMartin natomiast uczy czego innego. Dobry kod wymaga tylko znikomej liczby komentarzy. Je\u015bli ich potrzebujesz, by zrozumie\u0107, co si\u0119 dzieje, znaczy \u017ce kod jest nieczytelny. No i komentarze s\u0105 w pewnym sensie \u003Cem\u003Eniebezpieczne\u003C\/em\u003E: zapominamy je pisa\u0107, zapominamy je aktualizowa\u0107, boimy si\u0119 je usuwa\u0107, szybko trac\u0105 na wa\u017cno\u015bci...\u003C\/p\u003E\n\u003Cp\u003ESp\u00f3jrzcie na kod autoloadera po serii poprawek:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EAutoloader\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $namespace;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $path;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $registered = \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($namespace, $path = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.\u0027\u003C\/span\u003E)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;addEndingSlash($namespace, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;addEndingSlash($path, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E);\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EaddEndingSlash\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($word, $slash = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $lastCharacter = substr($word, \u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $lastCharacter == $slash ? $word : $word . $slash;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eautoload\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;isNotResponsibleForClass($className)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n        }\n\n        $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;classNameToFilePath($className);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n        }\n\n        $groupName = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;classNameToGroupName($className);\n        $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;classNameToFilePath($groupName);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n        }\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EisNotResponsibleForClass\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E substr($className, \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E, strlen(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace)) !== \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EclassNameToFilePath\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path . str_replace(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E, ltrim( $className, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E)) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.php\u0027\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EclassNameToGroupName\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $slashPos = strrpos($className,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E;\n        $base = substr($className,\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E,$slashPos);\n        $classPure = substr($className,$slashPos);\n        preg_match_all(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/(?:^|[A-Z])[a-z]+\/\u0027\u003C\/span\u003E,$classPure,$matches);\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $base . end($matches[\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E]) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027s\u0027\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eregister\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;registered) { \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; }\n        spl_autoload_register(\u003Cspan class=\u0022hljs-keyword\u0022\u003Earray\u003C\/span\u003E(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027autoload\u0027\u003C\/span\u003E));\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;registered = \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWystarczy zerkn\u0105\u0107 na funkcj\u0119 autoload, \u017ceby wiedzie\u0107, co robi. Ba, nawet nie trzeba zna\u0107 \u017cadnego j\u0119zyka programowania! To\u017c to niemal czysty angielski: \u201cif this is not responsible for class \u2018class name\u2019, return false\u201d. Nie mamy poj\u0119cia \u003Cem\u003Ejak\u003C\/em\u003E funkcja to robi, ale wida\u0107 jak na d\u0142oni \u003Cem\u003Eco\u003C\/em\u003E takiego wykonuje.\u003C\/p\u003E\n\u003Cp\u003E\u003Cem\u003E\u201cJak\u201d\u003C\/em\u003E natomiast znajduje si\u0119 w osobnych, prywatnych metodach. Rozdzielili\u015bmy zatem od siebie r\u00f3\u017cne \u003Cem\u003Ewarstwy abstrakcji\u003C\/em\u003E, kt\u00f3re wcze\u015bniej by\u0142y zlane w jedn\u0105, brzydk\u0105 funkcj\u0119. Bo je\u015bli kto\u015b zajrzy do naszego kodu, to najprawdopodobniej nie b\u0119dzie potrzebowa\u0142 znajomo\u015bci wszystkiego, co tam naskrobali\u015bmy, lecz przyjdzie z jakim\u015b jednym konkretnym zadaniem: \u201cogarn\u0105\u0107 jak mniej wi\u0119cej dzia\u0142a ten autoloader\u201d, \u201czmieni\u0107 format nazwy \u2018zbiorowego pliku\u2019\u201d, \u201czmieni\u0107 kolejno\u015b\u0107 sprawdzania potencjalnych plik\u00f3w\u201d itp. I dlatego rozdzielenie warstw abstrakcji tak bardzo upro\u015bci mu prac\u0119.\u003C\/p\u003E\n\u003Cp\u003ENa pierwszy rzut oka wydawa\u0142oby si\u0119 sensowniejsze stworzenie metody isResponsibleForClass zamiast jej negacji \u2013 isNotResponsibleForClass. Kto normalny pyta\u0142by klas\u0119, czy \u003Cem\u003Enie jest\u003C\/em\u003E za co\u015b odpowiedzialna? Odpowied\u017a \u201ctak, nie jestem\u201d tylko niepotrzebnie by wszystko zagmatwa\u0142a, prawda? No w\u0142a\u015bnie niekoniecznie. U\u017cycie tej metody jest tylko jedno i sprowadza si\u0119 do \u201cje\u015bli nie jeste\u015b za to odpowiedzialna, to daj sobie spok\u00f3j\u201d. Zapisanie tego warunku jako \u003Ccode\u003Eif (!$this-\u0026gt;isResponsibleForClass($className))\u003C\/code\u003E zmniejsza czytelno\u015b\u0107, poniewa\u017c tego wykrzyknika prawie nie wida\u0107. Zawsze zapominamy o wykrzyknikach...\u003C\/p\u003E\n\u003Cp\u003EZanegowanie dopad\u0142o te\u017c zmienn\u0105 \u003Ccode\u003Evalid\u003C\/code\u003E. Zawsze gdy j\u0105 widzia\u0142em, musia\u0142em si\u0119 zastanowi\u0107, po co ona komu. Kiedy niby autoloader staje si\u0119 \u201cinvalid\u201d? A chodzi przecie\u017c o to, \u017ce autoloader mo\u017ce by\u0107 albo \u003Cem\u003Ejeszcze nie zarejestrowany\u003C\/em\u003E, albo \u003Cem\u003Eju\u017c zarejestrowany\u003C\/em\u003E. Czemu wi\u0119c nie zmieni\u0107 nazwy tej w\u0142a\u015bciwo\u015bci na \u003Ccode\u003Eregistered\u003C\/code\u003E? Teraz metoda \u003Ccode\u003Eregister()\u003C\/code\u003E staje si\u0119 bardzo czytelna: \u201cje\u015bli jeste\u015b zarejestrowany, to ju\u017c wi\u0119cej si\u0119 nie rejestruj\u201d.\u003C\/p\u003E\n\u003Cp\u003EBazowy namespace powinien ko\u0144czy\u0107 si\u0119 backslashem, aby unikn\u0105\u0107 takich sytuacji, gdy chcemy na przyk\u0142ad przechwyci\u0107 klasy \u201cJava\/...\u201d, a zgarniemy tak\u017ce i \u201cJavascript\/...\u201d. Dla zachowania jednorodno\u015bci, to samo powinno dotyczy\u0107 drugiego parametru konstruktora (\u015bcie\u017cki do folderu). Ale po co cz\u0142owiekowi, kt\u00f3ry chce u\u017cy\u0107 naszego autoloadera, kaza\u0107 si\u0119 zastanawia\u0107 nad tym, czy wymagamy slasha czy nie? Mo\u017ce lepiej po prostu sprawd\u017amy, czy slash jest na ko\u0144cu parametru, i doklejmy go, je\u015bli nie? Dodanie metody \u003Ccode\u003EaddEndingSlash\u003C\/code\u003E sprawi\u0142o, \u017ce nie tylko sama klasa jest prostsza, ale tak\u017ce i jej u\u017cycie na zewn\u0105trz.\u003C\/p\u003E\n\u003Cp\u003ETym oto sposobem w nowym kodzie jest zdecydowanie mniej zagnie\u017cd\u017ce\u0144, metody s\u0105 kr\u00f3tsze, a ka\u017cda zajmuje si\u0119 dok\u0142adnie jedn\u0105 rzecz\u0105 na jednym poziomie abstrakcji.\u003C\/p\u003E\n\u003Cp\u003EI jak? Kt\u00f3r\u0105 wersj\u0119 wolicie? Kt\u00f3ra nie marnuje czasu programisty pr\u00f3buj\u0105cego j\u0105 zrozumie\u0107?\u003C\/p\u003E\n\u003Cp\u003E\u201cCzysty kod\u201d warto przeczyta\u0107, warto do niego wraca\u0107 i \u2013 przede wszystkim \u2013 warto stosowa\u0107 si\u0119 do zawartych w nim rad.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["czytelno\u015b\u0107","informatyka","kod","ksi\u0105\u017cka","php","programowanie"],"hasMore":true,"image":"https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022341.70731707317\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022341.70731707317\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E\n\u003Cp\u003ETylko najpierw kr\u00f3tki wst\u0119p, co to w og\u00f3le jest \u201cautoloader\u201d. Ot\u00f3\u017c: przy ka\u017cdym \u017c\u0105daniu do serwera uruchamiana jest nowa instancja interpretera PHP. Aby nie musia\u0142 on \u0142adowa\u0107 wszystkich plik\u00f3w .php obecnych w projekcie (a potrafi\u0105 ich by\u0107 tysi\u0105ce), lecz tylko te, z kt\u00f3rych akurat w tym \u017c\u0105daniu skorzysta, u\u017cywany jest mechanizm auto\u0142adowania. Dzia\u0142a to tak, \u017ce kiedy interpreter PHP trafi na u\u017cycie klasy, kt\u00f3rej nie zna, odpyta o ni\u0105 po kolei autoloadery, kt\u00f3re ma zarejestrowane. Je\u015bli kt\u00f3ry\u015b z nich zwr\u00f3ci true, oznacza to, \u017ce znalaz\u0142 on plik, w kt\u00f3rym dana klasa powinna si\u0119 znajdowa\u0107, i do\u0142\u0105czy\u0142 go. W przeciwnym razie interpreter pyta kolejnego autoloadera w kolejce, a dopiero je\u015bli wszystkie zawiod\u0105 \u2013 wyrzuca fatal error \u201cClass not found\u201d.\u003C\/p\u003E\n\u003Cp\u003ENapisa\u0142em sobie kiedy\u015b ma\u0142\u0105 klas\u0119 autoloadera, a raczej poprzerabia\u0142em jak\u0105\u015b znalezion\u0105 na necie. Wygl\u0105da\u0142a tak:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?php\n\nclass Autoloader {\n\n    private $namespace;\n\n    private $path;\n\n    private $valid = false;\n\n    public function __construct($namespace, $path = \u0027\u0027) {\n        $this-\u0026gt;namespace = $namespace;\n        $this-\u0026gt;path = $path;\n        $this-\u0026gt;valid = true;\n    }\n\n    public function autoload($className) {\n        \/\/ is this autoloader responsible for that particular class?\n        if (substr($className,0,strlen($this-\u0026gt;namespace)) === $this-\u0026gt;namespace) {\n            $path = $this-\u0026gt;path . str_replace(\u0027\\\\\u0027,\u0027\/\u0027, ltrim( $className, \u0027\\\\\u0027)) . \u0027.php\u0027;\n            if (file_exists($path)) {\n                require_once($path);\n                return true;\n            } else {\n                \/\/ if not straightforward, maybe try \u0022common\u0022 class files\n                \/\/ eg. \u0022Exceptions\u0022 for \u0022NotFoundException\u0022;\n                $slashPos = strrpos($className,\u0027\\\\\u0027,-1) + 1;\n                $base = substr($className,0,$slashPos);\n                $classPure = substr($className,$slashPos);\n                preg_match_all(\u0027\/(?:^|[A-Z])[a-z]+\/\u0027,$classPure,$matches);\n                $path = $this-\u0026gt;path . str_replace(\u0027\\\\\u0027,\u0027\/\u0027, ltrim( $base . end($matches[0]) . \u0027s\u0027, \u0027\\\\\u0027)) . \u0027.php\u0027;\n                if (file_exists($path)) {\n                    require_once($path);\n                    return true;\n                } else {\n                    return false; \/\/ damn, maybe other autoloaders will find something\n                }\n            }\n        } else {\n            return false; \/\/ no, let the other autoloaders handle that\n        }\n    }\n\n    public function register() {\n        if ($this-\u0026gt;valid) {\n            spl_autoload_register(array($this, \u0027autoload\u0027));\n            $this-\u0026gt;valid = false; \/\/in order not to register it twice\n        }\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EPrzyk\u0142adowe u\u017cycie mojego autoloadera wygl\u0105da nast\u0119puj\u0105co:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?php\n$autoloader = new Autoloader(\u0027Micrus\\\\\u0027, __DIR__ . \u0027\/vendor\/\u0027);\n$autoloader-\u0026gt;register();\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETworzymy nowy autoloader maj\u0105cy obs\u0142ugiwa\u0107 wszystkie klasy w przestrzeni nazw \u201cMicrus\u201d i szukaj\u0105cy ich w katalogu \u201cvendor\u201d, gdzie klasy s\u0105 umieszczone w podfolderach zgodnie ze swoj\u0105 przestrzeni\u0105 nazw. Oznacza to, \u017ce je\u015bli gdzie\u015b w kodzie b\u0119dziemy chcieli stworzy\u0107 nowy obiekt klasy \u003Ccode\u003EMicrus\\Foo\\Bar\\MyClass\u003C\/code\u003E, to powinna si\u0119 ona znajdowa\u0107 w pliku \u003Ccode\u003E\/vendor\/Micrus\/Foo\/Bar\/MyClass.php\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EDo tego dochodzi jeszcze pewien ma\u0142y feature (niezgodny z \u003Ca href=\u0022http:\/\/www.php-fig.org\/psr\/psr-4\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PSR-4\u003C\/a\u003E). Ot\u00f3\u017c je\u015bli chcemy zgrupowa\u0107 kilka podobnych klas w jednym pliku, mo\u017cemy zrobi\u0107 to w bardzo prosty spos\u00f3b. Mamy na przyk\u0142ad klasy wyj\u0105tk\u00f3w, kt\u00f3re potrafi\u0105 by\u0107 naprawd\u0119 malutkie i czasem niewygodnie jest rozbija\u0107 je na osobne pliki. Nazywamy je wszystkie u\u017cywaj\u0105c \u003Ca href=\u0022http:\/\/pl.wikipedia.org\/wiki\/PascalCase\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PascalCase\u003C\/a\u003E z \u201cException\u201d jako ostatnim s\u0142owem i umieszczamy w pliku \u003Ccode\u003EExceptions.php\u003C\/code\u003E (z dodatkowym -s). M\u00f3j autoloader obs\u0142u\u017cy taki przypadek.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\u0026lt;?php\nnamespace Micrus;\n\nclass ConfigFileException extends \\Exception { }\nclass NotFoundException extends \\Exception { protected $code = 404; }\nclass CacheException extends \\Exception { }\nclass RouteNotFoundException extends \\Exception { protected $code = 404; }\nclass InvalidArgumentException extends \\Exception { }\nclass UnauthorisedException extends \\Exception { protected $code = 403; }\nclass ArgvException extends \\Exception { }\nclass DatabaseException extends \\Exception { }\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EKod autoloadera nie wygl\u0105da \u017ale (a przynajmniej widzia\u0142em gorsze). Ale pierwsze spojrzenie na metod\u0119 \u201cautoload\u201d potrafi przerazi\u0107. Jest okropnie nieczytelna, mimo \u017ce komentarze obja\u015bniaj\u0105 jej dzia\u0142anie. Potrzeba troch\u0119 wysi\u0142ku, \u017ceby dowiedzie\u0107 si\u0119, co konkretnie robi.\u003C\/p\u003E\n\u003Cp\u003EWszyscy ucz\u0105, zeby pisa\u0107 komentarze do kodu. Du\u017co komentarzy. Nawet je\u015bli wydaje ci si\u0119 to bezsensowne, bo przecie\u017c rozumiesz, co napisa\u0142e\u015b, to musisz bra\u0107 pod uwag\u0119, \u017ce je\u015bli kod trafi w r\u0119ce kogo innego, albo i ty sam zajrzysz do niego rok czy dwa p\u00f3\u017aniej, to rozszyfrowanie go mo\u017ce ju\u017c nie by\u0107 takie proste.\u003C\/p\u003E\n\u003Cp\u003EMartin natomiast uczy czego innego. Dobry kod wymaga tylko znikomej liczby komentarzy. Je\u015bli ich potrzebujesz, by zrozumie\u0107, co si\u0119 dzieje, znaczy \u017ce kod jest nieczytelny. No i komentarze s\u0105 w pewnym sensie \u003Cem\u003Eniebezpieczne\u003C\/em\u003E: zapominamy je pisa\u0107, zapominamy je aktualizowa\u0107, boimy si\u0119 je usuwa\u0107, szybko trac\u0105 na wa\u017cno\u015bci...\u003C\/p\u003E\n\u003Cp\u003ESp\u00f3jrzcie na kod autoloadera po serii poprawek:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\u0026lt;?php\n\nclass Autoloader\n{\n    private $namespace;\n\n    private $path;\n\n    private $registered = false;\n\n    public function __construct($namespace, $path = \u0027.\u0027)\n    {\n        $this-\u0026gt;namespace = $this-\u0026gt;addEndingSlash($namespace, \u0027\\\\\u0027);\n        $this-\u0026gt;path = $this-\u0026gt;addEndingSlash($path, \u0027\/\u0027);\n    }\n\n    private function addEndingSlash($word, $slash = \u0027\/\u0027)\n    {\n        $lastCharacter = substr($word, -1);\n        return $lastCharacter == $slash ? $word : $word . $slash;\n    }\n\n    public function autoload($className)\n    {\n        if ($this-\u0026gt;isNotResponsibleForClass($className)) {\n            return false;\n        }\n\n        $path = $this-\u0026gt;classNameToFilePath($className);\n        if (file_exists($path)) {\n            require_once($path);\n            return true;\n        }\n\n        $groupName = $this-\u0026gt;classNameToGroupName($className);\n        $path = $this-\u0026gt;classNameToFilePath($groupName);\n        if (file_exists($path)) {\n            require_once($path);\n            return true;\n        }\n\n        return false;\n    }\n\n    private function isNotResponsibleForClass($className)\n    {\n        return substr($className, 0, strlen($this-\u0026gt;namespace)) !== $this-\u0026gt;namespace;\n    }\n\n    private function classNameToFilePath($className)\n    {\n        return $this-\u0026gt;path . str_replace(\u0027\\\\\u0027,\u0027\/\u0027, ltrim( $className, \u0027\\\\\u0027)) . \u0027.php\u0027;\n    }\n\n    private function classNameToGroupName($className)\n    {\n        $slashPos = strrpos($className,\u0027\\\\\u0027,-1) + 1;\n        $base = substr($className,0,$slashPos);\n        $classPure = substr($className,$slashPos);\n        preg_match_all(\u0027\/(?:^|[A-Z])[a-z]+\/\u0027,$classPure,$matches);\n\n        return $base . end($matches[0]) . \u0027s\u0027;\n    }\n\n    public function register()\n    {\n        if ($this-\u0026gt;registered) { return false; }\n        spl_autoload_register(array($this, \u0027autoload\u0027));\n        $this-\u0026gt;registered = true;\n\n        return true;\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWystarczy zerkn\u0105\u0107 na funkcj\u0119 autoload, \u017ceby wiedzie\u0107, co robi. Ba, nawet nie trzeba zna\u0107 \u017cadnego j\u0119zyka programowania! To\u017c to niemal czysty angielski: \u201cif this is not responsible for class \u2018class name\u2019, return false\u201d. Nie mamy poj\u0119cia \u003Cem\u003Ejak\u003C\/em\u003E funkcja to robi, ale wida\u0107 jak na d\u0142oni \u003Cem\u003Eco\u003C\/em\u003E takiego wykonuje.\u003C\/p\u003E\n\u003Cp\u003E\u003Cem\u003E\u201cJak\u201d\u003C\/em\u003E natomiast znajduje si\u0119 w osobnych, prywatnych metodach. Rozdzielili\u015bmy zatem od siebie r\u00f3\u017cne \u003Cem\u003Ewarstwy abstrakcji\u003C\/em\u003E, kt\u00f3re wcze\u015bniej by\u0142y zlane w jedn\u0105, brzydk\u0105 funkcj\u0119. Bo je\u015bli kto\u015b zajrzy do naszego kodu, to najprawdopodobniej nie b\u0119dzie potrzebowa\u0142 znajomo\u015bci wszystkiego, co tam naskrobali\u015bmy, lecz przyjdzie z jakim\u015b jednym konkretnym zadaniem: \u201cogarn\u0105\u0107 jak mniej wi\u0119cej dzia\u0142a ten autoloader\u201d, \u201czmieni\u0107 format nazwy \u2018zbiorowego pliku\u2019\u201d, \u201czmieni\u0107 kolejno\u015b\u0107 sprawdzania potencjalnych plik\u00f3w\u201d itp. I dlatego rozdzielenie warstw abstrakcji tak bardzo upro\u015bci mu prac\u0119.\u003C\/p\u003E\n\u003Cp\u003ENa pierwszy rzut oka wydawa\u0142oby si\u0119 sensowniejsze stworzenie metody isResponsibleForClass zamiast jej negacji \u2013 isNotResponsibleForClass. Kto normalny pyta\u0142by klas\u0119, czy \u003Cem\u003Enie jest\u003C\/em\u003E za co\u015b odpowiedzialna? Odpowied\u017a \u201ctak, nie jestem\u201d tylko niepotrzebnie by wszystko zagmatwa\u0142a, prawda? No w\u0142a\u015bnie niekoniecznie. U\u017cycie tej metody jest tylko jedno i sprowadza si\u0119 do \u201cje\u015bli nie jeste\u015b za to odpowiedzialna, to daj sobie spok\u00f3j\u201d. Zapisanie tego warunku jako \u003Ccode\u003Eif (!$this-\u0026gt;isResponsibleForClass($className))\u003C\/code\u003E zmniejsza czytelno\u015b\u0107, poniewa\u017c tego wykrzyknika prawie nie wida\u0107. Zawsze zapominamy o wykrzyknikach...\u003C\/p\u003E\n\u003Cp\u003EZanegowanie dopad\u0142o te\u017c zmienn\u0105 \u003Ccode\u003Evalid\u003C\/code\u003E. Zawsze gdy j\u0105 widzia\u0142em, musia\u0142em si\u0119 zastanowi\u0107, po co ona komu. Kiedy niby autoloader staje si\u0119 \u201cinvalid\u201d? A chodzi przecie\u017c o to, \u017ce autoloader mo\u017ce by\u0107 albo \u003Cem\u003Ejeszcze nie zarejestrowany\u003C\/em\u003E, albo \u003Cem\u003Eju\u017c zarejestrowany\u003C\/em\u003E. Czemu wi\u0119c nie zmieni\u0107 nazwy tej w\u0142a\u015bciwo\u015bci na \u003Ccode\u003Eregistered\u003C\/code\u003E? Teraz metoda \u003Ccode\u003Eregister()\u003C\/code\u003E staje si\u0119 bardzo czytelna: \u201cje\u015bli jeste\u015b zarejestrowany, to ju\u017c wi\u0119cej si\u0119 nie rejestruj\u201d.\u003C\/p\u003E\n\u003Cp\u003EBazowy namespace powinien ko\u0144czy\u0107 si\u0119 backslashem, aby unikn\u0105\u0107 takich sytuacji, gdy chcemy na przyk\u0142ad przechwyci\u0107 klasy \u201cJava\/...\u201d, a zgarniemy tak\u017ce i \u201cJavascript\/...\u201d. Dla zachowania jednorodno\u015bci, to samo powinno dotyczy\u0107 drugiego parametru konstruktora (\u015bcie\u017cki do folderu). Ale po co cz\u0142owiekowi, kt\u00f3ry chce u\u017cy\u0107 naszego autoloadera, kaza\u0107 si\u0119 zastanawia\u0107 nad tym, czy wymagamy slasha czy nie? Mo\u017ce lepiej po prostu sprawd\u017amy, czy slash jest na ko\u0144cu parametru, i doklejmy go, je\u015bli nie? Dodanie metody \u003Ccode\u003EaddEndingSlash\u003C\/code\u003E sprawi\u0142o, \u017ce nie tylko sama klasa jest prostsza, ale tak\u017ce i jej u\u017cycie na zewn\u0105trz.\u003C\/p\u003E\n\u003Cp\u003ETym oto sposobem w nowym kodzie jest zdecydowanie mniej zagnie\u017cd\u017ce\u0144, metody s\u0105 kr\u00f3tsze, a ka\u017cda zajmuje si\u0119 dok\u0142adnie jedn\u0105 rzecz\u0105 na jednym poziomie abstrakcji.\u003C\/p\u003E\n\u003Cp\u003EI jak? Kt\u00f3r\u0105 wersj\u0119 wolicie? Kt\u00f3ra nie marnuje czasu programisty pr\u00f3buj\u0105cego j\u0105 zrozumie\u0107?\u003C\/p\u003E\n\u003Cp\u003E\u201cCzysty kod\u201d warto przeczyta\u0107, warto do niego wraca\u0107 i \u2013 przede wszystkim \u2013 warto stosowa\u0107 si\u0119 do zawartych w nim rad.\u003C\/p\u003E","words":1438,"readTime":6,"lang":"pl"}}}}}