<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Petro Momot</title>
    <description>The latest articles on DEV Community by Petro Momot (@pmomot).</description>
    <link>https://dev.to/pmomot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F651026%2F2cd32ddb-f7b7-4604-88d4-e770816f47af.jpeg</url>
      <title>DEV Community: Petro Momot</title>
      <link>https://dev.to/pmomot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pmomot"/>
    <language>en</language>
    <item>
      <title>How we're discovering Secfi's engineering culture</title>
      <dc:creator>Petro Momot</dc:creator>
      <pubDate>Wed, 30 Mar 2022 11:53:44 +0000</pubDate>
      <link>https://dev.to/secfi/how-were-discovering-secfis-engineering-culture-1f61</link>
      <guid>https://dev.to/secfi/how-were-discovering-secfis-engineering-culture-1f61</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fmAFWQoH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbcrpg3irlwm5hyht14k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fmAFWQoH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbcrpg3irlwm5hyht14k.jpg" alt="Secfi engineering workshop begins" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every company and every team has a distinct mission and a culture. It doesn’t matter if it’s defined and articulated in words that each team member can recite or if it lives in the subconscious of a team. You can feel it when you enter the office or join a call, you can get a grasp of it during the interview process. Whenever I have an interview as a candidate, I enjoy asking the question about the company mission and its values. In most cases, the answers are vague and people say something like: “Yeah, we actually had a session when we defined something along these lines, but it was some time ago” and then start looking through the internal documentation or their own public website to find those.&lt;/p&gt;

&lt;p&gt;At Secfi we have defined a list of values that we come back to quite often – each of us is encouraged to give feedback/praise to a colleague at any moment and while doing it one has to select one of the values that the feedback is falling into. Also, during the mid-year and end-of-year reviews we score each other using the same list of values. All of this works well for the whole company, because each team or department in a company has its own unique vibe and set of HOW’s or culture differentiators. They correlate with the company-wide ones, but are still unique and special to the function and people on that team.&lt;/p&gt;

&lt;p&gt;The engineering department at Secfi is actively growing and, at the moment of writing, we have 21 colleagues. We decided that this is a great moment to discover our WHY and HOWs as a department. The reason why I’m saying “discover” and not “define” is that the culture and mission is something that’s already alive and in motion – we just need to discover it, to do a specific exercise that helps to uncover something that all of us already feel and live by.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we wanted to achieve
&lt;/h2&gt;

&lt;p&gt;The main goal was to discover our WHY and HOWs. But why?&lt;/p&gt;

&lt;p&gt;It’s more or less easy to keep the unspoken culture alive and strong when you don’t have new people joining – everyone knows everyone, processes are well defined and followed. Things change when the team is actively growing. Since the beginning of the year we have new people joining every couple weeks. Now it’s clear that we need to have these things well defined. To go further, we need to reinforce them by some daily/weekly/monthly/quarterly activities that somebody has to think about, prepare and execute. Another important point is when you have your WHY and HOWs defined it’s much easier to interview and assess people on a cultural fit. This goes both ways – it’s easier for us as a company to assess a candidate while the candidate themselves will be able to easily find these materials on our public website. To achieve these goals we decided to organize an (almost) full day workshop for the whole team.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened in the workshop
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/kbhrb3Fkw17q0jMxEW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/kbhrb3Fkw17q0jMxEW/giphy.gif" alt="workshop gif" width="500" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal of the workshop session was to find out how the engineering department contributes to and what the effect is on the company and the world. In the session we reflected on successes and special moments when the team was at its best. Situations when we felt proud to be part of this team. Events that have shaped it as we are today. &lt;/p&gt;

&lt;p&gt;A small but very important side note here: while I suggested the idea to do this workshop the following way, it would not be possible to actually do it without the relentless efforts of &lt;a href="https://www.linkedin.com/in/sarahvanderlaan/"&gt;Sarah van der Laan&lt;/a&gt;. She organized the room, equipment, lunch and arranged everything with all possible stakeholders 🚀&lt;/p&gt;

&lt;p&gt;The whole workshop consisted of several blocks of activities which we took from the &lt;a href="https://simonsinek.com/tribe-why-discovery-schematic/"&gt;Find Your Why&lt;/a&gt; book written by Simon Sinek, which is a great resource along with his other book “Start With Why”. Both books bring understanding to why it is important to start with why in every situation – at your work or at home, or somewhere else. The “Find Your Why” gives step by step instructions on how to do it on a personal level and on a group or tribe level.&lt;/p&gt;

