fbpx
goodfirms LOGO Created with Sketch.









    Już nas opuszczasz?

    Napisz czego potrzebujesz, a nasi eksperci powiedzą Ci jak to zrobić, ile to kosztuje i na kiedy będzie gotowe.








      GraphQL z Flutter — jak używać, by zwiększyć optymalizację bazy danych?

      10
      luty
      2023
      5 minut czytania
      Udostępnij

      Na ekranie smartfona można wyświetlić w czytelny i przyjazny sposób znacznie mniej informacji niż w przypadku monitora komputerowego. Z tego też powodu, aby zoptymalizować płynność działania aplikacji mobilnych, należy się przede wszystkim upewnić czy wysyłane za pośrednictwem API zapytania pobierają tylko i wyłącznie niezbędne dane.

      Tworzone współcześnie wieloplatformowe aplikacje współdzielą ze sobą najczęściej bazę danych, ponieważ w ten właśnie sposób da się stosunkowo łatwo uniknąć wielu niepotrzebnych kosztów. Dzięki współdzielonej bazie danych można zabezpieczyć się przed scenariuszem, w którym każdy potencjalnie wykryty błąd trzeba naprawiać osobno dla każdej platformy. Pomimo że w teorii REST jest w stanie przynajmniej częściowo rozwiązać ten problem, to w praktyce nie zawsze tak jest. Na szczęście na skutek zmagań z analogicznymi trudnościami developerzy z Facebooka opracowali własne rozwiązanie o nazwie GraphQL, które następnie rozpowszechniło się dzięki fundacji Linuxa.

      Czym dokładnie jest GraphQL i dlaczego tak wiele osób nazywa go następcą RESTa? Jakie koncepcje leżą u podstaw GraphQL? W jaki sposób GraphQL pomaga w optymalizacji wieloplatformowych aplikacji? Na wszystkie te pytania postaramy się odpowiedzieć w poniższym poradniku.

      Co to jest GraphQL i czym odróżnia się od REST?

      Opublikowany w 2015 roku przez developerów z Facebooka (obecnie Meta) GraphQL to jeden z najpopularniejszych otwartych języków zapytań (ang. Query Language). Warto podkreślić tu jednak, iż od 2018 roku odpowiedzialność za dalszy rozwój GraphQL przejęła sławetna organizacja non-profit Linux Foundation. W odpowiedzi na przesyłane za pośrednictwem API i GraphQL zapytania najczęściej zwracane są dane w formie dokumentu w formacie JSON. Jedną z największych zalet GraphQL jest to, iż w porównaniu do REST zapewnia on znacznie większą elastyczność i precyzję. Ponadto w przeciwieństwie do REST GraphQL do obsługi wymiany danych wykorzystuje tylko i wyłącznie jeden endpoint.

      Dlaczego GraphQL określany jest mianem następcy RESTa?

      Nieustannie rozwijany w charakterze projektu typu open-source GraphQL najbardziej przydaje się w przypadku wieloplatformowych aplikacji, ponieważ w tym właśnie scenariuszu niemalże zawsze zaczynają się pierwsze problemy z RESTem. Jeśli aplikacja mobilna wyświetla mniej danych niż desktopowa, to nie powinno się niepotrzebnie pobierać w wersji mobilnej nadmiaru informacji, gdyż spowolni to jej działanie. Pobieranie danych za pośrednictwem API i GraphQL jest dużo łatwiejsze od REST API ze względu na to, iż nie trzeba tworzyć dodatkowych zapytań ani endpointów. Mając na uwadze, iż twórcy GraphQL od początku starają się rozwiązać problemy znane każdemu, kto próbował rozwijać wieloplatformową aplikacje w standardzie REST API, łatwo zrozumieć można, dlaczego język ten w pełni zasłużył na miano następcy RESTa.

      Podstawy GraphQL – najważniejsze koncepcje i pojęcia

      Zanim na podstawie przykładowych zapytań zobrazujemy przewagę, jaką GraphQL zapewnia nad RESTem, musimy wpierw, chociaż częściowo wyjaśnić podstawy GraphQL. Warto wspomnieć tu również, iż szczegółowa specyfikacja i dokumentacja GraphQL jest w pełni dostępna w języku angielskim na stronie fundacji GraphQL. Do najważniejszych koncepcji w GraphQL zaliczyć trzeba następujące 3 terminy:

      1. Typ Query

      Komunikacja danych w GraphQL bazuje na zapytaniach (ang. Queries), które to definiowane są właśnie przy pomocy słowa kluczowego query oraz dodatkowych parametrów (np. nazw poszczególnych właściwości zasobów). Należy podkreślić tu również, iż każde zapytanie w GraphQL przechodzi przez 3 fazy (parsowania, walidacji i wykonania). Finalnie, obiekt JSON, który otrzymujemy w odpowiedzi na prawidłowe zapytanie, będzie wypełniony danymi w dokładnie takiej samej strukturze jak w zapytaniu.

      2. Resolver

      Jako że GraphQL nie potrafi sam określić, gdzie dokładnie znajdują się dane, o które pytamy, to trzeba mu to wyjaśnić przy pomocy tzw. resolverów. Innymi słowy, jest to zbiór funkcji odpowiedzialnych za generowanie odpowiedzi na przesyłane za pośrednictwem API zapytania. Resolver może zwracać zarówno obiekty, obietnice, jak i też wartości skalarne (np. Int, Float, String, Boolean, ID itp.).

      3. Schema

      W GraphQL zawsze trzeba zaprojektować schemat (ang. Schema), który będzie definiował, w jaki sposób przebiega komunikacja z serwerem API. Definicje te określa się zazwyczaj przy pomocy języka SDL (ang. Schema Definition Language) lub IDL (Interface Definition Language). GraphQL można połączyć z dowolnym językiem programowania (np. Dart, JavaScript, Java, Ruby, Scala itd.), ale trzeba pamiętać tu, iż jest on klasyfikowany jako język silnie typowany. Innymi słowy, każda definicja musi mieć dokładnie określony typ. Podstawowym komponentem schematu, który reprezentuje obiekt wraz z jego właściwościami, są typy obiektowe (ang. Object Types). W GraphQL wyróżnić można także typy skalarne oraz typy wyższego rzędu (ang. Root Types), takie jak np. typ Query, Mutation albo Subscription. Ostatnie trzy wspomniane typy odpowiadają kolejno za akcje takie jak pobieranie, modyfikowanie czy obserwowanie.

      Jak wygodnie budować zapytania API w GraphQL? 

      Jedną z wielu zalet GraphQL jest to, iż zarówno z poziomu przeglądarki internetowej, jak i dedykowanego IDE (np. GraphQL Playground albo GraphiQL) można korzystać z niezwykle praktycznych podpowiedzi. Jeżeli w trakcie tworzenia zapytania API wciśniemy jednocześnie klawisz control i spację, GraphQL wygeneruje nam automatycznie listę dostępnych funkcji oraz obiektów. Dzięki tej niezmiernie wygodnej funkcjonalności tworzenie precyzyjnych zapytań staje się dużo łatwiejsze i szybsze. Warto wspomnieć tu także, iż GraphQL pozwala na to, by w jednym zapytaniu pobierać różne rodzaje danych, a jeśli nie znamy parametrów poszczególnych obiektów, to dzięki wspomnianemu wyżej skrótowi automatycznie wygeneruje się lista dostępnych właściwości. Bardziej wymagających użytkowników ucieszy zaś z pewnością to, iż w zapytaniach typu Query można dowolnie zagnieżdżać informacje, jeśli tylko pozwala na to struktura danych.

      Podsumowanie – w jaki sposób GraphQL pomaga w zwiększeniu optymalizacji aplikacji opracowanych we Flutter?

      W przypadku wieloplatformowych aplikacji, które powstają na bazie Fluttera, zamiast tracić czas na tworzenie większej liczby endpointów w standardzie REST, zdecydowanie bardziej opłaca się postawić na GraphQL, gdyż w każdym zapytaniu wykorzystuje on w trakcie komunikacji tylko jeden endpoint. Zarówno w przypadku mobilnych, jak i też desktopowych wersji aplikacji nie powinno się za pośrednictwem API pobierać zbędnych danych, ponieważ może to odczuwalnie pogorszyć wydajność po stronie klienta. Problem z długim czasem wczytywania danych w odpowiedzi na wygenerowane przez użytkownika zapytania jest dużo bardziej dotkliwy na urządzeniach mobilnych (np. smartfonach, laptopach oraz tabletach). Niezoptymalizowane zapytania API (np. pobieranie 1000 rekordów, aby wyświetlić 1) pochłaniają niepotrzebnie więcej transferu, pamięci i mocy obliczeniowej, a to zużywa dodatkowo więcej energii. Z tych też powodów, aby zoptymalizować płynność komunikacji dla aplikacji wieloplatformowych we Fluttter, zamiast REST znacznie rozsądniej jest wykorzystać GraphQL.

      Wiktor Sobczyk

      Bezpłatna konsultacja

      Powiedz nam czego potrzebujesz, a nasi eksperci Powiedzą Ci jak to zrobić, ile to kosztuje i na kiedy będzie gotowe.

      Inne wpisy na blogu

      19
      styczeń
      2023
      Dzięki wsparciu Google i coraz liczniejszego środowiska developerów Flutter wciąż utrzymuje się w ścisłej czołówce najpopularniejszych frameworków do tworzenia wieloplatformowych aplikacji mobilnych oraz webowych. Jako, że wszystkie zaprojektowane we Flutterze aplikacje bazują na Dart, w przygotowanym poniżej poradniku będziemy wielokrotnie posiłkować się fragmentami kodu w tym właśnie języku. Jak poprawić wygląd i intuicyjność aplikacji we…
      tagi: #Technologia
      czytaj artykuł
      Cykl życia defektów we Flutterze
      Karol
      6 minut czytania
      18
      listopad
      2022
      Testowaniem opracowywanych, utrzymywanych i rozwijanych aplikacji webowych zajmują się nie tylko programiści, którzy odpowiedzialni są za kod źródłowy, ale także testerzy. Przy pomocy zautomatyzowanych i manualnych testów da się zweryfikować pod kątem obecności błędów każdy rodzaj oprogramowania. Dzięki wsparciu profesjonalistów można uniknąć nieprzyjemnej sytuacji, w której rozeźleni użytkownicy sami zgłaszają wykryte wady i defekty. Aby…
      tagi: #Bezpieczeństwo
      czytaj artykuł
      <div id="panel-861-0-0-1" class="widget widget-features2 so-wrapper so-panel" data-animationcss="scrolled" data-index="1" data-style="{"fullhd":"margin:","pc":"margin:","tablet":"margin:","phone":"margin:"}" style=""><div class="container"><div class="row justify-content-center"><div class="col col-12"><h6 class="header text--48"> Nasze usługi <svg x="0px" y="0px" viewBox="0 0 394.7 22.1" style="enable-background:new 0 0 394.7 22.1;" xml:space="preserve"> <path class="path1 path-draw draw" fill="none" d="M0.1,21.1C170.6,1,266.6-1.9,394.6,3.1"></path> </svg></h6></div><div class="col col-12 col-md-6 col-lg-4"><div class="feature feature-multi-link"><div class="border_part1"></div><div class="border_part2"></div> <a class="title-container is_icon" href="https://it-solve.pl/uslugi-programistyczne/tworzenie-aplikacji-mobilnych/"><div class="icon"><span class=""><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 61.7 65.54"><defs></defs><title>home-ico3</title><g id="Warstwa_2" data-name="Warstwa 2"><g id="Calque_2" data-name="Calque 2"><path class="cls-1" d="M61.59,53.61,55,40.69c-2.46-4-6.07-4-7.66-3.4L36.87,41.56l-5.71-9.31A4.25,4.25,0,0,0,25.37,31a4.34,4.34,0,0,0-1.91,2.56,4,4,0,0,0,.43,3.19L34.58,54.15l-5.51-1.32a4.14,4.14,0,0,0-5,3l-.11.47a4.14,4.14,0,0,0,.48,3.13A4.1,4.1,0,0,0,27,61.33l17.34,4.18a1,1,0,0,0,.24,0,1,1,0,0,0,.23-2L27.46,59.38a2.13,2.13,0,0,1-1.56-2.57l.11-.47a2.13,2.13,0,0,1,2.59-1.56l7.87,1.88a1,1,0,0,0,1.08-1.5L25.6,35.67A2.08,2.08,0,0,1,25.39,34a2.38,2.38,0,0,1,1-1.38,2.27,2.27,0,0,1,3.05.64l6.15,10a1,1,0,0,0,1.22.4l11.24-4.57c.12,0,3-1,5.21,2.51l6.53,12.84a1,1,0,1,0,1.78-.9Z"></path><path class="cls-1" d="M26.6,16.16a1,1,0,0,0-.84-.68l-6.13-.65L17.12,9.2a1,1,0,0,0-1.83,0l-2.51,5.63-6.13.65a1,1,0,0,0-.85.68,1,1,0,0,0,.29,1.06l4.57,4.12-1.27,6a1,1,0,0,0,.39,1,1,1,0,0,0,1.08.06l5.35-3.08,5.34,3.08a1.05,1.05,0,0,0,.49.13,1,1,0,0,0,.59-.19,1,1,0,0,0,.39-1l-1.28-6,4.58-4.12A1,1,0,0,0,26.6,16.16ZM20,20.24a1,1,0,0,0-.31,1l.93,4.4-3.9-2.24a1,1,0,0,0-1,0l-3.9,2.24.93-4.4a1,1,0,0,0-.31-1l-3.34-3,4.48-.47a1,1,0,0,0,.8-.59l1.84-4.11L18,16.17a1,1,0,0,0,.8.59l4.48.47Z"></path><path class="cls-1" d="M2,53.44V46.15H24.79v-2H2V3.49A1.49,1.49,0,0,1,3.49,2H28.93a1.49,1.49,0,0,1,1.48,1.49V27.31h2V3.49A3.48,3.48,0,0,0,28.93,0H3.49A3.49,3.49,0,0,0,0,3.49V53.44a3.49,3.49,0,0,0,3.49,3.49H20.43v-2H3.49A1.49,1.49,0,0,1,2,53.44Z"></path><path class="cls-1" d="M14.14,49.42a1,1,0,0,0,0,2h4.14a1,1,0,0,0,0-2Z"></path></g></g></svg></span></div><div class="title text--24">Aplikacje mobilne</div> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a><div class="description text--16"><a class="btn btn-rainbow btn-main" style="margin: 35px 0;" href="https://it-solve.pl/uslugi-programistyczne/tworzenie-aplikacji-mobilnych/"> <span class="text--16">zobacz więcej</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a></div></div></div><div class="col col-12 col-md-6 col-lg-4"><div class="feature feature-multi-link"><div class="border_part1"></div><div class="border_part2"></div> <a class="title-container is_icon" href="https://it-solve.pl/uslugi-programistyczne/tworzenie-aplikacji-internetowych/"><div class="icon"><span class=""><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 66.42 49.31"><defs></defs><title>home-ico2</title><g id="Warstwa_2" data-name="Warstwa 2"><g id="Calque_2" data-name="Calque 2"><path class="cls-1" d="M11.18,39.82h17.9V21.26H11.18Zm2-16.56h13.9V37.82H13.18Z"></path><path class="cls-1" d="M54.24,21.61H37.15a1,1,0,0,0,0,2H54.24a1,1,0,0,0,0-2Z"></path><path class="cls-1" d="M54.24,29.54H37.15a1,1,0,0,0,0,2H54.24a1,1,0,0,0,0-2Z"></path><path class="cls-1" d="M54.24,37.47H37.15a1,1,0,0,0,0,2H54.24a1,1,0,1,0,0-2Z"></path><rect class="cls-1" x="5.51" y="11.86" width="55.39" height="2"></rect><path class="cls-1" d="M9.32,8.8A1.78,1.78,0,1,0,7.54,7,1.78,1.78,0,0,0,9.32,8.8Z"></path><circle class="cls-1" cx="16.77" cy="7.02" r="1.78"></circle><circle class="cls-1" cx="24.22" cy="7.02" r="1.78"></circle><path class="cls-1" d="M61.84,0H4.57A4.58,4.58,0,0,0,0,4.57V44.74a4.58,4.58,0,0,0,4.57,4.57H61.84a4.58,4.58,0,0,0,4.58-4.57V4.57A4.58,4.58,0,0,0,61.84,0Zm2.58,44.74a2.58,2.58,0,0,1-2.58,2.57H4.57A2.57,2.57,0,0,1,2,44.74V4.57A2.57,2.57,0,0,1,4.57,2H61.84a2.58,2.58,0,0,1,2.58,2.57Z"></path></g></g></svg></span></div><div class="title text--24">Aplikacje webowe</div> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a><div class="description text--16"><a class="btn btn-rainbow btn-main" style="margin: 35px 0;" href="https://it-solve.pl/uslugi-programistyczne/tworzenie-aplikacji-internetowych/"> <span class="text--16">zobacz więcej</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a></div></div></div><div class="col col-12 col-md-6 col-lg-4"><div class="feature feature-multi-link"><div class="border_part1"></div><div class="border_part2"></div> <a class="title-container is_icon" href="https://it-solve.pl/uslugi-programistyczne/outsourcing-programistow/"><div class="icon"><span class=""><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56.17 59.33"><defs></defs><title>1</title><g id="Warstwa_2" data-name="Warstwa 2"><g id="Calque_3" data-name="Calque 3"><path class="cls-1" d="M28.08,33.63c6,0,11.77-7.65,12.64-16.72.48-5.08.52-10.24-2.43-13.48C36.19,1.12,32.85,0,28.08,0S20,1.12,17.88,3.43c-2.95,3.25-2.91,8.4-2.43,13.48C16.31,26,22.1,33.63,28.08,33.63ZM19.36,4.77C21.06,2.91,23.91,2,28.08,2s7,.91,8.73,2.77c1.82,2,2.23,5.12,2.14,8.51A33,33,0,0,1,31.8,10a7,7,0,0,0,.76-1.81l-2-.42S29.42,13,21.29,13v2c4.92,0,7.72-1.65,9.3-3.31a34.21,34.21,0,0,0,8.25,3.68c0,.47-.07.94-.12,1.4C38,24.67,33,31.63,28.08,31.63s-9.88-7-10.64-14.91C17,12.1,16.93,7.45,19.36,4.77Z"></path><path class="cls-1" d="M55.15,45.65c-1.08-8-6-9-6.17-9.07s-5-1.4-10.11-2.26l-.73-.12L34,42.56l-5.15-5.85-.33-.34h-.9l-5.46,6.19L18,34.2l-.73.12c-5.14.86-10,2.24-10,2.24h0c-.21,0-5.18,1-6.26,9.15L0,59.13l2,.15L3,45.91c.87-6.52,4.5-7.36,4.73-7.41,0,0,4.41-1.24,9.17-2.08l4.18,8.46L22.87,44l-.4-.81,2.74,3.09L23.59,59.08l2,.25L27,48.26l1.13,1.28,1.1-1.25,1.39,11,2-.25L31,46.29l2.74-3.11-.4.81,1.79.89,4.18-8.46c4.76.84,9.13,2.07,9.25,2.1s3.77.87,4.64,7.34l1,13.42,2-.15Zm-27,.87L24.71,42.7l3.37-3.83,3.38,3.83Z"></path></g></g></svg></span></div><div class="title text--24">Outsourcing pracowników IT</div> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a><div class="description text--16"><a class="btn btn-rainbow btn-main" style="margin: 35px 0;" href="https://it-solve.pl/uslugi-programistyczne/outsourcing-programistow/"> <span class="text--16">zobacz więcej</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a></div></div></div><div class="col col-12 col-md-6 col-lg-4"><div class="feature feature-multi-link"><div class="border_part1"></div><div class="border_part2"></div> <a class="title-container is_icon" href="https://it-solve.pl/uslugi-programistyczne/qa-testowanie/"><div class="icon"><span class=""><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62.95 57.88"><defs></defs><title>home-ico4</title><g id="Warstwa_2" data-name="Warstwa 2"><g id="Calque_3" data-name="Calque 3"><path class="cls-1" d="M63,33.77V24.1l-7.68-1.26a22.1,22.1,0,0,0-1.89-4.58l4.52-6.37L51.06,5.06,44.69,9.58a21.87,21.87,0,0,0-4.58-1.89L38.85,0h-5V2h3.27l1.2,7.3.64.16a19.8,19.8,0,0,1,5.25,2.17l.56.33,6-4.29,4.45,4.44L51,18.16l.33.55A20,20,0,0,1,53.5,24l.16.63L61,25.8v6.27l-7.29,1.2-.16.64a20.25,20.25,0,0,1-2.19,5.29l-.34.56,4.31,6L50.85,50.2l-6-4.31-.56.34A20.16,20.16,0,0,1,39,48.41l-.63.16-1.24,7.31H33.88v2h5l1.31-7.71a22.24,22.24,0,0,0,4.57-1.89l6.33,4.54L57.9,46l-4.55-6.33A22.44,22.44,0,0,0,55.27,35Z"></path><path class="cls-1" d="M44.42,28.94A10.49,10.49,0,0,0,33.88,18.53v2a8.41,8.41,0,1,1,0,16.81v2A10.48,10.48,0,0,0,44.42,28.94Z"></path><path class="cls-1" d="M0,28.94A29,29,0,0,0,28.92,57.85h1V0h-1A29,29,0,0,0,0,28.94ZM27.92,39.61a39.53,39.53,0,0,0-11,1.82,30.65,30.65,0,0,1-2.4-10.22c0-.43,0-.86,0-1.29H27.92ZM2,27.92a26.69,26.69,0,0,1,5.74-15.6,43.49,43.49,0,0,0,7.69,3.59,34.18,34.18,0,0,0-3,12Zm10.41,2c0,.47,0,.93,0,1.4A32.78,32.78,0,0,0,15,42.08a44.49,44.49,0,0,0-7.22,3.43A26.79,26.79,0,0,1,2,29.92Zm2.05-2a32.48,32.48,0,0,1,2.88-11.39A39.58,39.58,0,0,0,27.92,18.2v9.72ZM27.92,16.2a37.69,37.69,0,0,1-9.67-1.5A54.27,54.27,0,0,1,27.5,2.07l.42,0ZM24.46,2.4a54.06,54.06,0,0,0-8.14,11.69,42.27,42.27,0,0,1-7.24-3.32A26.93,26.93,0,0,1,24.46,2.4ZM9,47.06a41.61,41.61,0,0,1,6.72-3.15,42.19,42.19,0,0,0,8.16,11.48A26.9,26.9,0,0,1,9,47.06ZM27.29,55.8A41.38,41.38,0,0,1,17.7,43.27a37.56,37.56,0,0,1,10.22-1.66V55.84Z"></path></g></g></svg></span></div><div class="title text--24">QA i testowanie</div> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a><div class="description text--16"><a class="btn btn-rainbow btn-main" style="margin: 35px 0;" href="https://it-solve.pl/uslugi-programistyczne/qa-testowanie/"> <span class="text--16">zobacz więcej</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a></div></div></div><div class="col col-12 col-md-6 col-lg-4"><div class="feature feature-multi-link"><div class="border_part1"></div><div class="border_part2"></div> <a class="title-container is_icon" href="https://it-solve.pl/uslugi-programistyczne/product-design/"><div class="icon"><span class=""><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54.76 54.7"><defs></defs><title>home-ico5</title><g id="Warstwa_2" data-name="Warstwa 2"><g id="Calque_2" data-name="Calque 2"><path class="cls-1" d="M53.3,8,46.8,1.46a5,5,0,0,0-7.08,0l-4,4L49.33,19l4-4A5,5,0,0,0,53.3,8Zm-1.42,5.65-2.55,2.56L38.58,5.43l2.56-2.55a3,3,0,0,1,4.24,0l6.5,6.5a3,3,0,0,1,0,4.24Z"></path><path class="cls-1" d="M20.78,44.67,16.14,40,40.38,15.8,39,14.39,14.73,38.62,10.09,34,34.33,9.75,32.91,8.34,7.21,34a1,1,0,0,0-.23.37l-6.92,19a1,1,0,0,0,.23,1,1,1,0,0,0,1.05.23l19-6.86a1,1,0,0,0,.37-.24L46.26,22,44.84,20.6Zm-12-9.23L19.31,46l-8.77,3.16-5-5ZM4.78,46.26l3.69,3.68L2.67,52Z"></path></g></g></svg></span></div><div class="title text--24">Product Design</div> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a><div class="description text--16"><a class="btn btn-rainbow btn-main" style="margin: 35px 0;" href="https://it-solve.pl/uslugi-programistyczne/product-design/"> <span class="text--16">zobacz więcej</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg></a></div></div></div><div class="col col-12 col-md-6 col-lg-4"><div class="feature feature-multi-link"><div class="border_part1"></div><div class="border_part2"></div> <a class="title-container is_icon" href="https://it-solve.pl/uslugi-programistyczne/warsztaty-discovery/"><div class="icon"><span class=""><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 55.79 57.19"><defs></defs><title>benefit-6</title><g id="Warstwa_2" data-name="Warstwa 2"><g id="Calque_2" data-name="Calque 2"><path class="cls-1" d="M13.33,33.86a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41L8.93,26.64l5.81-5.81a1,1,0,0,0,0-1.42,1,1,0,0,0-1.41,0L7.52,25.22,1.71,19.41A1,1,0,1,0,.29,20.83L6.1,26.64.29,32.45a1,1,0,0,0,0,1.41,1,1,0,0,0,1.42,0l5.81-5.81Z"></path><path class="cls-1" d="M45.35,42.45a1,1,0,0,0-1.42,0l-5.81,5.81-5.81-5.81a1,1,0,0,0-1.41,1.41l5.81,5.81L30.9,55.48a1,1,0,0,0,1.41,1.42l5.81-5.81,5.81,5.81a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-5.81-5.81,5.81-5.81A1,1,0,0,0,45.35,42.45Z"></path><path class="cls-1" d="M46.34,13.43a9.45,9.45,0,1,0,9.45,9.44A9.44,9.44,0,0,0,46.34,13.43Zm0,16.89a7.45,7.45,0,1,1,7.45-7.45A7.45,7.45,0,0,1,46.34,30.32Z"></path><path class="cls-1" d="M32.83,7.12a.94.94,0,0,0,.51.14,1,1,0,0,0,.51-1.86L25,.13A1,1,0,0,0,24.52,0h0a1.27,1.27,0,0,0-.34,0,.69.69,0,0,0-.19.1.39.39,0,0,0-.11.06,1,1,0,0,0-.32.35L19,9.77a1,1,0,0,0,.44,1.34,1,1,0,0,0,.45.1,1,1,0,0,0,.89-.55l3.57-7.14c2.38,7.21,8.76,33.4-17,49.92a1,1,0,0,0,.54,1.84,1,1,0,0,0,.54-.16c26.2-16.8,20.34-43.88,17.88-51.9Z"></path></g></g></svg></span></div><div class="title text--24">Warsztaty Discovery</div> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a><div class="description text--16"><a class="btn btn-rainbow btn-main" style="margin: 35px 0;" href="https://it-solve.pl/uslugi-programistyczne/warsztaty-discovery/"> <span class="text--16">zobacz więcej</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a></div></div></div><div class="col col-12"> <a class="btn btn-rainbow btn-main" href="https://it-solve.pl/uslugi-programistyczne/"> <span class="text--16">więcej na temat naszych usług</span> <svg class="arrow" x="0px" y="0px" width="35.2px" height="25.7px" viewBox="0 0 35.2 25.7" style="enable-background:new 0 0 35.2 25.7;" xml:space="preserve"> <polyline fill="none" points="22.2,0.4 34.5,12.9 22.2,25.4 "></polyline> <line fill="none" x1="34.5" y1="12.9" x2="0" y2="12.9"></line> </svg> </a></div></div></div></div>
      <div class="text--16" style="text-align: center;"> <div class="text--16" style="text-align: center;">Jak możemy Ci pomóc?</div> <div class="text--48" style="text-align: center;">Porozmawiaj z nami!</div> </div>

      Błąd: Brak formularza kontaktowego.

      Kamil
      Head of Business Development
      Kliknij, aby podejrzeć