<?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>Forem: Secfi</title>
    <description>The latest articles on Forem by Secfi (@secfi).</description>
    <link>https://forem.com/secfi</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%2Forganization%2Fprofile_image%2F3612%2F8c7601a6-9bba-40e4-8eba-bde2c9c5d9f6.png</url>
      <title>Forem: Secfi</title>
      <link>https://forem.com/secfi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/secfi"/>
    <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://forem.com/secfi/how-were-discovering-secfis-engineering-culture-1f61</link>
      <guid>https://forem.com/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://forem.com/secfi/mobx-apollo-client-journey-3aam</link>
      <guid>https://forem.com/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>
    <item>
      <title>Using GraphQL to improve our microservices at Secfi</title>
      <dc:creator>Manu Hortet</dc:creator>
      <pubDate>Wed, 16 Jun 2021 13:52:00 +0000</pubDate>
      <link>https://forem.com/secfi/using-graphql-to-improve-our-microservices-at-secfi-2o2e</link>
      <guid>https://forem.com/secfi/using-graphql-to-improve-our-microservices-at-secfi-2o2e</guid>
      <description>&lt;p&gt;A couple of years ago, we at the engineering team at Secfi decided to go GraphQL. This helped us reduce complexity in our system, improve performance and have a more intuitive API. Let's talk about that!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;




&lt;p&gt;Our decision to start using GraphQL was a response to some specific problems we had. So let's start by giving some context about our system, and what those problems were.&lt;/p&gt;

&lt;p&gt;At that point in time, our frontend was made up of a couple of different clients. And as we kept adding features to them, it got clear that they had different needs, data consumption wise. Some of those needs were difficult to fulfill given our backend capacities. &lt;/p&gt;

&lt;p&gt;Our backend was designed as a distributed system. In it, different services written in Node and Python exposed their own REST APIs. Each API allowed clients to interact with the subset of models the service was responsible for. Some of our models were related to one another, although living separately and being manipulated by different services. This created a clear pain point: joining and working with data coming from multiple services. &lt;/p&gt;

&lt;p&gt;As we initially lacked a strategy to fix this on the backend side, logic to operate around it was written in the clients. In these cases, the client would need to call the server multiple times, collecting data from different services. When everything was fetched, it could be joined and used. This was slow and introduced too much unnecessary complexity to the frontend. We identified our first, big need: to simplify our clients.&lt;/p&gt;

&lt;p&gt;But having a distributed system came with another drawback for us, data management wise. The APIs of the multiple services tended to be slightly different as they were written using various frameworks and languages. This also added extra complexity to the clients, which needed to be able to interact with the server in multiple ways. Moreover, it made working around the system less intuitive. &lt;/p&gt;

&lt;p&gt;To sum up, our data strategy was causing us these problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frontend was getting complex.&lt;/li&gt;
&lt;li&gt;The frontend was getting slow.&lt;/li&gt;
&lt;li&gt;Fetching data was not intuitive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;




&lt;p&gt;The problem was clearly identified now. We needed to rethink our data strategy. The solution had to come from tweaking our distributed system, not from punishing our clients any more.&lt;/p&gt;

&lt;p&gt;One of the ways we figured could potentially improve the situation, was to start using the &lt;a href="https://refactoring.guru/design-patterns/facade" rel="noopener noreferrer"&gt;facade pattern&lt;/a&gt;. This software pattern was introduced in the Gang of Four's prominent book &lt;a href="https://en.wikipedia.org/wiki/Design_Patterns" rel="noopener noreferrer"&gt;Design Patterns&lt;/a&gt;, and using it we expected to move the complexity that our data model had brought to the clients away from them. This complexity wouldn't disappear, but would be treated by a new service (the facade), focused on concentrating and minimizing it. &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%2Fi%2Fvav95ntu7ag4r2svu8i2.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%2Fi%2Fvav95ntu7ag4r2svu8i2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we had decided on the facade pattern, &lt;strong&gt;GraphQL&lt;/strong&gt; started to look like part of the ideal solution. This is because GraphQL is designed to get many resources in a single request, and that was exactly what we wanted to allow our clients to do. The new facade service would then be a GraphQL server, using the aggregate of all our different models as a schema.&lt;/p&gt;