&lt;p&gt;The workshop opened with an introduction of the methodology and background followed by an icebreaker. For the icebreaker we divided all participants into groups of two and asked each colleague to share something that inspired them to join the company. This activity took just 5 minutes but set a great foundation for the further discussions and interactions.&lt;/p&gt;

&lt;p&gt;I will not list here all the details of the workshop – I encourage you to read the book and organize one in your company or team. What I will share is that after roughly 5 hours (including breaks) we had plenty of material to define our HOWs, our culture and a solid draft of our WHY statement as a department.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;On top of having a draft for the mission of an engineering at Secfi we have achieved multiple goals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Everyone felt like an active part of the tribe.
&lt;/h4&gt;

&lt;p&gt;People shared stories that made them feel proud to work here. We received great positive feedback on the spot and during the week following the workshop.&lt;/p&gt;

&lt;p&gt;Some of the testimonials:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The workshop itself was our best to date, I don't know what I'd change"&lt;/p&gt;

&lt;p&gt;"We need more events like this!"&lt;/p&gt;

&lt;p&gt;"Can you share a guide or just your experience organizing it? It would be nice to have more workshops and sharing your experience might give ideas/inspiration to people"&lt;/p&gt;

&lt;p&gt;"Everything was perfect! Thank you!"&lt;/p&gt;

&lt;p&gt;"[I enjoyed] the collaboration, everyone was involved in the process."&lt;/p&gt;

&lt;p&gt;"The exercise, the vibes, the fun"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Actionable next steps brainstorm
&lt;/h4&gt;

&lt;p&gt;We brainstormed actionable next steps for our department and decided to pick several of them as soon as possible. There were quite a few great action points that came from the brainstorming. I would split all the ideas into three groups – 1) one-time actions that are quick to implement; 2) bigger mid-term projects that need a bit more brainstorming and ownership; 3) broader ideas that need some thorough review and thinking. Overall the list looks very exciting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xTiN0CNHgoRf1Ha7CM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xTiN0CNHgoRf1Ha7CM/giphy.gif" alt="excited kid gif" width="345" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;You may have noticed that I have not shown any of our WHY or HOW statements in this article. The reason for this is that at this moment we’re working on finalizing the WHY and refining our HOWs. For this we asked several volunteers from the team to join and now the five of us are preparing this and the next steps that we’ll describe in more detail in the following article. Thank you for reading and I hope that our experience will inspire you to do the same activity in your team and or company.&lt;/p&gt;

</description>
      <category>culture</category>
      <category>workshop</category>
      <category>why</category>
    </item>
    <item>
      <title>Mobx -&gt; Apollo client journey</title>
      <dc:creator>Petro Momot</dc:creator>
      <pubDate>Thu, 10 Feb 2022 12:50:55 +0000</pubDate>
      <link>https://dev.to/secfi/mobx-apollo-client-journey-3aam</link>
      <guid>https://dev.to/secfi/mobx-apollo-client-journey-3aam</guid>
      <description>&lt;p&gt;Hi, my name is Petro and I’m a senior frontend engineer at Secfi. We are helping startup employees understand their equity and assisting some of them to avoid losing their deserved reward.&lt;/p&gt;

&lt;p&gt;Secfi is actively growing — client applications are getting bigger and maintaining one global state by hand becomes a difficult task. This article will explore our approach in resolving this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: What did the migration from MobX to Apollo client give us?
&lt;/h2&gt;

&lt;p&gt;Simplifying our data layer with GQL/Apollo allowed us to reduce a lot of the state management needs and boilerplate — to the point of removing Mobx altogether. &lt;/p&gt;

&lt;p&gt;In the end we got:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smaller amount of &lt;a href="https://en.wikipedia.org/wiki/Abstraction_(computer_science)" rel="noopener noreferrer"&gt;abstractions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;most of caching is handled automatically&lt;/li&gt;
&lt;li&gt;code generation (&lt;strong&gt;25k-30k&lt;/strong&gt; lines code removed + backend and frontend always in sync)&lt;/li&gt;
&lt;li&gt;faster loading time due to smaller amount of calls and reduced amount of data transferred&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This migration was not done in isolation. There were a lot of data model, tooling and even organizational changes that also occurred in parallel. These all interconnect, work together and influence one another.&lt;/p&gt;




&lt;h2&gt;
  
  
  How we grew to a point that a refactor was needed
