<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Wzorce Projektowe - bdabek.pl</title>
	<atom:link href="https://www.bdabek.pl/tag/wzorce-projektowe/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.bdabek.pl/tag/wzorce-projektowe/</link>
	<description>Bartosz Dąbek</description>
	<lastBuildDate>Sat, 03 Dec 2022 11:12:22 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.bdabek.pl/wp-content/uploads/2020/10/cropped-5986134a-46ba-41ac-9c82-bb4ffb3a7bf3_200x200-1-150x150.png</url>
	<title>Wzorce Projektowe - bdabek.pl</title>
	<link>https://www.bdabek.pl/tag/wzorce-projektowe/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>✔️ Spring Framework &#8211; Jak Bronić Się Przed Oddaniem Kontroli Frameworkowi? ⛔️⛔️</title>
		<link>https://www.bdabek.pl/spring-framework-jak-bronic-sie-przed-oddaniem-kontroli-frameworkowi/</link>
					<comments>https://www.bdabek.pl/spring-framework-jak-bronic-sie-przed-oddaniem-kontroli-frameworkowi/#respond</comments>
		
		<dc:creator><![CDATA[Bartosz Dąbek]]></dc:creator>
		<pubDate>Sat, 28 Nov 2020 11:00:46 +0000</pubDate>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Wzorce Projektowe]]></category>
		<guid isPermaLink="false">https://www.bdabek.pl/?p=2032</guid>

					<description><![CDATA[<p>Spring Framework powstał jako alternatywa dla programowania aplikacji z użyciem Javy EE w 2002 roku. Dziś jest kompleksowym rozwiązaniem dla wielu innych problemów a jego znajomość wśród developerów Javy jest już standardem. Cześć  Spring sprawia, że programowanie w Javie jest szybsze, łatwiejsze i bezpieczniejsze dla każdego. Spring skupia się na szybkości, prostocie i produktywności, dzięki&#8230;&#160;<a href="https://www.bdabek.pl/spring-framework-jak-bronic-sie-przed-oddaniem-kontroli-frameworkowi/" rel="bookmark">Dowiedz się więcej &#187;<span class="screen-reader-text">✔️ Spring Framework &#8211; Jak Bronić Się Przed Oddaniem Kontroli Frameworkowi? ⛔️⛔️</span></a></p>
<p>Artykuł <a href="https://www.bdabek.pl/spring-framework-jak-bronic-sie-przed-oddaniem-kontroli-frameworkowi/">✔️ Spring Framework &#8211; Jak Bronić Się Przed Oddaniem Kontroli Frameworkowi? ⛔️⛔️</a> pochodzi z serwisu <a href="https://www.bdabek.pl">bdabek.pl</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Spring Framework</strong> powstał jako alternatywa dla programowania aplikacji z użyciem Javy EE w 2002 roku. Dziś jest kompleksowym rozwiązaniem dla wielu innych problemów a <strong>jego znajomość wśród developerów Javy jest już standardem</strong>.</p>
<hr />
<h3>Cześć <img decoding="async" class="emoji" role="img" draggable="false" src="https://s.w.org/images/core/emoji/12.0.0-1/svg/1f642.svg" alt="&#x1f642;" /></h3>
<blockquote><p>Spring sprawia, że programowanie w Javie jest szybsze, łatwiejsze i bezpieczniejsze dla każdego. Spring skupia się na szybkości, prostocie i produktywności, dzięki czemu stał się najpopularniejszym na świecie frameworkiem Java.<br />
<cite>spring.io</cite></p></blockquote>
<p>Cytat powyżej doskonale opisuje znaczenie Springa w dzisiejszym świecie (2020). Spring jest wszędzie &#8211; niezależnie od tego, czy chodzi o <a href="https://netflixtechblog.com/netflix-oss-and-spring-boot-coming-full-circle-4855947713a0" target="_blank" rel="noopener noreferrer">streaming telewizji</a>, <a href="https://tanzu.vmware.com/big-data/press-release/mercedes-benz-teams-with-pivotal-to-bring-connected-car-app-to-life" target="_blank" rel="noopener noreferrer">samochody z dostępem do internetu</a>, <a href="https://tech.target.com/2018/12/18/spring-feign.html" target="_blank" rel="noopener noreferrer">zakupy online</a>, czy też niezliczone inne innowacyjne rozwiązania. Dzięki swojej elastyczności, ilości projektów jakie rozwija (w sposób zadowalający programistów na całym świecie) oraz społeczeństwa (<em>community</em>) jakie zostało wokół niego stworzone, z pewnością można stwierdzić, że <strong>Spring Framework jest częścią obecnego świata</strong>.</p>
<p>Należy jednak pamiętać, że nadal <strong>jest to tylko framework a rynek bywa nieprzewidywalny</strong>. Co w przyadku, kiedy okaże się, że Spring jest już przeżytkiem? <strong>Czy będziesz musiał przepisać całą aplikację od zera tylko dlatego, że pozwoliłeś się mu uwięzić</strong>?</p>
<p>W dzisiejszym artykule:</p>
<ul>
<li><a href="#Elastyczność a kontrola"><strong>Elastyczność a kontrola</strong></a></li>
<li><a href="#Gdzie leży granica?"><strong>Gdzie leży granica?</strong></a></li>
<li><a href="#Technika obrony przed oddaniem władzy w ręce Springa"><strong>Technika obrony przed oddaniem władzy w ręce Springa</strong></a></li>
</ul>
<hr id="Elastyczność a kontrola" />
<h2><strong>Elastyczność a kontrola</strong></h2>
<p>Spring Boot, czyli jeden z podprojektów springa, który drastycznie poprawia produktywność. Pozwala na postawinie aplikacji od zera za pomocą dosłownie kilku kliknięć przy pomocy <a href="https://start.spring.io/" target="_blank" rel="noopener noreferrer">Spring Initializr</a>. W dobie, kiedy duży nacisk jako IT kładziemy na architekturę, gdzie każdy moduł ma konkretną odpowiedzialność (mikroserwisy), Spring Boot jest świetnym wyborem bo dostarcza nam przygotowany projekt, który musimy tylko odpowiednio zakodować.</p>
<p>Skupiam się szczególnie na projekcie Spring Boot&#8217;owym, ale <strong>sprawa zabetonowania kodu frameworkiem</strong> równomiernie dotyczy każdego innego projektu. Generalnie chodzi o komponenty, gdzie w dużej mierze polegamy na sercu Springa &#8211; IoC, AOP. Zyskujemy dzięki temu dużą elastyczność bo możemy szybko dostarczać funkcjonalności, które chce biznes, ale jednocześnie płacimy za to tym, że polegamy na mechanizmach frameworka.</p>
<p>Czy jest z tym jakiś problem? Dopóki wszystko działa to nie. Problem pojawia się gdy coś przestaje działać. Wtedy okazuje się, że z 10-osobowego zespołu, jedna&#8230; może dwie osoby, mniej lub więcej wiedzą co dzieje się pod spodem (dobrze jeżeli chociaż tyle osób się znajdzie) i umieją rozwiązać problem. <strong>To nie znaczy, że mamy wywalić wszystkie frameworki z naszego kodu i napisać je samemu</strong>. Efekt końcowy będzie taki sam. Osoby, które napiszą daną rzecz za jakiś czas są nieobecne &#8211; inny projekt / zmiana pracy / emerytura.</p>
<hr id="Gdzie leży granica?" />
<h2><strong>Gdzie leży granica?</strong></h2>
<p><strong>Niezaprzeczalnym faktem jest, że w znacznej większości przyapadków nie będziesz przepisywać funkcjonalności, które dostarczają Ci zewnętrzni dostawcy</strong> (biblioteki / frameworki). Dobrze byłoby wiedzieć co dzieje się pod spodem danego komponentu, jakie są kompromisy jego użycią &#8211; co zyskujemy a co tracimy. Niestety, znajomość, co dzieje się pod spodem, często nie jest adekwatna. Żeby nie teoryzować już za wiele i przejść do konkretów, to moim zdaniem <strong>granice wyznacza czas</strong>.</p>
<p>Załóżmy, że na projekcie używasz Spring Boota i działasz w branży księgowości. Dostałeś zadanie aby dodać nową funkcjonalność obsługi subskrypcji (użytkownicy co miesiąc płacą za usługę księgowości). Dla uproszczenia przyjmimy, że taka subskrypcja może być utworzona (użytkownik dołącza do planu księgowości), wyszukiwana (np. przez adminów systemu), przedłużana oraz może nastąpić rezygnacja przez użytkownika.</p>
<p>Na pierwszy rzut oka, typowy CRUD, ale tak nie jest. Nie będziemy wchodzić w domenę bo to nie jest temat tego artykułu, ale pozwól, że przedstawię Ci kilka argumentów utrudniających domenę:</p>
<ul>
<li>co z użytkownikami, którzy są stałymi klientami (zniżki / rabaty)</li>
<li>użytkownicy, którzy wykupuja plan na kilka lat z góry (zniżki / rabaty)</li>
<li>różne plany subskrypcji (np. najdroższy plan posiada support dostępny 24/7)</li>
<li>subskrypcje w wersji trial (14/30 dni)</li>
</ul>
<p>Znalazłoby się jeszcze kilka(naście) innych utrudnień, ale nie do tego zmierzamy. <strong>Jak byś to zaczął opędzlowywać w springu?</strong> @RestController, @Service, @Component nad każdą z klas, później dla metod, w których może wystąpić rollback @Transactional i jazda? Po miesiącu kodowania okazuje się, że Twój kod jest i działa. Tylko problem, że jest on w 100% zależny od Springa i jego mechanizmów.</p>
<p>Czy jest złoty środek, który pomoże w walce o niezależność kodu?</p>
<hr id="Technika obrony przed oddaniem władzy w ręce Springa" />
<h2><strong>Technika obrony przed oddaniem władzy w ręce Springa</strong></h2>
<p>Skoro znamy już problem i wiemy, że Spring Framework daje nam dużo benefitów ale jednocześnie częściowo uniezależnia nas od siebie jako dostawcy, to jak możemy się tego ustrzec? Mam zarówno dobrą jak i złą wiadomość. Zacznijmy od złej &#8211; <strong>nie da się tego ustrzec.</strong> Dobra natomaist jest taka, że możemy to załagodzić.</p>
<p>Dlaczego nie możemy się ustrzec? Używając Springa w naszych aplikacjach zapewne będziemy chcieli skorzystać z jego głównych zalet &#8211; kontenera IoC czy też mechanizmu AOP (<em>Aspect Oriented Programming</em>). Mechanizmy wokół kontenera IoC są odpowiedzialne za inicjalizację, konfigurowanie i składanie obiektów (beanów), a sam kontener zarządza ich cyklem życia co znacznie ułatwia programowanie. Natomiast, jeżeli chodzi o AOP &#8211; jest to mechanizm wykorzystywany chociażby przy <a href="https://www.bdabek.pl/jak-dziala-adnotacja-transactional-w-springu/" target="_blank" rel="noopener noreferrer">transakcjach</a>, logowaniu, obsłudze wyjątków czy też kwestiach bezpieczeństwa (<em>security</em>).</p>
<h4>To jak załagodzić standardowe flow?</h4>
<p>Do tego celu przyda nam się:</p>
<ul>
<li>umiejętność tworzenia konfiguracji i beanów samodzielnie,</li>
<li>wiedza jak działa wzorzec projektowy fasada.</li>
</ul>
<p>I tyle. Te dwie rzeczy pomogą nam częściowo uwolnić się od zależności frameworka. <strong>Lecimy z przykładem wcześniej wspomnianych subskrypcji</strong>.</p>
<p>Na samym początku trzeba zdefiniować fasadę, która przykrywa wszystkie istotne akcje biznesowe (utworzenie, wyszukanie, przedłużenie, rezygnację):</p><pre class="crayon-plain-tag">public class CompanySubscriptionFacade {

	private final CreateNewCompanySubscriptionService createNewCompanySubscriptionService;
	private final UnsubscriptionService unsubscribeFromSubscriptionService;
	private final CompanySubscriptionRepository companySubscriptionRepository;

	CompanySubscriptionFacade(CreateNewCompanySubscriptionService createNewCompanySubscriptionService,
							  UnsubscriptionService unsubscribeFromSubscriptionService,
							  CompanySubscriptionRepository companySubscriptionRepository) {
		this.createNewCompanySubscriptionService = createNewCompanySubscriptionService;
		this.unsubscribeFromSubscriptionService = unsubscribeFromSubscriptionService;
		this.companySubscriptionRepository = companySubscriptionRepository;
	}

	public Result createCompanySubscription(UUID subscriberId) {
		return createNewCompanySubscriptionService.create(subscriberId);
	}

	public CompanySubscription update(CompanySubscription sub) {
		return companySubscriptionRepository.save(sub);
	}

	public Result unsubscribe(SubscriberId subscriber, SubscriptionId subscription) {
		return unsubscribeFromSubscriptionService.unsub(subscriber, subscription);
	}

	public Optional&lt;CompanySubscription&gt; findSubscription(SubscriptionId subscriberId) {
		return companySubscriptionRepository.findBy(subscriberId);
	}
}</pre><p>Jest to czysta klasa Javowa, podobnie zresztą jak CreateNewCompanySubscriptionService oraz UnsubscriptionService (z perspektywy kodu Javowego przed konfiguracją, która za chwilę nastąpi). Teraz czas na samodzielną konfigurację:</p><pre class="crayon-plain-tag">@Configuration
public class CompanySubscriptionConfiguration {

	/**
	 * wykorzystywane w testach
	 */
	public CompanySubscriptionFacade companySubscriptionFacade() {
		InMemoryCompanySubscriptionRepository companySubscriptionRepository = new InMemoryCompanySubscriptionRepository();

		return companySubscriptionFacade(
				createNewCompanySubscriptionService(companySubscriptionRepository),
				enrollToCompanySubscription(companySubscriptionRepository, new NoOpDomainEventPublisher()),
				companySubscriptionRepository);
	}

	@Bean
	CompanySubscriptionFacade companySubscriptionFacade(CreateNewCompanySubscriptionService createNewCompanySubscriptionService,
														UnsubscriptionService unsubscriptionService,
														CompanySubscriptionRepository companySubscriptionRepository) {
		return new CompanySubscriptionFacade(createNewCompanySubscriptionService, unsubscriptionService, companySubscriptionRepository);
	}

	@Bean
	CompanySubscriptionRepository companySubscriptionRepository() {
		return new InMemoryCompanySubscriptionRepository();
	}

	@Bean
	UnsubscriptionService unsubscriptionService(CompanySubscriptionRepository companySubscriptionRepository,
													  DomainEventPublisher domainEventPublisher) {
		return new UnsubscriptionService(companySubscriptionRepository, domainEventPublisher);
	}

	@Bean
	CreateNewCompanySubscriptionService createNewCompanySubscriptionService(CompanySubscriptionRepository companySubscriptionRepository) {
		return new CreateNewCompanySubscriptionService(companySubscriptionRepository);
	}
}</pre><p>Klasa konfiguracyjna natomiast jest właśnie tą klasą, która odpowiada za utworzenie beanów. Sama posiada adnotację @Configuration oraz <strong>jest odpowiedzialna za prawidłowe powiązanie zależności</strong>.</p>
<p>Jeżeli chcesz dodać wsparcie dla transakcji / aspektów, które wykorzystują mechanizmy Springa to nie ma z tym najmniejszego problemu. Wystarczy że dodasz nowy @Aspect dla nowego aspektu, a w przypadku transakcji @Transactional na odpowiednim beanie lub jednej z metod. Posiadasz nadal pełne wsparcie mechanizmów Springa a jednocześnie nie betonujesz kodu na wymianę na inny framework. Będzie się to wiązało z przepisaniem konfiguracji (i oczywiście wsparcia dla ewentualnie napisanych aspektów / transakcji przez owy framework).</p>
<hr />
<h2>Podsumowanie</h2>
<p><a href="https://www.bdabek.pl/spring-boot-i-logi-ustawienia-logbacka/lightbulb/" rel="attachment wp-att-976" data-slb-active="1" data-slb-asset="1379905354" data-slb-internal="976"><img decoding="async" class="aligncenter wp-image-976 size-thumbnail lazyloaded" src="https://cdn.shortpixel.ai/client/to_webp,q_glossy,ret_img,w_150,h_150/https://www.bdabek.pl/wp-content/uploads/2020/05/Lightbulb-150x150.jpg" alt="" width="150" height="150" data-src="https://cdn.shortpixel.ai/client/to_webp,q_glossy,ret_img,w_150,h_150/https://www.bdabek.pl/wp-content/uploads/2020/05/Lightbulb-150x150.jpg" /></a></p>
<p>Koncept, który tu przedstawiłem jest poniekąd inspirowany podejściem jakie może być spotkane w <a href="https://www.bdabek.pl/architektura-hexagonalna/" target="_blank" rel="noopener noreferrer">architekturze hexagonalnej</a>. Jeżeli chciałbyś dowiedzieć się więcej na ten temat to w źródłach zostawiam <a href="https://youtu.be/ILBX9fa9aJo" target="_blank" rel="noopener noreferrer">link</a> do świetnej prezentacji Jakuba Nabrdalika z warszawskiego JUGA oraz dodatkowo takie podejście jest przedstawione w bardzo dobrym kursie <a href="https://droganowoczesnegoarchitekta.pl/" target="_blank" rel="noopener noreferrer">DNA</a> (tylko drogim).</p>
<p>Co do samego podejścia. Plusy? Sami kontrolujemy tworzenie beanów, więc doskonale wiemy, co jest tworzone i jakie są zależności. Przy klasach z większą ilością zależności <strong>szybciej dostrzegamy problemy z kodem </strong>bo sami musimy zarządzać zależnościami. <strong>Minusem natomiast jest to, że musimy wykonać więcej pracy.</strong> Jeżeli wszystkie klasy w naszym projekcie są bean&#8217;ami (najczęściej występuje to przy wykorzystaniu <a href="https://www.bdabek.pl/architektura-warstwowa-zlo-czy-dobro/" target="_blank" rel="noopener noreferrer">architektury warstwowej</a>), to prawdopodobnie lepiej już oddać władze w ręce Springa i niech się dzieje co się ma dziać.</p>
<p>Źródła:</p>
<ul>
<li><strong><a href="https://spring.io/" target="_blank" rel="noopener noreferrer">Spring</a></strong></li>
<li><strong><a href="https://youtu.be/ILBX9fa9aJo" target="_blank" rel="noopener noreferrer">WJUG #211 &#8211; [PL] Modularity and hexagonal architecture in real life: Jakub Nabrdalik</a></strong></li>
</ul>
<div id="wpd-post-rating" class="wpd-not-rated">
<div class="wpd-rating-wrap"></div>
</div>
<p>Artykuł <a href="https://www.bdabek.pl/spring-framework-jak-bronic-sie-przed-oddaniem-kontroli-frameworkowi/">✔️ Spring Framework &#8211; Jak Bronić Się Przed Oddaniem Kontroli Frameworkowi? ⛔️⛔️</a> pochodzi z serwisu <a href="https://www.bdabek.pl">bdabek.pl</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bdabek.pl/spring-framework-jak-bronic-sie-przed-oddaniem-kontroli-frameworkowi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Wzorzec Strategii 🙏. Jak Czytelnie Pisać Kod? 🤔</title>
		<link>https://www.bdabek.pl/wzorzec-strategii-%f0%9f%99%8f-jak-czytelnie-pisac-kod-%f0%9f%a4%94/</link>
					<comments>https://www.bdabek.pl/wzorzec-strategii-%f0%9f%99%8f-jak-czytelnie-pisac-kod-%f0%9f%a4%94/#comments</comments>
		
		<dc:creator><![CDATA[Bartosz Dąbek]]></dc:creator>
		<pubDate>Sat, 31 Oct 2020 11:00:28 +0000</pubDate>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Wzorce Projektowe]]></category>
		<guid isPermaLink="false">https://www.bdabek.pl/?p=1800</guid>

					<description><![CDATA[<p>Pisanie kodu nie jest rzeczą trudną. Pisanie kodu, który będzie działać prawidłowo i będzie rozumiany przez innych jest trudniejsze. Natomiast kod, który spełnia poprzednie właściwości a dodatkowo jest utrzymywalny i łatwo wymienialny jest już pewnego rodzaju sztuką &#8211; sztuką programowania. Cześć  Dzisiejszy artykuł będzie poświęcony pisaniu dobrego kodu. Zdefiniujemy czym jest dobry kod i jak&#8230;&#160;<a href="https://www.bdabek.pl/wzorzec-strategii-%f0%9f%99%8f-jak-czytelnie-pisac-kod-%f0%9f%a4%94/" rel="bookmark">Dowiedz się więcej &#187;<span class="screen-reader-text">Wzorzec Strategii 🙏. Jak Czytelnie Pisać Kod? 🤔</span></a></p>
<p>Artykuł <a href="https://www.bdabek.pl/wzorzec-strategii-%f0%9f%99%8f-jak-czytelnie-pisac-kod-%f0%9f%a4%94/">Wzorzec Strategii 🙏. Jak Czytelnie Pisać Kod? 🤔</a> pochodzi z serwisu <a href="https://www.bdabek.pl">bdabek.pl</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Pisanie kodu nie jest rzeczą trudną. Pisanie kodu, który będzie działać prawidłowo i będzie rozumiany przez innych jest trudniejsze. Natomiast kod, który spełnia poprzednie właściwości a dodatkowo jest utrzymywalny i łatwo wymienialny jest już pewnego rodzaju sztuką &#8211; <strong>sztuką programowania</strong>.</p>
<hr />
<h3>Cześć <img decoding="async" class="emoji" role="img" draggable="false" src="https://s.w.org/images/core/emoji/12.0.0-1/svg/1f642.svg" alt="&#x1f642;" /></h3>
<p>Dzisiejszy artykuł będzie poświęcony pisaniu dobrego kodu. Zdefiniujemy czym jest dobry kod i jak go pisać. W artykule, oprócz aspektów technicznych poruszę również kwestie mentalne &#8211; w końcu kod pisany jest przez ludzi. Następnie inni go czytają, modyfikują lub usuwają i przepisują od nowa. I tak kręci się nasz programistyczny świat <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>W dzisiejszym artykule:</p>
<ul>
<li><a href="#Czym jest dobry kod?"><strong>Czym jest dobry kod?</strong></a></li>
<li><a href="#Wzorzec Strategii a Dobry Kod"><strong>Wzorzec Strategii a Dobry Kod</strong></a></li>
<li><a href="#Jak zastosować to w praktyce?"><strong>Jak zastosować to w praktyce?</strong></a></li>
</ul>
<hr id="Czym jest dobry kod?" />
<h2><strong>Czym jest dobry kod?</strong></h2>
<p>Aby pisać dobry kod należy zdefiniować czym on w ogóle jest. Moim zdaniem dobry kod to taki, który po pierwsze jest <strong>łatwy w zrozumieniu</strong>. Wiem, że czasami rozwiązujemy problemy, które nie są trywialne i faktycznie w tych przypadkach ciężko o pisanie kodu łatwego w zrozumieniu. Jednak w większości przypadków nasz kod jest sekwencją procedur, która w sposób mniej lub bardziej spójny spełnia wymagania biznesowe.</p>
<p><a href="https://www.bdabek.pl/?attachment_id=1947" rel="attachment wp-att-1947"><img fetchpriority="high" decoding="async" class="aligncenter wp-image-1947" src="https://www.bdabek.pl/wp-content/uploads/2020/10/quality-triangle.jpg" alt="" width="400" height="345" srcset="https://www.bdabek.pl/wp-content/uploads/2020/10/quality-triangle.jpg 697w, https://www.bdabek.pl/wp-content/uploads/2020/10/quality-triangle-300x259.jpg 300w" sizes="(max-width: 400px) 100vw, 400px" /></a></p>
<p>Drugą metryką dobrego kodu jest <strong>możliwość jego zmiany lub jego całkowita wymiana</strong> bez obawy popsucia innych, teoretycznie niezależnych obszarów. Łatwo to brzmi na papierze. W praktyce jest to zadanie bardzo trudne do osiągnięcia. Dlaczego tak się dzieje? Wydaje mi się, że częściowo jest to pochodna tego jak angażujemy się w projekt. Z autopsji wiem, że występują sytuacje gdy nam się po prostu nie chce myśleć i <strong>piszemy aby było</strong>. Czy możemy temu zaradzić? Chyba nie. Aczkolwiek <strong>z pewnością możemy to załagodzić</strong> wykorzystując wzorzec strategii.</p>
<p><strong>Kolejnym problemem z metryką zmiany lub całkowitej wymiany jest jej mierzalność</strong>. Otóz to czy dany kod jest łatwy do zmiany (<em>rozszerzenia</em>) czy też do całkowitej wymiany wyjdzie dopiero przy faktycznej potrzebie. Czasami na taką potrzebę czekamy tydzień a czasami 6 miesięcy. O ile w pierwszym przypadku zmianą może się zająć osoba, która implementowała początkowe rozwiązanie o tyle w drugim przypadku bardzo często będzie to osoba nie związana z początkową implementacją.</p>
<p>Jak widzisz pisanie dobrego kodu jest sztuką zrozumienia. Kod który piszemy będzie czytany i zarządzany przez innych. <strong>Największym wyzwaniem programisty jest aby napisać kod, który w jasny sposób przekaże intencje i będzie użyty we właściwym kontekście</strong>. Istnieją zasady i konwencje, które programiści powinni znać i stosować. Pomagają one dwóm zupełnie różnym osobom (programistom) na wzajemne zrozumienie bez względu na narodowość czy przekonania. Wydaje mi się, że <em>must-have</em> każdego programisty to przeczytanie <strong><a href="https://www.amazon.com/Robert-C.-Martin/e/B000APG87E" target="_blank" rel="noopener noreferrer">lektur wujka Boba o czystym kodzie</a></strong>. Większość programistów na całym świecie przeczytała te lektury (<em>przynajmniej Czysty Kod</em>) dzięki czemu w naszym programistycznym świecie mamy wspólne pojęcie czym jest czysty kod i jak go tworzyć.</p>
<p><a href="https://www.bdabek.pl/?attachment_id=1946" rel="attachment wp-att-1946"><img decoding="async" class="aligncenter size-full wp-image-1946" src="https://www.bdabek.pl/wp-content/uploads/2020/10/clean-code-rules.png" alt="" width="1489" height="1031" srcset="https://www.bdabek.pl/wp-content/uploads/2020/10/clean-code-rules.png 1489w, https://www.bdabek.pl/wp-content/uploads/2020/10/clean-code-rules-300x208.png 300w, https://www.bdabek.pl/wp-content/uploads/2020/10/clean-code-rules-1024x709.png 1024w, https://www.bdabek.pl/wp-content/uploads/2020/10/clean-code-rules-768x532.png 768w" sizes="(max-width: 1489px) 100vw, 1489px" /></a></p>
<hr id="Wzorzec Strategii a Dobry Kod" />
<h2><strong>Wzorzec Strategii a Dobry Kod</strong></h2>
<p>Strategia czyli jeden z wzorców programowania obiektowego, którego raczej nie muszę i nie chcę szczegółowo przedstawiać. Jeżeli ktoś chce sobie przypomnieć jak ten wzorzec działa to odsyłam m.in. do <strong><a href="https://refactoring.guru/design-patterns/strategy" target="_blank" rel="noopener noreferrer">tego linka</a></strong>. <strong>W dużym skrócie jest to wzorzec behawioralny, który pozwala na zdefiniowanie rodziny (zbiorów) algorytmów, umieszczenie każdego z nich w osobnej klasie i uczynienie ich obiektami wymiennymi</strong>.</p>
<p><a href="https://www.bdabek.pl/?attachment_id=1951" rel="attachment wp-att-1951"><img decoding="async" class="aligncenter size-full wp-image-1951" src="https://www.bdabek.pl/wp-content/uploads/2020/10/strategy-pattern.png" alt="" width="669" height="344" srcset="https://www.bdabek.pl/wp-content/uploads/2020/10/strategy-pattern.png 669w, https://www.bdabek.pl/wp-content/uploads/2020/10/strategy-pattern-300x154.png 300w" sizes="(max-width: 669px) 100vw, 669px" /></a></p>
<p>Co strategia ma do dobrego kodu? Moim zdaniem kluczowe jest zdanie <em><strong>rodzina algorytmów</strong></em>. Może to być algorytm do obliczania ceny produktu w zależności który klient dokonuje zakupu lub obliczanie ceny pizzy w zależności od tego jakie składniki zostały użyte i jaki rabat będzie udzielony. Rodziną algorytmów równie dobrze może być wybór <strong>implementacji</strong> do obliczania drogi, jaką mamy do pokonania w zależności czy jedziemy autem, rowerem czy pokonujemy trasę pieszo (<em>przykład: google maps</em>). Przykłady użycia można mnożyć.</p>
<p>Rozkładając definicję <strong>rodzina algorytmów na łopatki</strong> to okaże się, że algorytm jest to <strong>wykonanie logiki pewnej decyzji biznesowej</strong>. A co się dzieje z decyzjami biznesowymi? <strong>Zmieniają się</strong> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> . Nie zawsze &#8211; dobrym przykładem mogą być jakieś regulacje prawne, które od X lat są niezmienne i szansa na to że ulegną zmianie jest nikła. Jednak znaczna większość decyzji biznesowych ulega zmianom. Są doprecyzowywane, usuwane, dodawane, zamieniane na inne.</p>
<p><a href="https://www.bdabek.pl/?attachment_id=1953" rel="attachment wp-att-1953"><img decoding="async" class="aligncenter size-full wp-image-1953" src="https://www.bdabek.pl/wp-content/uploads/2020/10/requirement-changes.jpg" alt="" width="639" height="199" srcset="https://www.bdabek.pl/wp-content/uploads/2020/10/requirement-changes.jpg 639w, https://www.bdabek.pl/wp-content/uploads/2020/10/requirement-changes-300x93.jpg 300w" sizes="(max-width: 639px) 100vw, 639px" /></a></p>
<p><strong>Dostrzegasz korelację pomiędzy wzorcem strategii a decyzjami biznesowymi</strong>? Ja tak. Wykorzystując strategie nasze oprogramowanie jest bardziej elastyczne. Jeżeli miałbym przytoczyć zasady <strong><a href="https://en.wikipedia.org/wiki/SOLID" target="_blank" rel="noopener noreferrer">SOLID</a> </strong>to kod, który wytworzymy z automatu przyjmuje jedną z zasad [1] a drugą [2] w momencie gdy pomyślimy i nie upychamy wszystkiego do jednego worka:</p>
<ul>
<li><strong>Open-closed principle [1]</strong></li>
<li><strong>Single-responsibility principle [2]</strong></li>
</ul>
<p>Dzięki temu nasz kod będzie otwarty na rozszerzenie. Będziemy mogli dowolnie dodawać nowe funkcjonalności przez dodanie nowego <em>algorytmu</em> i w jednym miejscu w kodzie definiować nowe rozszerzenie (wybór strategii). Wybór strategii może być instrukcją <strong>switch-case</strong>, <strong>prostym warunkiem if</strong> lub w bardziej hardcorowych przypadkach konfiguracją wyekstraktowaną do zewnętrznego pliku. Jednak moim zdaniem ostatnia opcja nie sprawdza się w przypadku rozwiązań biznesowych, gdzie wiemy dokładnie kto jest naszym klientem (nie jest to oprogramowanie kierowane do wszystkich).</p>
<hr id="Jak zastosować to w praktyce?" />
<h2><strong>Jak zastosować to w praktyce?</strong></h2>
<p>To jest chyba najtrudniejsza część tego artykułu. Nie mogę dać Ci konkretnych wytycznych <strong>kiedy</strong> zastosować wzorzec strategii bo nie znam domeny w jakiej pracujesz. Nie wiem co jest elementem zmiennym i z czego biznes czerpie największą wartość. Co jest jeszcze trudniejsze &#8211; często bywa tak, że chociaż wiesz w jakiej domenie się obracasz to nie jesteś w niej ekspertem i nie masz pojęcia czy wymaganie, które właśnie implementujesz może być zmieniane. I co masz zrobić?</p>
<p>Teraz napiszę kilka zdań, z którymi część może się nie zgodzić (<em>być może sam za jakiś czas stwierdzę, że to jest bez sensu</em>). Zakładając, że nie możesz wyciągnąć więcej informacji ze strony biznesu (po prostu nie możesz dowiedzieć się więcej o domenie) musisz <strong>działać na czuja</strong> i <strong>wszędzie tam gdzie czujesz, że kontekst może być zmienialny stostuj wzorzec strategii</strong>.</p>
<p>Aby lepiej to zobrazować podam Ci przykład. Załóżmy że pracujesz dla sklepu, który zajmuje się produkcją i dystrybucją biurek. Do tej pory sklep działał lokalnie i cała sprzedaż opierała się o kontakt telefoniczny. Teraz przechodzą w sprzedaż online. Twoim zadaniem jest implementacja logiki <strong>prostego</strong> systemu płatności. Ma to być dostarczone szybko (każda stracona godzina to $). W celu uproszczenia załóżmy, że cały system jest już zrobiony a Ty musisz zaimplementować ten jeden mały feature.</p>
<p>Musisz zaimplementować płatność, która może być realizowana za pomocą płatności bankowej lub blika. Kiedy użytkownicy dokonują płatności przy pomocy blika, dodatkowo zyskują punkty lojalnościowe (taka promocja). Kod do tego może wyglądać następująco:</p><pre class="crayon-plain-tag">public OrderResult makePurchase() {
  OrderResult result = purchaseDesk();

  // implementacja płatności
  makePayment(result);

  return result;
}

private void makePayment(OrderResult result) {
  if (result.isWeb()) {
    result.setPaymentMethod(PaymentType.BANK_ACC);
    notificationSystem.sendEmailNotification();    
  } else if (result.isBlik()) {
    result.setPaymentMethod(PaymentType.BLIK);
    result.addLoyalityPoint();
    notificationSystem.sendMobileNotification();
  }  

  throw new UnsupportedOperationException("Payments other than Web and Blik are not supported");
}</pre><p>Nie wchodźmy w mantry tego czy ten kod ma sens czy nie. Chodzi o fakt, że teraz dochodzi kolejne rozszerzenie. Sklep dostaje feedback, że wybór płatności jest zbyt skąpy i klienci chcą aby dodano szybkie przelewy oraz możliwość przelewu offline (<em>co to za klienci?? <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </em>). Sterowany czasem możesz iść w kierunku dodawania kolejnych if&#8217;ów do metody <em>makePayment(&#8230;)</em>.</p><pre class="crayon-plain-tag">private void makePayment(OrderResult result) { 
  if (result.isWeb()) { 
  ....

  else if (result.isFastPayment()) {
    result.setPaymentMethod(PaymentType.FAST_PAYMENT);
    metricService.measureUsage();
  } else if (result.isOffline()) {
    result.setPaymentMethod(PaymentType.OFFLINE);
    result.extractLoyalityPoint();
    metricService.addDumbness();
    notificationSystem.sendSmsNotification();
    notificationSystem.informAboutLegacyPaymentMethod();
  }

  throw new UnsupportedOperationException("Payments other than Web and Blik are not supported"); 
}</pre><p>Będę z Tobą szczery &#8211; nie mam z tym problemu do czasu kiedy logika metody <em>makePayment(&#8230;)</em> zaczyna się rozrastać, tak jak w naszym wyimaginowanym przypadku. Kolejny problem to kiedy różne osoby modyfikowały ten kod i teraz żadna inna (nawet te, które ten kod pisały) nie chce tego fragmentu ruszać bo nie do końca wie jak to działa i boi się zepsuć. Byłem w tym miejscu w kodzie produkcyjnym. Nadal się z tym spotykam i myślę, że każdy kto pisze software zna to uczucie. Wiesz, że przydałoby się zrefaktoryzować ten fragment kodu ale nie możesz bo nie ma czasu i zasobów a żeby zrozumieć całość trzeba będzie wejść głęboko w logikę.</p>
<p>Gdybyśmy zamiast tego od razu wyczuli możliwość zmian, zaoszczędzilibyśmy późniejszych bólów. Oczywiście zdaję sobie sprawę, że niesie to inne problemy, typu przekazywanie zależności do konkretnych strategii (coś czego nie uwzględniłem w przykładzie poniżej). Można to załatwić w najprostszy sposób, czyli wstrzykując zależność przez konstruktor. Jednak najważniejsze pytanie które się pojawia i na które nie umiem Ci odpowiedzieć &#8211; <strong>czy warto</strong>? Według mnie w wielu przypadkach tak ale jednak nie zawsze.</p><pre class="crayon-plain-tag">public OrderResult makePurchase() {
  OrderResult result = purchaseDesk();

  PaymentStrategy strategy = choosePaymentStrategy(orderResult);
  strategy.makePayment(orderResult);

  return orderResult;
}

private PaymentStrategy choosePaymentStrategy(OrderResult result) {
  if (result.isWeb()) {
    return new WebPaymentStrategy();
  } else if (result.isBlik()) {
    return new BlikPaymentStrategy();
  }  else if (result.isFastPayment()) {
    return new FastPaymentStrategy();
  } else if ( result.isOffline()) {
    return new OfflinePaymentStrategy();
  }   
  throw new UnsupportedOperationException("");
}

// przykładowa implementacja Strategii
class WebPaymentStrategy implements PaymentStrategy {
  @Override
  public void makePayment(OrderResult orderResult) {
    result.setPaymentMethod(PaymentType.BANK_ACC); 
    notificationSystem.sendEmailNotification(); 
  }
}</pre><p><a href="https://www.bdabek.pl/?attachment_id=1967" rel="attachment wp-att-1967"><img decoding="async" class="aligncenter size-full wp-image-1967" src="https://www.bdabek.pl/wp-content/uploads/2020/10/payment-strategy-classes.png" alt="" width="422" height="188" srcset="https://www.bdabek.pl/wp-content/uploads/2020/10/payment-strategy-classes.png 422w, https://www.bdabek.pl/wp-content/uploads/2020/10/payment-strategy-classes-300x134.png 300w" sizes="(max-width: 422px) 100vw, 422px" /></a></p>
<p>Może się zdarzyć tak, że miałeś złe przeczucie i kod, który ująłeś w strategię nie ma żadnych rozszerzeń. Skończyłeś z interfejsem i jego dwoma implementacjami które się nie zmieniają. Coś co mógłbyś ująć w jednej metodzie z dwoma if&#8217;ami i 15 liniami kodu jest hierarchią klas. Pytanie &#8211; <strong>czy to jest aż tak złe</strong>? W najgorszym przypadku masz 2 dodatkowe klasy, każda zawierająca po 5 linii logiki kodu. Nie jestem zwolennikiem takiego podejścia ale uważam, że będzie to lepsze niż metoda z zagnieżdżającymi się if&#8217;ami, które z czasem mogą dojść. Czy jest <strong>złoty środek</strong>? I tak i nie. Zależy z kim pracujesz. Ja osobiście jestem zdania, że <strong>powinniśmy zaczynać jak najprościej</strong> &#8211; w tym przypadku od metody. A kiedy widzisz, że to się rozrasta <strong>robisz refaktor</strong>. <strong>Nie akceptujesz wymówek typu: to ma być na już</strong>!</p>
<hr />
<h2>Podsumowanie</h2>
<p><a href="https://www.bdabek.pl/spring-boot-i-logi-ustawienia-logbacka/lightbulb/" rel="attachment wp-att-976" data-slb-active="1" data-slb-asset="1379905354" data-slb-internal="976"><img decoding="async" class="aligncenter wp-image-976 size-thumbnail lazyloaded" src="https://cdn.shortpixel.ai/client/to_webp,q_glossy,ret_img,w_150,h_150/https://www.bdabek.pl/wp-content/uploads/2020/05/Lightbulb-150x150.jpg" alt="" width="150" height="150" data-src="https://cdn.shortpixel.ai/client/to_webp,q_glossy,ret_img,w_150,h_150/https://www.bdabek.pl/wp-content/uploads/2020/05/Lightbulb-150x150.jpg" /></a></p>
<p>Mam nadzieję, że ten artykuł uświadomi nas trochę w działaniu. Nie piszmy kodu bez myślenia! Patrzmy, co może się zdarzyć dalej. Być może kod, który właśnie klepiesz za 3 miesiące będzie musiał być wyrzucony do kosza a zamiast niego <strong>o wiele szybciej</strong> powstanie nowa implementacja? Tylko pytanie &#8211; czy Twój kod jest gotowy na tak szybką wymianę? Czy kod, który wcześniej naklepałeś nie zawiera zawiłości i nieoczekiwanych wyników?</p>
<p>Oczywiste jest, że im dłużej jesteś na danym projekcie, tym większą wiedzę masz na temat tego co tworzysz. Może faktycznie będzie tak, że uznasz iż kod, który pisałeś 2 miesiące temu trzeba przepisać z nowo poznaną wiedzą. Jak duży będzie koszt przepisania? Czy będzie to tylko kwestia napisania nowej logiki i jej odpowiednie wstrzyknięcie? A może modyfikowanie 10 miejsc z dozą niepewności czy system będzie działać dalej tak samo? Sam odpowiedz na to pytanie i <strong>pamiętaj</strong>, że kod który dziś tworzysz jutro może być zarządzany przez kogoś innego.</p>
<p>Na koniec pozwolę sobie utworzyć własny cytat:</p>
<blockquote><p>Kod jest jak bumerang, kiedyś do Ciebie wróci.</p>
<p><cite>Bartosz Dąbek</cite></p></blockquote>
<p>&nbsp;</p>
<p>Źródła:</p>
<ul>
<li><strong><a href="https://refactoring.guru/design-patterns/strategy" target="_blank" rel="noopener noreferrer">Strategy</a></strong></li>
<li><strong><a href="https://youtu.be/v9ejT8FO-7I" target="_blank" rel="noopener noreferrer">Strategy Pattern – Design Patterns (ep 1)</a></strong></li>
</ul>
<hr />
<h3>Za tydzień</h3>
<p>Mamy pierwszy tydzień nowego miesiąca a to oznacza <strong>podsumowanie października oraz plany na listopad</strong>.</p>
<div id="wpd-post-rating" class="wpd-not-rated">
<div class="wpd-rating-wrap"></div>
</div>
<p>Artykuł <a href="https://www.bdabek.pl/wzorzec-strategii-%f0%9f%99%8f-jak-czytelnie-pisac-kod-%f0%9f%a4%94/">Wzorzec Strategii 🙏. Jak Czytelnie Pisać Kod? 🤔</a> pochodzi z serwisu <a href="https://www.bdabek.pl">bdabek.pl</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bdabek.pl/wzorzec-strategii-%f0%9f%99%8f-jak-czytelnie-pisac-kod-%f0%9f%a4%94/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