&lt;p&gt;Our new GraphQL server, acting as a facade, also dissipated the problem we had with the backend not being intuitive. This is because we could now always be served by the facade when requesting any data. There is no more need to talk to different services, in different ways. Now designing new services was more friendly, as choosing new frameworks or simply API designs was not a problem in the frontend.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;




&lt;p&gt;After having used the facade pattern and GraphQL for a while, we can say we are happy with the results. The refactor was expensive, but our original problems have been mitigated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complexity was effectively reduced in the frontend. The developer experience is now nicer, and adding features is faster.&lt;/li&gt;
&lt;li&gt;Performance was improved. Most data management happens now on the server side, reducing communication times.&lt;/li&gt;
&lt;li&gt;Our API got to be more intuitive and easier to interact with. Also, we can now check the auto-generated Docs offered by Apollo Server's &lt;a href="https://www.apollographql.com/docs/apollo-server/testing/graphql-playground/" rel="noopener noreferrer"&gt;GraphQL Playground&lt;/a&gt;. Pretty cool!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  What is next?
&lt;/h2&gt;




&lt;p&gt;We want to keep stepping up our GraphQL game, of course! Some of the initiatives we are discussing or already working on are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Federating our services. This aims at improving separation of concerns across our backend. You can read more about federation &lt;a href="https://www.apollographql.com/docs/federation/federation-spec/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Using DataLoader. As our product scales up, we are working to improve the platform's performance. The &lt;a href="https://github.com/graphql/dataloader" rel="noopener noreferrer"&gt;DataLoader library&lt;/a&gt; is one of the solutions we are considering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Does this sound like fun to you? If so, we may be a good match. 🥰&lt;br&gt;
Consider checking our open positions at &lt;a href="https://www.secfi.com/careers" rel="noopener noreferrer"&gt;secfi.com/careers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>microservices</category>
    </item>
    <item>
      <title>4 simple steps you can take now to improve your TypeScript codebase</title>
      <dc:creator>Manon</dc:creator>
      <pubDate>Wed, 17 Feb 2021 19:46:39 +0000</pubDate>
      <link>https://forem.com/secfi/4-simple-steps-you-can-take-now-to-improve-your-typescript-codebase-58ca</link>
      <guid>https://forem.com/secfi/4-simple-steps-you-can-take-now-to-improve-your-typescript-codebase-58ca</guid>
      <description>&lt;p&gt;&lt;em&gt;Because in an ideal world, readability and maintainability would be the north star of every programmer.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;TL;DR&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make your TS Config as strict as possible so you can agree on naming conventions, avoid typing errors, etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a linter and formatter tool so your team can focus on the real deal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agree on a project architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leverage the power of pair programming to solve complex issues&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Don't try to abstract so much that your teammate (and, most likely, your future self) cannot understand your code later. When working within a team, often the most critical issue is to read and understand other people's code. Focusing on readability and maintainability will not only help you read and refactor your code in two months from now, but it will also help the whole team to be more productive, efficient, and, overall, happy!&lt;/p&gt;

&lt;p&gt;Readable and maintainable codebases are also key when it comes to scaling your application. When starting a new project, it is better to start simple and small with strong and clear foundations rather than over-engineering your application without even knowing where your project will be in a few months from now.&lt;/p&gt;

&lt;p&gt;But what can you do to make readability and maintainability your north star?&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Make your TS Config as strict as possible
&lt;/h2&gt;