&lt;/h2&gt;

&lt;p&gt;At Secfi we utilize React as the main library for our FE stack so all our other technology choices are based on React and its ecosystem. Before diving into the MobX migration it's important to explore why and how we used MobX in the first place — to provide some much needed context and history behind our decision making process.&lt;/p&gt;

&lt;p&gt;When our app grew to the state of needing the state management library (pun intended) we explored the two most common options in the React ecosystem — Redux or MobX. We didn’t like the amount of boilerplate code that we had to write if we went the Redux path and at the same time the MobX community had come up with the &lt;a href="https://mobx-state-tree.js.org/intro/welcome" rel="noopener noreferrer"&gt;MobX-State-Tree&lt;/a&gt; library which offered cool benefits, such as runtime type checking, data normalization and clear structure. On top of that we could (and did) set it up in a way that mimicked our backend data model and the microservices structure using the MobX-State-Tree models and actions. The benefit of this was obvious — frontend state structure was in sync with the backend — what can be better? The drawback though was in the actual details behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems that started to arise with time
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Models interdependency&lt;/li&gt;
&lt;li&gt;Increasing complexity, plus amount of calls&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To understand how these issues rose from our set-up back then it’s important to show a part of our business data model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7mjd5cofskavizx35ln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7mjd5cofskavizx35ln.png" alt="Models tree diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MobX-State-Tree has a great mechanism called actions in their models. These actions allow subscriptions to events on the model and facilitate performing side effects. We used it on all our models to fetch all related models in the tree. When the customer loaded the home page we needed to get all Affiliations for them,  resulting in each MobX-State-Tree model of the Affiliation making calls to resolve Company, Company Assessment, Tax Info and arrays of Option Grants and Share Grants. Each of these entities had their own initializing logic to fetch all other entities that they had references to.&lt;/p&gt;

&lt;p&gt;Of course there were checks in place to not fetch the same entity (checked by uuid) twice, but this improvement paled in comparison with the amount of REST API calls that were initiated on the page load. For reference — if the customer had indicated that they worked in 5 companies there could be 100 rest api calls initiated on the application load to populate the state with all necessary information. And while we could optimize specifically for the home page by joining all the calls into a new backend endpoint, the overfetching issue would remain on a platform level. &lt;/p&gt;

&lt;p&gt;As you might have guessed, this was also not fun to maintain. Models were naturally utilized as a source of parts of the business logic, since they were foundational to the application. Soon enough some of our UI pieces started to be affected as well: we created a separate store for theming configuration; all models grew to have computed properties that were meant for pure UI representation. At some point we realized that the state grew into one very big and hard to maintain creature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo98fphh495u8ehdul3tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo98fphh495u8ehdul3tr.png" alt="Models tree backend setup"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Apollo client to the rescue!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzczv7kq0zthqek3ktlnq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzczv7kq0zthqek3ktlnq.gif" alt="Apollo client to the rescue!"&gt;&lt;/a&gt;&lt;br&gt;
It was clear that the situation had to be improved but where to start? There were different solutions we could leverage to solve this problem, we went with the GraphQL in combination with React Context api — for parts that were client-specific.&lt;/p&gt;
&lt;h3&gt;
  
  
  Backend transformation
&lt;/h3&gt;

&lt;p&gt;One action point the team decided on was to start utilizing the power of the GraphQL. In our business case the data model is represented in multiple ways by our tools, helping the user to understand their equity options and their complications by presenting them in different ways. Another great benefit was that we could hide the backend implementation and logic altogether and have one orchestration service/facade which would serve as an “API Contract” giving the team certainty in the expected inputs and outputs of each operation. This in turn gave the ability to generate types for the client apps and queries + mutation hooks to write even less code. Last but not least, having data fetched through GraphQL allowed us to retrieve only the necessary bits of the model and not the whole thing. To read a bit more about this — check out the &lt;a href="https://dev.to/secfi/using-graphql-to-improve-our-microservices-at-secfi-2o2e"&gt;backend article&lt;/a&gt; on the migration. Apollo client also gave us local cache out of the box, so here we saved on even more code, complexity and unnecessary api calls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyw2bypw4xir4rqgwzouh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyw2bypw4xir4rqgwzouh.png" alt="Graphql layer"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Frontend transformation
&lt;/h3&gt;

