{"id":29845,"date":"2023-05-17T08:51:48","date_gmt":"2023-05-17T06:51:48","guid":{"rendered":"https:\/\/nearshore-it.eu\/artykuly\/zasady-solid-dobre-praktyki-w-programowaniu\/"},"modified":"2024-11-07T15:15:00","modified_gmt":"2024-11-07T14:15:00","slug":"zasady-solid-dobre-praktyki-w-programowaniu","status":"publish","type":"post","link":"https:\/\/nearshore-it.eu\/pl\/artykuly\/zasady-solid-dobre-praktyki-w-programowaniu\/","title":{"rendered":"Zasady SOLID w programowaniu obiektowym"},"content":{"rendered":"\n<div class=\"table-of-contents\">\n    <p class=\"title\">PRZEJD\u0179 DO:<\/p>\n    <ol>\n                    <li><a href=\"#kod\">1.  Po pierwsze, czysty kod <\/a><\/li>\n                    <li><a href=\"#programowaniu\">2.  Czym jest SOLID w programowaniu? <\/a><\/li>\n                    <li><a href=\"#SOLID\">3.  Najwa\u017cniejsze zasady SOLID <\/a><\/li>\n                    <li><a href=\"#SOLID-\u2013-przyk\u0142ady-z-wykorzystaniem-Angularau002du002d\">4.  SOLID \u2013 przyk\u0142ady z wykorzystaniem Angulara  <\/a><\/li>\n                    <li><a href=\"#Podsumowanieu002du002d\">5.  Podsumowanie\u00a0<\/a><\/li>\n            <\/ol>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"kod\">Po pierwsze, czysty kod<\/h2>\n\n\n\n<p>Pisanie czystego kodu (ang. <strong>clean code<\/strong>) powinno by\u0107 kluczowym elementem w pracy ka\u017cdego programisty. To w\u0142a\u015bnie czysty kod pozwala nam utrzymywa\u0107 nasze systemy w dobrym stanie, zapewniaj\u0105c \u0142atwo\u015b\u0107 w utrzymaniu i rozwoju oraz wi\u0119ksz\u0105 elastyczno\u015b\u0107. Dlaczego jeszcze dbanie o czysty kod jest tak wa\u017cne? Wed\u0142ug raportu \u201eThe state of software code&#8221;, <strong>40% developer\u00f3w przyznaje, \u017ce najbardziej frustruje ich wykrywanie i naprawiane b\u0142\u0119d\u00f3w w kodzie<\/strong>, co nieraz mo\u017ce przyczynia\u0107 si\u0119 do przepracowania, a nawet wypalenia zawodowego. Nie wspominaj\u0105c o op\u00f3\u017anieniach w rozwoju oprogramowania.<\/p>\n\n\n\n<p>Czysty kod to taki, kt\u00f3ry jest czytelny, \u0142atwy do zrozumienia, modyfikacji i testowania. \u0141atwo\u015b\u0107 w zrozumieniu kodu jest szczeg\u00f3lnie wa\u017cna w przypadku wi\u0119kszych projekt\u00f3w, gdzie nad tymi samymi plikami pracuje zwykle wiele os\u00f3b. Zw\u0142aszcza w tego typu projektach powinni\u015bmy d\u0105\u017cy\u0107 do tego, aby pisany przez nas kod by\u0142 przejrzysty i klarowny, nawet dla os\u00f3b, kt\u00f3re nie pracowa\u0142y nad danym projektem od samego pocz\u0105tku. Tu z pomoc\u0105 przychodz\u0105 zasady znane jako SOLID.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"programowaniu\">Czym jest SOLID w programowaniu?<\/h2>\n\n\n\n<p>SOLID to zestaw pi\u0119ciu zasad, kt\u00f3re zosta\u0142y opracowane przez Roberta C. Martina, znanego jako \u201e<strong>Uncle Bob<\/strong>\u201d, w latach 90. XX wieku. Dzi\u0119ki tym zasadom otrzymali\u015bmy narz\u0119dzia, kt\u00f3re nie tylko pomagaj\u0105 w projektowaniu i implementacji system\u00f3w, ale tak\u017ce umo\u017cliwiaj\u0105 ich utrzymywanie, rozw\u00f3j i skalowanie. Korzystanie z tych zasad cz\u0119sto pozwala znacz\u0105co skr\u00f3ci\u0107 czas pracy nad projektem oraz zmniejszy\u0107 ilo\u015b\u0107 b\u0142\u0119d\u00f3w, co przek\u0142ada si\u0119 na zwi\u0119kszenie efektywno\u015bci i jako\u015bci samego kodu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"SOLID\">Najwa\u017cniejsze zasady SOLID<\/h2>\n\n\n\n<p>W tym artykule o SOLID om\u00f3wi\u0119 zasady, na kt\u00f3rych opiera si\u0119 filozofia pisania czystego kodu. SOLID to skr\u00f3towiec utworzony od pi\u0119ciu zasad projektowania obiektowego, kt\u00f3rych celem jest u\u0142atwienie modyfikowania, skalowania i utrzymywania kodu.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Single Responsibility Principle&nbsp;<\/h3>\n\n\n\n<p>Pierwsz\u0105 z zasad SOLID jest zasada pojedynczej odpowiedzialno\u015bci (ang. <strong>Single Responsibility Principle \u2013 SPR<\/strong>). Zgodnie z ni\u0105 klasa powinna mie\u0107 tylko jedn\u0105 odpowiedzialno\u015b\u0107, czyli powinna by\u0107 odpowiedzialna tylko za jedn\u0105 rzecz. O ile nie mo\u017cna jednoznacznie stwierdzi\u0107, kt\u00f3ra zasada SOLID jest najwa\u017cniejsza, poniewa\u017c ka\u017cda zasada wp\u0142ywa na jako\u015b\u0107 kodu w r\u00f3\u017cny spos\u00f3b, o tyle wielu programist\u00f3w uwa\u017ca, \u017ce to w\u0142a\u015bnie zasada pojedynczej odpowiedzialno\u015bci jest absolutnym minimum, kt\u00f3re ka\u017cdy z nas powinien stosowa\u0107 w swoim kodzie.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Open\/Closed Principle&nbsp;<\/h3>\n\n\n\n<p>Drug\u0105 wa\u017cn\u0105 zasad\u0105 jest zasada otwarte\/zamkni\u0119te (ang. <strong>Open\/Closed Principle \u2013 OCP<\/strong>). Wed\u0142ug tej zasady klasa powinna by\u0107 otwarta na rozszerzanie, ale jednocze\u015bnie zamkni\u0119ta na modyfikacj\u0119. To oznacza, \u017ce gdy chcemy doda\u0107 now\u0105 funkcjonalno\u015b\u0107 do naszej aplikacji, nie powinni\u015bmy modyfikowa\u0107 istniej\u0105cego kodu, a jedynie dodawa\u0107 nowy. Dzi\u0119ki temu zmiany w jednej cz\u0119\u015bci systemu nie spowoduj\u0105 awarii w innych jego cz\u0119\u015bciach.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Liskov Substitution Principle&nbsp;<\/h3>\n\n\n\n<p>Kolejn\u0105 zasad\u0105 jest zasada podstawienia Liskov (ang. <strong>Liskov Substitution Principle \u2013 LSP<\/strong>). Zasada ta okre\u015bla, \u017ce obiekty typu pochodnego powinny by\u0107 zawsze zast\u0119powalne przez obiekty typu bazowego. To oznacza, \u017ce klasa dziedzicz\u0105ca powinna by\u0107 w pe\u0142ni zgodna z klas\u0105, po kt\u00f3rej dziedziczy. Dzi\u0119ki tej zasadzie mo\u017cemy unikn\u0105\u0107 b\u0142\u0119d\u00f3w wynikaj\u0105cych z niezgodno\u015bci mi\u0119dzy klasami, a tak\u017ce u\u0142atwi\u0107 sobie przysz\u0142y rozw\u00f3j aplikacji.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Interface Segregation Principle&nbsp;<\/h3>\n\n\n\n<p>Czwart\u0105 zasad\u0105 jest zasada segregacji interfejs\u00f3w (ang. <strong>Interface Segregation Principle \u2013 ISP<\/strong>). Wed\u0142ug niej interfejsy powinny by\u0107 ma\u0142e i jednorodne, a klienci powinni korzysta\u0107 tylko z tych, kt\u00f3rych potrzebuj\u0105. Oznacza to, \u017ce klasa powinna implementowa\u0107 tylko te metody, kt\u00f3rych potrzebuje, a wi\u0119c interfejs nie powinien zmusza\u0107 jej do implementacji pozosta\u0142ych metod. To pozwala unikn\u0105\u0107 skomplikowania kodu.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dependency Inversion Principle&nbsp;<\/h3>\n\n\n\n<p>Pi\u0105t\u0105 i ostatni\u0105 zasad\u0105 SOLID jest zasada odwr\u00f3cenia zale\u017cno\u015bci (ang. <strong>Dependency Inversion Principle \u2013 DIP<\/strong>). Zgodnie z ni\u0105 zale\u017cno\u015bci mi\u0119dzy klasami powinny by\u0107 odwr\u00f3cone. Oznacza to, \u017ce klasy powinny zale\u017ce\u0107 od abstrakcji, a nie od konkretnych implementacji. Dzi\u0119ki temu kod jest \u0142atwiejszy do testowania i modyfikowania.&nbsp;&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dlaczego zasady SOLID s\u0105 tak wa\u017cne?&nbsp;&nbsp;<\/h3>\n\n\n\n<p>Podsumowuj\u0105c, zasady SOLID s\u0105 kluczowe dla tworzenia skalowalnych, elastycznych i \u0142atwych w utrzymaniu aplikacji. Wymagaj\u0105 one od nas abstrakcyjnego my\u015blenia, projektowania i wdra\u017cania czytelnego kodu. W\u0142a\u015bciwe stosowanie zasad SOLID pozwala unikn\u0105\u0107 licznych problem\u00f3w, takich jak trudno\u015b\u0107 we wprowadzaniu zmian i testowaniu czy nieczytelno\u015b\u0107 i niejednoznaczno\u015b\u0107 kodu.&nbsp;<\/p>\n\n\n\n<p>W kolejnych rozdzia\u0142ach skupi\u0119 si\u0119 na ka\u017cdej z zasad SOLID, rozwin\u0119 ich znaczenie i om\u00f3wi\u0119 przyk\u0142ady, dzi\u0119ki czemu b\u0119dziemy w stanie lepiej zrozumie\u0107, jak mo\u017cna stosowa\u0107 je w praktyce.<\/p>\n\n\n\n<p><strong>Przeczytaj tak\u017ce: <\/strong><a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/najlepsze-frameworki-frontendowe\/\">Kt\u00f3ry\u00a0framework frontendowy jest najlepszy?<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"SOLID-\u2013-przyk\u0142ady-z-wykorzystaniem-Angulara--\">SOLID \u2013 przyk\u0142ady z wykorzystaniem Angulara&nbsp;&nbsp;<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Zasada pojedynczej odpowiedzialno\u015bci&nbsp;<\/h3>\n\n\n\n<p>Zasada pojedynczej odpowiedzialno\u015bci ma na celu popraw\u0119 jako\u015bci kodu i u\u0142atwienie jego rozwijania. Zgodnie z ni\u0105 ka\u017cdy element kodu powinien mie\u0107 tylko jedn\u0105 odpowiedzialno\u015b\u0107, a zmiany w jednej funkcjonalno\u015bci nie powinny wp\u0142ywa\u0107 na pozosta\u0142e. Innymi s\u0142owy, klasa, funkcja czy modu\u0142 powinny robi\u0107 tylko to, do czego zosta\u0142y stworzone i nie powinny mie\u0107 dodatkowych zada\u0144, kt\u00f3re nie s\u0105 zwi\u0105zane z ich g\u0142\u00f3wn\u0105 odpowiedzialno\u015bci\u0105.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Zastosowanie zasady pojedynczej odpowiedzialno\u015bci przynosi wiele korzy\u015bci. Przede wszystkim <strong>u\u0142atwia utrzymywanie i rozwijanie kodu<\/strong>, poniewa\u017c kod staje si\u0119 bardziej modularny i \u0142atwiej jest zidentyfikowa\u0107 miejsca, w kt\u00f3rych nale\u017cy dokona\u0107 zmian. Ponadto, dzi\u0119ki temu, \u017ce ka\u017cdy element ma tylko jedn\u0105 odpowiedzialno\u015b\u0107, \u0142atwiej jest go testowa\u0107 i staje si\u0119 on du\u017co bardziej zrozumia\u0142y dla innych programist\u00f3w.&nbsp;<\/p>\n\n\n\n<p>W jaki spos\u00f3b mo\u017cemy rozpozna\u0107, \u017ce zasada pojedynczej odpowiedzialno\u015bci nie jest spe\u0142niona? Cz\u0119sto nie jest \u0142atwo zidentyfikowa\u0107 miejsce, w kt\u00f3rym ko\u0144czy si\u0119 odpowiedzialno\u015b\u0107 jednego komponentu, a zaczyna drugiego. Z pomoc\u0105 przychodzi regu\u0142a wykorzystuj\u0105ca sp\u00f3jnik \u201ci\u201d. Je\u015bli opisuj\u0105c odpowiedzialno\u015b\u0107 danego elementu u\u017cyjemy s\u0142owa \u201ci\u201d, mo\u017cemy potraktowa\u0107 to jako sygna\u0142, \u017ce nasz element zajmuje si\u0119 zbyt wieloma rzeczami \u2013 jego odpowiedzialno\u015b\u0107 nie jest pojedyncza.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Zar\u00f3wno ten przyk\u0142ad, jak i wszystkie kolejne b\u0119d\u0105 napisane we frameworku Angular. We\u017amy komponent <strong>DataComponent<\/strong>, kt\u00f3rego zadaniem jest pobranie danych z serwera <strong>i<\/strong> ich przetworzenie <strong>i <\/strong>ich wy\u015bwietlenie. W opisie odpowiedzialno\u015bci natrafili\u015bmy na s\u0142owo \u201ci\u201d, co mo\u017ce oznacza\u0107, \u017ce b\u0119dziemy potrzebowali udoskonali\u0107 nasz kod.&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Component({ \n\n  selector: 'app-data', \n\n  template: ` \n\n    &lt;ul> \n\n      &lt;li *ngFor=\"let item of items\"> \n\n        {{ item }} \n\n      &lt;\/li> \n\n    &lt;\/ul> \n\n  `, \n\n}) \n\nexport class DataComponent implements OnInit { \n\n  items: string[] = []; \n\n \n\n  constructor(private http: HttpClient) {} \n\n \n\n  ngOnInit(): void { \n\n    this.http.get&lt;Item[]>('http:\/\/example.com\/data').subscribe((data: Item[]) => { \n\n      this.items = data.map((item) => item.name.toUpperCase()); \n\n    }); \n\n  }   \n\n}<\/pre>\n\n\n\n<p>I faktycznie takie podej\u015bcie \u0142amie zasad\u0119 pojedynczej odpowiedzialno\u015bci, poniewa\u017c komponent ten powinien by\u0107 odpowiedzialny tylko za prezentacj\u0119 danych. Aby go poprawi\u0107 i spe\u0142ni\u0107 zasad\u0119 pojedynczej odpowiedzialno\u015bci, mo\u017cemy wydzieli\u0107 logik\u0119 pobierania danych i ich przetwarzania do oddzielnych serwis\u00f3w. Nasz komponent i wydzielone serwisy b\u0119d\u0105 wtedy wygl\u0105da\u0142y tak:&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Component({ \n\n  selector: 'app-data', \n\n  template: ` \n\n    &lt;ul> \n\n      &lt;li *ngFor=\"let item of items\"> \n\n        {{ item }} \n\n      &lt;\/li> \n\n    &lt;\/ul> \n\n  `, \n\n}) \n\nexport class DataComponent implements OnInit { \n\n  items: string[] = []; \n\n \n\n  constructor(private itemsService: ItemsService,  \n\n    private dataService: DataService) {} \n\n \n\n  ngOnInit(): void { \n\n    this.itemsService.getItems().subscribe((items) => { \n\n      this.items = this.dataService.processData(items); \n\n    }); \n\n  }   \n\n} \n\n \n\n@Injectable() \n\nexport class ItemsService { \n\n  constructor(private http: HttpClient) { } \n\n \n\n  getItems(): Observable&lt;Item[]> { \n\n    return this.http.get&lt;Item[]>('http:\/\/example.com\/data'); \n\n  } \n\n} \n\n \n\n@Injectable() \n\nexport class DataService { \n\n  processData(data: Item[]): string[] { \n\n    return data.map((item) => item.name.toUpperCase()); \n\n  } \n\n}<\/pre>\n\n\n\n<p>Dzi\u0119ki takiemu podej\u015bciu odpowiedzialno\u015b\u0107 zosta\u0142a rozproszona, a ka\u017cdy z obiekt\u00f3w ma tylko jedn\u0105.&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Komponent <strong>DataComponent<\/strong> zajmuje si\u0119 tylko prezentacj\u0105 danych,&nbsp;<\/li>\n\n\n\n<li>Serwis<strong> ItemsService<\/strong> odpowiedzialny jest tylko za pobranie danych,&nbsp;<\/li>\n\n\n\n<li>Serwis <strong>DataService<\/strong> zawiera tylko logik\u0119 przetwarzania danych.&nbsp;<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Dzi\u0119ki takiemu podzia\u0142owi jeste\u015bmy w stanie w bardzo \u0142atwy spos\u00f3b przygotowa\u0107 wymagane testy, a tak\u017ce w przysz\u0142o\u015bci b\u0119dziemy w stanie szybko zlokalizowa\u0107 miejsca, kt\u00f3re potencjalnie b\u0119d\u0105 mog\u0142y wymaga\u0107 jakich\u015b zmian lub udoskonale\u0144.&nbsp;<\/p>\n\n\n\n<p>Wniosek jest taki, \u017ce zasada pojedynczej odpowiedzialno\u015bci jest <strong>kluczowa dla tworzenia czytelnego i \u0142atwego w utrzymaniu kodu<\/strong>. Przez wielu programist\u00f3w uwa\u017cana jest za najwa\u017cniejsz\u0105 spo\u015br\u00f3d wszystkich zasad SOLID. Poprawne jej zrozumienie i stosowanie pozwalaj\u0105 na \u0142atwiejsze rozwijanie oprogramowania oraz zmniejszenie ryzyka pojawienia si\u0119 b\u0142\u0119d\u00f3w w kodzie.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Zasada otwarte\/zamkni\u0119te&nbsp;<\/h3>\n\n\n\n<p>Zasada ta pomaga w tworzeniu kodu, kt\u00f3ry jest bardziej elastyczny i \u0142atwiejszy do rozbudowy. Dzi\u0119ki niej mo\u017cemy dodawa\u0107 nowe funkcje bez obawy o to, \u017ce wprowadzimy b\u0142\u0119dy w ju\u017c istniej\u0105cym kodzie.&nbsp;&nbsp;<\/p>\n\n\n\n<p>\u201e<strong>Tworzone modu\u0142y powinny by\u0107 otwarte na rozbudow\u0119<\/strong>\u201d &#8211; ale jak to rozumie\u0107? Oznacza to tyle, \u017ce gdy chcemy wprowadzi\u0107 now\u0105 funkcjonalno\u015b\u0107 do aplikacji, nie powinni\u015bmy modyfikowa\u0107 ju\u017c istniej\u0105cego kodu, tylko dodawa\u0107 nowy kod, a istniej\u0105ce modu\u0142y powinny to umo\u017cliwia\u0107. W ten spos\u00f3b nowa funkcjonalno\u015b\u0107 mo\u017ce zosta\u0107 dodana bez wp\u0142ywu na dotychczasowe dzia\u0142anie aplikacji.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Aby spe\u0142ni\u0107 t\u0119 zasad\u0119, warto w kodzie wykorzystywa\u0107 zalety programowania obiektowego, czyli mechanizmy dziedziczenia, polimorfizmu i interfejs\u00f3w. Dzi\u0119ki nim mo\u017cemy oddzieli\u0107 kod, kt\u00f3ry si\u0119 zmienia, od kodu, kt\u00f3ry pozostaje sta\u0142y.&nbsp;<\/p>\n\n\n\n<p>Zasada otwarte\/zamkni\u0119te jest szczeg\u00f3lnie wa\u017cna w du\u017cych projektach, w kt\u00f3rych ka\u017cda zmiana w kodzie mo\u017ce przynie\u015b\u0107 nieoczekiwane skutki uboczne i prowadzi\u0107 do b\u0142\u0119d\u00f3w. Dzi\u0119ki spe\u0142nieniu tej zasady mo\u017cemy unikn\u0105\u0107 tych problem\u00f3w i tworzy\u0107 bardziej niezawodne oprogramowanie.&nbsp;<\/p>\n\n\n\n<p>Powinni\u015bmy stosowa\u0107 t\u0119 zasad\u0119 r\u00f3wnie\u017c wtedy, kiedy tworzymy now\u0105 bibliotek\u0119. Z za\u0142o\u017cenia u\u017cytkownicy naszej biblioteki nie b\u0119d\u0105 mogli wprowadza\u0107 w niej zmian, lecz by\u0142oby dobrze, aby tam, gdzie mia\u0142oby to sens, w jaki\u015b spos\u00f3b byli w stanie rozszerza\u0107 jej mo\u017cliwo\u015bci w swoim projekcie.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Jako przyk\u0142ad we\u017amy serwis <strong>PaymentService<\/strong> do przetwarzania p\u0142atno\u015bci:&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Injectable() \n\nexport class PaymentService {   \n\n  processPayment(paymentMethod: string): void { \n\n    switch (paymentMethod) { \n\n        case 'creditCard': \n\n            this.processCreditCardPayment(); \n\n            break; \n\n        case 'cashOnDelivery': \n\n            this.processCashOnDeliveryPayment(); \n\n            break;     \n\n        default: \n\n            throw new Error('Unsupported payment method'); \n\n    } \n\n  } \n\n \n\n  private processCreditCardPayment(): void { \n\n    \/\/ logika przetwarzania p\u0142atno\u015bci kart\u0105 kredytow\u0105 \n\n  } \n\n \n\n  private processCashOnDeliveryPayment(): void { \n\n    \/\/ logika przetwarzania p\u0142atno\u015bci przy odbiorze \n\n  } \n\n}<\/pre>\n\n\n\n<p>Serwis ten \u0142amie zasad\u0119 otwarte\/zamkni\u0119te, poniewa\u017c implementacja nowej metody p\u0142atno\u015bci wymaga\u0142aby od nas wprowadzenia zmian w samym serwisie. Zamiast tego powinni\u015bmy przygotowa\u0107 serwis w taki spos\u00f3b, aby nowe metody p\u0142atno\u015bci mog\u0142y by\u0107 dodawane bez ingerencji w jego kod.&nbsp;<\/p>\n\n\n\n<p>Mo\u017cemy to zrobi\u0107, przygotowuj\u0105c interfejs <strong>PaymentMethod<\/strong>, kt\u00f3ry b\u0119dzie implementowany przez nowe metody p\u0142atno\u015bci, a same metody p\u0142atno\u015bci b\u0119d\u0105 przekazywane jako argument do funkcji <strong>processPayment<\/strong>.&nbsp;<\/p>\n\n\n\n<p>Nowy serwis<strong> PaymentService<\/strong> wraz z interfejsem <strong>PaymentMethod<\/strong> i kolejnymi metodami p\u0142atno\u015bci wygl\u0105da\u0142yby tak:&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Injectable() \n\nexport class PaymentService { \n\n  processPayment(paymentMethod: PaymentMethod): void { \n\n    paymentMethod.processPayment(); \n\n  } \n\n} \n\n \n\ninterface PaymentMethod { \n\n  processPayment(): void; \n\n} \n \n\n@Injectable() \n\nexport class CreditCardService implements PaymentMethod { \n\n  processPayment(): void { \n\n    \/\/ logika przetwarzania p\u0142atno\u015bci kart\u0105 kredytow\u0105 \n\n  } \n\n} \n \n\n@Injectable() \n\nexport class CashOnDeliveryService implements PaymentMethod { \n\n  processPayment(): void { \n\n    \/\/ logika przetwarzania p\u0142atno\u015bci przy odbiorze \n\n  } \n\n} \n \n\n@Injectable() \n\nexport class PaypalService implements PaymentMethod { \n\n  processPayment(): void { \n\n    \/\/ logika przetwarzania p\u0142atno\u015bci Paypal \n\n  } \n\n} \n\n \n\n\/\/ ... <\/pre>\n\n\n\n<p>Dzi\u0119ki temu ka\u017cd\u0105 now\u0105 metod\u0119 p\u0142atno\u015bci mo\u017cemy doda\u0107, tworz\u0105c now\u0105 klas\u0119 implementuj\u0105c\u0105 interfejs <strong>PaymentMethod<\/strong>. Tym samym nie musimy wprowadza\u0107 zmian w serwisie <strong>PaymentService<\/strong>, a co za tym idzie, spe\u0142nia on teraz zasad\u0119 otwarte\/zamkni\u0119te.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Podsumowuj\u0105c, zasada otwarte\/zamkni\u0119te zak\u0142ada, \u017ce klasy powinny by\u0107 otwarte na rozszerzanie, ale zamkni\u0119te na modyfikacj\u0119. Oznacza to, \u017ce nowe funkcjonalno\u015bci nale\u017cy wprowadza\u0107 nie poprzez wprowadzanie zmian w istniej\u0105cych elementach programu, lecz za pomoc\u0105 dodawania nowych klas i modu\u0142\u00f3w. Poprawne zastosowanie tej zasady mo\u017ce przyczyni\u0107 si\u0119 do zwi\u0119kszenia elastyczno\u015bci kodu oraz zmniejszenia ilo\u015bci b\u0142\u0119d\u00f3w w trakcie tworzenia aplikacji.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Zasada podstawienia Liskov&nbsp;<\/h3>\n\n\n\n<p>Zasada podstawienia Liskov m\u00f3wi o tym, \u017ce<strong> powinni\u015bmy mie\u0107 mo\u017cliwo\u015b\u0107 zast\u0105pienia klasy bazowej klas\u0105 dziedzicz\u0105c\u0105 bez zmiany dzia\u0142ania programu<\/strong>. Innymi s\u0142owy, je\u015bli klasa A dziedziczy po klasie B, to powinno by\u0107 mo\u017cliwe u\u017cycie klasy A zamiast obiektu klasy B, a program nadal powinien dzia\u0142a\u0107 poprawnie. W mojej opinii jest to najbardziej skomplikowana zasada spo\u015br\u00f3d wszystkich zasad SOLID.&nbsp;<\/p>\n\n\n\n<p>Zasada ta umo\u017cliwia \u0142atwe dodawanie nowych funkcjonalno\u015bci do istniej\u0105cego ju\u017c kodu. Klasa dziedzicz\u0105ca po klasie bazowej mo\u017ce wprowadza\u0107 nowe funkcjonalno\u015bci, ale musi zachowywa\u0107 interfejs klasy bazowej. Dzi\u0119ki temu aplikacja mo\u017ce korzysta\u0107 z obiekt\u00f3w klas dziedzicz\u0105cych jak z obiekt\u00f3w klasy bazowej, co umo\u017cliwia \u0142atwe rozszerzanie funkcjonalno\u015bci.&nbsp;<\/p>\n\n\n\n<p>Zasada ta zosta\u0142a sformu\u0142owana przez Barbar\u0119 Liskov w latach 80. XX wieku i by\u0142a pierwotnie stosowana w j\u0119zykach programowania proceduralnego. Z czasem sta\u0142a si\u0119 r\u00f3wnie wa\u017cna w kontek\u015bcie programowania obiektowego.&nbsp;<\/p>\n\n\n\n<p>Jako przyk\u0142ad utworzymy komponent <strong>BirdComponent<\/strong>, w ramach kt\u00f3rego b\u0119dziemy chcieli wyprowadza\u0107 nasze ptaki \u201ena spacer\u201d. Stworzymy zatem klas\u0119 bazow\u0105 <strong>Bird <\/strong>i dla przyk\u0142adu spr\u00f3bujemy utworzy\u0107 dla niej jak\u0105\u015b klas\u0119 dziedzicz\u0105c\u0105.&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Bird { \n\n  fly(distance: number): void { \n\n    console.log(`Bird flew ${distance} meters`); \n\n  } \n\n} \n\n \n\nclass Penguin extends Bird { \n\n  fly(distance: number): void { \n\n    throw new Error('Penguins do not fly'); \n\n  } \n\n} \n \n\n@Component({ \n\n  selector: 'app-bird', \n\n  template: `&lt;p>Bird Component&lt;\/p>` \n\n}) \n\nexport class BirdComponent implements OnInit { \n\n  ngOnInit(): void { \n\n    const bird = new Penguin(); \n\n    this.takeToFly(bird, 10);   \n\n  } \n \n\n  takeToFly(bird: Bird, distance: number) { \n\n    bird.fly(distance); \n\n  } \n\n} <\/pre>\n\n\n\n<p>Mo\u017cemy zaobserwowa\u0107, \u017ce zasada podstawienia Liskov zosta\u0142a tutaj z\u0142amana, poniewa\u017c kiedy wywo\u0142amy metod\u0119 <strong>takeToFly <\/strong>dla obiektu typu dziedzicz\u0105cego <strong>Penguin<\/strong>, nie otrzymamy tego samego, oczekiwanego rezultatu, jaki chcieliby\u015bmy uzyska\u0107, gdyby\u015bmy wywo\u0142ali t\u0119 sam\u0105 metod\u0119 dla obiektu typu bazowego <strong>Bird<\/strong>.&nbsp;<\/p>\n\n\n\n<p>A w jaki spos\u00f3b zasada umo\u017cliwia \u0142atwe dodawanie nowych funkcjonalno\u015bci? Zmienimy troch\u0119 przyk\u0142ad i za\u0142o\u017cymy, \u017ce nie wszystkie ptaki lataj\u0105, ale wszystkie potrafi\u0105 \u015bpiewa\u0107. Utworzymy zn\u00f3w klas\u0119 bazow\u0105 <strong>Bird <\/strong>i dodamy do niej klas\u0119 dziedzicz\u0105c\u0105, kt\u00f3ra tym razem b\u0119dzie implementowa\u0107 poprawnie wszystkie metody z klasy <strong>Bird<\/strong>, ale r\u00f3wnie\u017c dodawa\u0107 nowe.&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Bird { \n\n    sing(lyrics: string): void { \n\n        console.log(`Bird sang ${lyrics} beautifully`); \n\n    } \n\n} \n \n\nclass FlyingBird extends Bird { \n\n    fly(distance: number): void {  \n\n        console.log(`Bird flew ${distance} meters`);      \n\n    }  \n\n} \n \n\n@Component({ \n\n    selector: 'app-bird', \n\n    template: `&lt;p>Bird Component&lt;\/p>` \n\n}) \n\nexport class BirdComponent implements OnInit { \n\n    ngOnInit(): void { \n\n        const bird = new FlyingBird(); \n\n        this.makeBirdSign(bird, \"We are the champions!\"); \n\n    } \n \n\n    makeBirdSign(bird: Bird, lyrics: string) { \n\n        bird.sing(lyrics); \n\n    } \n\n} <\/pre>\n\n\n\n<p>Zgodnie z zasad\u0105 podstawienia Liskov &#8211; <strong>FlyingBird<\/strong> zachowuje si\u0119 tak samo jak <strong>Bird<\/strong>, a ma dodatkow\u0105 funkcjonalno\u015b\u0107. W rezultacie w kodzie, kt\u00f3ry do tej pory korzysta\u0142 z typu <strong>Bird<\/strong>, mo\u017cemy u\u017cy\u0107 typu <strong>FlyingBird<\/strong>. Ptak jest w stanie dodatkowo lata\u0107, a istniej\u0105cy kod nie zosta\u0142 popsuty.&nbsp;<\/p>\n\n\n\n<p>Podsumowuj\u0105c, zasada podstawiania Liskov to wa\u017cna zasada programowania obiektowego, kt\u00f3ra zapewnia, \u017ce nasz kod jest elastyczny, \u0142atwy w utrzymaniu i testowaniu oraz spe\u0142nia wysokie standardy jako\u015bciowe, a stosowana poprawnie, pomaga unikn\u0105\u0107 b\u0142\u0119d\u00f3w.<\/p>\n\n\n\n<p><strong>Przeczytaj tak\u017ce: <\/strong><a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/programowanie-reaktywne-w-js-z-rxjs\/\">Wprowadzenie do\u00a0funkcjonalnego programowania reaktywnego w\u00a0JavaScript z\u00a0RxJS<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Zasada segregacji interfejs\u00f3w&nbsp;<\/h3>\n\n\n\n<p>Celem tej zasady jest zwi\u0119kszenie elastyczno\u015bci, \u0142atwo\u015bci w utrzymaniu i rozwoju oprogramowania. M\u00f3wi ona, \u017ce \u201e<strong>klient nie powinien by\u0107 zmuszony do zale\u017cno\u015bci od interfejs\u00f3w, kt\u00f3rych nie u\u017cywa<\/strong>\u201d.&nbsp;<\/p>\n\n\n\n<p>Zgodnie z ni\u0105 nie powinno by\u0107 jednego du\u017cego interfejsu, kt\u00f3ry jest implementowany przez wszystkie klasy, gdy tylko cz\u0119\u015b\u0107 z jego metod jest potrzebna w danym kontek\u015bcie. Zamiast tego interfejsy powinny by\u0107 podzielone na mniejsze i bardziej konkretne, kt\u00f3re s\u0105 bardziej dostosowane do potrzeb klient\u00f3w.&nbsp;<\/p>\n\n\n\n<p>Ta zasada jest wa\u017cna, poniewa\u017c pozwala nam na utrzymanie czysto\u015bci kodu oraz zwi\u0119kszenie jego czytelno\u015bci i zrozumia\u0142o\u015bci. Dzi\u0119ki temu, \u017ce ka\u017cda klasa implementuje tylko te metody, kt\u00f3re s\u0105 jej potrzebne, kod staje si\u0119 bardziej modu\u0142owy i \u0142atwiejszy w utrzymaniu.&nbsp;<\/p>\n\n\n\n<p>Powinni\u015bmy u\u017cywa\u0107 tej zasady zw\u0142aszcza wtedy, kiedy projektujemy interfejsy, kt\u00f3re maj\u0105 by\u0107 implementowane przez wiele klas. W szczeg\u00f3lno\u015bci, gdy interfejs jest zbyt du\u017cy, powinien by\u0107 rozbity na mniejsze interfejsy, aby unikn\u0105\u0107 sytuacji, w kt\u00f3rej klasy s\u0105 zmuszone implementowa\u0107 metody, kt\u00f3rych nie potrzebuj\u0105.&nbsp;<\/p>\n\n\n\n<p>Jako przyk\u0142ad, za\u0142\u00f3\u017cmy, \u017ce chcemy utworzy\u0107 strony w naszej aplikacji oraz aby komponenty reprezentuj\u0105ce strony mia\u0142y t\u0119 sam\u0105 struktur\u0119. Stw\u00f3rzmy zatem interfejs <strong>PageContent<\/strong> i zaimplementujemy go w naszym komponencie.&nbsp;&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> \nexport interface PageContent { \n\n    id: string; \n\n    content: string; \n\n    loading: boolean; \n\n    load(): void; \n\n} \n \n\n@Component({ \n\n    selector: 'app-errors', \n\n    template: `&lt;p>Erros Component&lt;\/p>` \n\n}) \n\nexport class ErrorsComponent implements PageContent { \n\n    id = \"; \n\n    content = \"; \n\n    loading = false; \n\n    load(): void { \n\n        \/\/ Logika \u0142adowania strony... \n\n    } \n\n} <\/pre>\n\n\n\n<p>Dodali\u015bmy przy okazji logik\u0119 \u0142adowania strony, kt\u00f3ra mog\u0142aby zawiera\u0107 np. animacj\u0119 \u0142adowania. Nasz interfejs gwarantuje, \u017ce ka\u017cdy komponent, kt\u00f3ry go implementuje, b\u0119dzie dzia\u0142a\u0142 prawid\u0142owo. Za\u0142\u00f3\u017cmy teraz, \u017ce dostali\u015bmy zadanie, aby utworzy\u0107 now\u0105 stron\u0119, kt\u00f3ra b\u0119dzie przechowywa\u0142a sta\u0142\u0105 zawarto\u015b\u0107. Oznacza to, \u017ce w komponencie nie potrzebujemy ju\u017c mechanizmu \u0142adowania. Chc\u0105c zaimplementowa\u0107 ten sam interfejs, musieliby\u015bmy zostawi\u0107 metod\u0119 <strong>load <\/strong>pust\u0105, a w naszym komponencie musieliby\u015bmy utworzy\u0107 metod\u0119, kt\u00f3rej nie potrzebujemy. I dlatego ten przyk\u0142ad \u0142amie zasad\u0119 segregacji interfejs\u00f3w.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Aby go poprawi\u0107, powinni\u015bmy wydzieli\u0107 dodatkowy interfejs, kt\u00f3ry s\u0142u\u017cy\u0142by nam do \u0142adowania stron, i u\u017cy\u0107 go wsz\u0119dzie tam, gdzie tego potrzebujemy. Pozosta\u0142e strony implementowa\u0142yby inny interfejs, z kt\u00f3rego wyci\u0119liby\u015bmy mechanizm \u0142adowania strony. W ten spos\u00f3b:&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">export interface PageContent { \n\n    id: string; \n\n    content: string; \n\n} \n \n\nexport interface PageLoad { \n\n    loading: boolean; \n\n    load(): void; \n\n} \n \n\n@Component({ \n\n    selector: 'app-errors', \n\n    template: `&lt;p>Erros Component&lt;\/p>` \n\n}) \n\nexport class ErrorsComponent implements PageContent, PageLoad { \n\n    id = \"; \n\n    content = \"; \n\n    loading = false; \n\n    load(): void { \n\n        \/\/ Logika \u0142adowania strony... \n\n    } \n\n} \n \n\n@Component({ \n\n    selector: 'app-static', \n\n    template: `&lt;p>Static Component&lt;\/p>` \n\n}) \n\nexport class StaticComponent implements PageContent { \n\n    id = \"; \n\n    content = \"; \n\n} <\/pre>\n\n\n\n<p>Dzi\u0119ki temu interfejsy zosta\u0142y posegregowane, a komponenty nie musz\u0105 implementowa\u0107 metod, kt\u00f3rych nie potrzebuj\u0105. Tym samym zasada segregacji interfejs\u00f3w zosta\u0142a spe\u0142niona.&nbsp;<\/p>\n\n\n\n<p>Podsumowuj\u0105c, ka\u017cda klasa powinna implementowa\u0107 tylko te metody, kt\u00f3re s\u0105 jej potrzebne. Dzi\u0119ki temu kod staje si\u0119 bardziej modu\u0142owy i \u0142atwiejszy w utrzymaniu. Zasada segregacji interfejs\u00f3w jest szczeg\u00f3lnie wa\u017cna, gdy projektujemy interfejsy, kt\u00f3re maj\u0105 by\u0107 implementowane przez wiele klas. Poprawne stosowanie tej zasady pozwala na stworzenie bardziej elastycznego i czytelnego kodu.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Zasada odwracania zale\u017cno\u015bci&nbsp;<\/h3>\n\n\n\n<p>Zasada ta g\u0142osi, \u017ce modu\u0142y wysokiego poziomu nie powinny zale\u017ce\u0107 od modu\u0142\u00f3w niskiego poziomu, a oba rodzaje modu\u0142\u00f3w powinny zale\u017ce\u0107 od abstrakcji. Innymi s\u0142owy, <strong>powinni\u015bmy unika\u0107 silnych zale\u017cno\u015bci mi\u0119dzy modu\u0142ami,<\/strong> a zamiast tego wykorzystywa\u0107 abstrakcj\u0119 i interfejsy.&nbsp;<\/p>\n\n\n\n<p>Zasad\u0119 odwracania zale\u017cno\u015bci nale\u017cy stosowa\u0107 w sytuacjach, gdy mamy do czynienia z kodem, w kt\u00f3rym jedna cz\u0119\u015b\u0107 aplikacji jest mocno powi\u0105zana z inn\u0105 i trudno jest j\u0105 zrefaktoryzowa\u0107 lub zmieni\u0107. W takiej sytuacji nale\u017cy rozwa\u017cy\u0107 zastosowanie abstrakcji i interfejs\u00f3w, kt\u00f3re pozwol\u0105 na \u0142atwiejsz\u0105 wymian\u0119 jednej cz\u0119\u015bci aplikacji na inn\u0105 bez konieczno\u015bci modyfikowania ca\u0142ej reszty kodu.&nbsp;<\/p>\n\n\n\n<p>Innym wa\u017cnym aspektem zasady odwracania zale\u017cno\u015bci jest to, \u017ce umo\u017cliwia ona pisanie kodu, kt\u00f3ry jest bardziej elastyczny i \u0142atwiejszy w utrzymaniu. Dzi\u0119ki zastosowaniu abstrakcji i interfejs\u00f3w nasza aplikacja staje si\u0119 bardziej modularna, co u\u0142atwia jej rozwijanie i testowanie.&nbsp;<\/p>\n\n\n\n<p>Sprawd\u017amy, jak dobrze jest to zrobione w Angularze. Je\u015bli postanowimy stworzy\u0107 serwis i wstrzykn\u0105\u0107 go w naszym komponencie, Angular sprawi, \u017ce ten <strong>komponent nie b\u0119dzie zale\u017cny od konkretnej implementacji<\/strong> tego serwisu, a jedynie od jego abstrakcji. Oznacza to, \u017ce b\u0119dziemy mogli w ka\u017cdej chwili dostarczy\u0107 inn\u0105 jego implementacj\u0119. Dzi\u0119ki temu Angular automatycznie poniek\u0105d zapewnia, \u017ce zasada odwracania zale\u017cno\u015bci jest spe\u0142niona. Sp\u00f3jrzmy na przyk\u0142ad.&nbsp;<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Component({ \n\n    selector: \"app-some-component\", \n\n    providers: [ \n\n       provide: SomeService, \n\n       useClass: SomeImplementationOfSomeService \n\n    ] \n\n}) \n\nexport class SomeComponent implements OnInit { \n\n    constructor(private someService: SomeService) {} \n\n \n\n    ngOnInit(): void { \n\n        this.someService.someMethod(); \n\n    } \n\n} <\/pre>\n\n\n\n<p>Dzi\u0119ki sekcji <strong>providers <\/strong>i parametrowi <strong>useClass <\/strong>mo\u017cemy podstawi\u0107 dowoln\u0105 implementacj\u0119 serwisu <strong>SomeService <\/strong>w ka\u017cdym komponencie, w kt\u00f3rym tego potrzebujemy. Je\u015bli tego nie zrobimy, komponent wykorzysta domy\u015bln\u0105 implementacj\u0119 serwisu. Mogliby\u015bmy p\u00f3j\u015b\u0107 o krok dalej i potraktowa\u0107 <strong>SomeService <\/strong>z za\u0142o\u017cenia abstrakcyjnie, czyli nie przywi\u0105zywa\u0107 si\u0119 nigdzie do jego domy\u015blnej implementacji i wtedy w ka\u017cdym module\/komponencie podstawia\u0107 interesuj\u0105c\u0105 nas implementacj\u0119 w zale\u017cno\u015bci od kontekstu i wymaga\u0144.&nbsp;<\/p>\n\n\n\n<p>Podsumowuj\u0105c, zasada odwracania zale\u017cno\u015bci jest kluczowa dla tworzenia kodu, kt\u00f3ry jest \u0142atwiejszy w utrzymaniu, bardziej elastyczny i modu\u0142owy. Stosowanie abstrakcji i interfejs\u00f3w pozwala nam unikn\u0105\u0107 silnych zale\u017cno\u015bci mi\u0119dzy r\u00f3\u017cnymi cz\u0119\u015bciami aplikacji i u\u0142atwia nam wymian\u0119 jednej implementacji na inn\u0105.&nbsp;<\/p>\n\n\n\n<p>Wa\u017cne jest r\u00f3wnie\u017c, aby pami\u0119ta\u0107, \u017ce zasada odwracania zale\u017cno\u015bci nie oznacza ca\u0142kowitego uniezale\u017cnienia od konkretnej implementacji. Cz\u0119sto potrzebujemy konkretnej implementacji, ale dzi\u0119ki zastosowaniu abstrakcji i interfejs\u00f3w mo\u017cemy \u0142atwo zamieni\u0107 jedn\u0105 implementacj\u0119 na inn\u0105, bez potrzeby zmieniania ca\u0142ego kodu.&nbsp;<\/p>\n\n\n\n<p><strong>Przeczytaj tak\u017ce:<\/strong><a href=\"\/?p=6617\" target=\"_blank\" data-type=\"URL\" data-id=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/jesli-nie-redux-to-co-zarzadzanie-stanem-aplikacji-w-react\/\" rel=\"noreferrer noopener\"><strong> <\/strong>Je\u015bli nie&nbsp;Redux, to&nbsp;co?&nbsp;Zarz\u0105dzanie stanem aplikacji w&nbsp;React<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Podsumowanie--\">Podsumowanie&nbsp;&nbsp;<\/h2>\n\n\n\n<p>Zasady SOLID w programowaniu obiektowym to nie tylko teoria, ale przede wszystkim praktyka, kt\u00f3ra zmienia spos\u00f3b, w jaki tworzymy oprogramowanie. Ich stosowanie <strong>zapewnia \u0142atwiejsze utrzymanie i rozwijanie kodu, zwi\u0119ksza elastyczno\u015b\u0107, u\u0142atwia testowanie<\/strong>, a tak\u017ce <strong>przyczynia si\u0119 do zmniejszenia koszt\u00f3w<\/strong> i czasu potrzebnego na p\u00f3\u017aniejsze modyfikacje.&nbsp;<\/p>\n\n\n\n<p>Dzi\u0119ki nim unikamy powszechnych problem\u00f3w w projektowaniu, takich jak klasyczny problem \u201e<strong>spaghetti code<\/strong>\u201d, w kt\u00f3rym cz\u0119sto trudno jest zrozumie\u0107 zale\u017cno\u015bci mi\u0119dzy klasami. Zasady SOLID zapewniaj\u0105 lepsz\u0105 separacj\u0119 zada\u0144, co u\u0142atwia prac\u0119 w zespole oraz pozwala na tworzenie bardziej modu\u0142owego kodu. Kod, kt\u00f3ry jest \u0142atwy w utrzymaniu i testowaniu, jest te\u017c bardziej stabilny i odporny na b\u0142\u0119dy. A to z kolei przek\u0142ada si\u0119 na mniejsz\u0105 liczb\u0119 b\u0142\u0119d\u00f3w w produkcie ko\u0144cowym oraz mniejsze ryzyko op\u00f3\u017anie\u0144 w projekcie.&nbsp;<\/p>\n\n\n\n<p>Na koniec warto wspomnie\u0107, \u017ce zasady SOLID nie s\u0105 czym\u015b, co zawsze nale\u017cy stosowa\u0107 w 100%. S\u0105 to narz\u0119dzia, kt\u00f3re mo\u017cna dostosowa\u0107 do konkretnych potrzeb projektu. Wa\u017cne jest jednak, by pami\u0119ta\u0107 o ich istnieniu i korzysta\u0107 z nich, gdy tylko jest to mo\u017cliwe.&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Z pewno\u015bci\u0105 ka\u017cdy programista cho\u0107 raz zastanawia\u0142 si\u0119 nad tym, jak sprawi\u0107, aby jego kod by\u0142 bardziej czytelny, a tworzony system \u2013 skalowalny i elastyczny. Z pomoc\u0105 przychodz\u0105 zasady SOLID, kt\u00f3re stanowi\u0105 \u015bwietn\u0105 podstaw\u0119 w projektowaniu i implementacji system\u00f3w informatycznych. Dzi\u0119ki nim nie musimy wymy\u015bla\u0107 wszystkiego od nowa, poniewa\u017c zasady te maj\u0105 sprawdzone narz\u0119dzia, kt\u00f3re pozwalaj\u0105 nam na tworzenie optymalnego kodu.<\/p>\n","protected":false},"author":171,"featured_media":29846,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"iawp_total_views":183,"footnotes":""},"categories":[1,582],"tags":[613],"offering":[522],"class_list":["post-29845","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artykuly","category-technologie","tag-angular-2","offering-tech-blog"],"acf":[],"_links":{"self":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/29845","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/users\/171"}],"replies":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/comments?post=29845"}],"version-history":[{"count":3,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/29845\/revisions"}],"predecessor-version":[{"id":33945,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/29845\/revisions\/33945"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media\/29846"}],"wp:attachment":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media?parent=29845"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/categories?post=29845"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/tags?post=29845"},{"taxonomy":"offering","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/offering?post=29845"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}