&lt;p&gt;If you can, make your TS Config strict. You might have tons of errors, to begin with, but this is worth it as you will enjoy all the benefits of better type safety.&lt;br&gt;
Here are some of the most useful rules you can enable in your TSconfig file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"strict":&lt;/code&gt; the strict flag will enable a wide range of type checking, therefore, resulting in stronger guarantees of program correctness. If you turn this on, you will enable all of the strict mode family options. If you want to enable only some of the strict family (see below), it is not necessary to enable strict.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"strictNullChecks":&lt;/code&gt; set this rule to truewill save you a considerable amount of Javascript errors; especially the much-loved runtime error 'undefined' is not a function , frequently caused by bugs in JavaScript code. With strictNullChecksenabled, TypeScript won't allow you to use a variable that is not known to the compiler (an exception is to be made with the use of any typed variables, more on this later).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"strictBindCallApply"&lt;/code&gt;: this rule is also super useful as it will check that the built-in methods of functions call, bindand apply are correctly invoked.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"strictFunctionTypes":&lt;/code&gt; if enabled, function parameters are checked more correctly. However, this rule doesn't apply to functions written in the method syntax, only for function syntax.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"forceConsistentCasingInFilesNames":&lt;/code&gt; enabling this rule will be useful if you are working on a project where developers use different OS because it will prevent issues related to the file casing and how the files are referenced in the code. TypeScript will thus issue an error if a program tries to include a file with a casing different from the casing on disk.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"noImplicitAny":&lt;/code&gt; TypeScript will issue an error whenever it would have found a type any. This rule is really strict and probably hard to implement in large codebases or codebases transitioning to TypeScript.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"noImplicitThis":&lt;/code&gt; TypeScript will raise an error if your code has implied any type of "this" expression.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"noImplicitReturns":&lt;/code&gt; if you enable this rule, TypeScript will check all code paths in a function to ensure they actually return a value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"noUnusedParameters":&lt;/code&gt; enabling this will raise errors on unused parameters in functions.&lt;br&gt;
For full reference, you can check the official documentation here.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use a linter and formatter tool
&lt;/h2&gt;

&lt;p&gt;Why is it so critical to have a TypeScript code that is readable, well-formatted, and clean? Because it will allow programmers to focus on what they do best and enjoy the most: implement business logic, improve performance, enhance the architecture of a codebase, build a UI library… you name it!&lt;br&gt;
Using a linter and formatter tool (ESlint, Prettier…) will provide consistency to your codebase and make your team happier. And, we all know that a happy team is an efficient one! By keeping your TypeScript clean with linters and formatters, you are avoiding long debates among programmers regarding missing semi-colons or indentation (oh, joy!)&lt;/p&gt;

&lt;p&gt;Your codebase will become:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;easier to read and start with for new joiners&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;easier to review&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;easier to refactor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a happier place where programmers have fewer frictions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Agree on a project architecture
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;As Daniel Irvine pointed out in &lt;a href="https://dev.to/d_ir/clean-code-dirty-code-human-code-6nm?signin=true"&gt;this article&lt;/a&gt;, 'almost always the biggest problem I see is interpersonal issues that stem from disagreements about project direction and structure.'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are working on a solo project or within a team, you will always be rewarded if you agree and follow a clear project structure. This will allow you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;onboard&lt;/strong&gt; new joiners more easily&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;navigate your project in a &lt;strong&gt;structured and clear way&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;find relevant files faster&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;better refactor&lt;/strong&gt; your code as it will be easier to see the bigger picture within your project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;overall, &lt;strong&gt;enhance your productivity and happiness&lt;/strong&gt; with working on your project&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Use the power of pair programming to solve complex issues
&lt;/h2&gt;

&lt;p&gt;Why should you consider pairing with a teammate more often? For many good reasons!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It's &lt;strong&gt;fun and creates bonding&lt;/strong&gt; within a team, which is not to be neglected as it will most likely improve the overall codebase in the long run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It allows a &lt;strong&gt;faster and better spread of knowledge&lt;/strong&gt; among teams, especially if the programmer leading the session is familiar with a part of the codebase the other teammate is not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Along with the same idea, pair programming will allow a &lt;strong&gt;better transfer of skills&lt;/strong&gt; towards junior developers as they can pick-up tips and tricks from more experienced developers, leading to faster growth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usually, when pair programming, you and your teammate are &lt;strong&gt;programming 'out loud'&lt;/strong&gt;, which ultimately leads to discover hidden items in the code and to a clearer understanding of the complexities.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thanks for reading, and happy coding! 😀&lt;/p&gt;

</description>
      <category>programming</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