&lt;p&gt;While &lt;code&gt;slowly&lt;/code&gt; migrating most of the API interactions to the facade we realized that our frontend architecture is not well defined and scalable either. We had two client side applications — client facing and admin facing — that were written in quite different ways and at some point it became a real struggle to switch between projects and fix bugs. This motivated us to define one architectural standard for all frontend apps. We'll cover this process and our learnings and wins in a separate article. With every feature refactored we also moved the backend integration to the Apollo client removing the dependency on the central MobX store. One important thing worth mentioning here is — frontend applications have user interactions-driven state and the Apollo client does not cover this part. For smaller pieces of state we utilize React &lt;a href="https://reactjs.org/docs/hooks-faq.html" rel="noopener noreferrer"&gt;hooks&lt;/a&gt; api — &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useReducer&lt;/code&gt;. For more complex we use React &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;Context&lt;/a&gt; api. There are several top level contexts that handle logic such as authentication, theme and multiple feature-specific contexts throughout the app. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxprq8rr3llcsumu9kvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxprq8rr3llcsumu9kvp.png" alt="Frontend setup with models tree and graphql facade"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  How it works now
&lt;/h2&gt;

&lt;p&gt;First, we define a &lt;code&gt;*.graphql&lt;/code&gt; file in the folder where it is going to be used — eg near the container or specific hook. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;fragment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AffiliationOverview&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Affiliation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;logo&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;company_assessment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getAllAffiliationOverview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$customerUuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;affiliations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;allAffiliations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$customerUuid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;totalCount&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;AffiliationOverview&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reader can notice that we define &lt;code&gt;uuid&lt;/code&gt; property inside of each entity — we've configured the Apollo client to use uuid as unique identifiers to handle automatic cache updates and linking (by default it uses &lt;code&gt;id&lt;/code&gt; property). &lt;a href="https://www.apollographql.com/docs/react/data/fragments/" rel="noopener noreferrer"&gt;Fragment&lt;/a&gt; here is a reusable piece of the entity. If we need the same piece of the model in multiple queries in the same file — we move it to the local fragment. If it becomes common for more queries and mutations across the app — we move it to global fragments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmqoy31xdsx0b7k2bzbhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmqoy31xdsx0b7k2bzbhf.png" alt="Graphql fragments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second, we run the &lt;code&gt;generate&lt;/code&gt; command — it will get all the types from the relevant backend environment.&lt;/p&gt;

&lt;p&gt;Now we are able to import the generated hooks and types across our applications and use them as regular React hooks, while ensuring type safety and alignment with our backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGetAllAffiliationOverviewQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@generated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.apollographql.com/docs/react/data/queries/" rel="noopener noreferrer"&gt;Queries&lt;/a&gt; are quite straightforward. &lt;a href="https://www.apollographql.com/docs/react/data/mutations/" rel="noopener noreferrer"&gt;Mutations&lt;/a&gt;, on the other hand, become more tricky, especially those that add or remove items in an array. Apollo client is not smart enough to determine how to update the cache in case of addition or removal mutations. There are two ways to do it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simple: provide list of queries to refetch, this way the cache gets updated with the fresh response from the backend; drawback — additional backend call(s)&lt;/li&gt;
&lt;li&gt;more complex but more efficient: update cache manually, it saves on the backend calls, but one needs to mutate the cache which might not be trivial in some cases.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Half a year ago we removed the last bits of the MobX in our apps — logic related to authenticating the user, interacting with session tokens and other profile related bits and pieces. Only the data fetching part migrated to the Apollo client implementation, the rest got its own React Provider(s) and now the whole app interacts with those pieces via hooks. That pull request alone reduced our codebase by 5k lines of code. It's not the line count that made the whole team happy that day, but the realization that now we have one way of interacting with the backend and a year+ long migration has been finished.&lt;/p&gt;

&lt;p&gt;To reiterate, in the end of this process we got:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smaller amount of &lt;a href="https://en.wikipedia.org/wiki/Abstraction_(computer_science)" rel="noopener noreferrer"&gt;abstractions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;most of caching is handled automatically&lt;/li&gt;
&lt;li&gt;code generation, backend and frontend always in sync&lt;/li&gt;
&lt;li&gt;faster loading time due to smaller amount of calls and reduced amount of data transferred&lt;/li&gt;
&lt;li&gt;and &lt;code&gt;last but not least&lt;/code&gt; — happier team maintaining all of this!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>apollo</category>
      <category>mobx</category>
      <category>state</category>
    </item>
  </channel>
</rss>
