<?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: Michael Mazzone</title>
    <description>The latest articles on DEV Community by Michael Mazzone (@michael_mazzone_87d595a97).</description>
    <link>https://dev.to/michael_mazzone_87d595a97</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%2F2386444%2F30a08443-587f-41c9-afc4-5b54f3595269.jpeg</url>
      <title>DEV Community: Michael Mazzone</title>
      <link>https://dev.to/michael_mazzone_87d595a97</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michael_mazzone_87d595a97"/>
    <language>en</language>
    <item>
      <title>Modular React architecture</title>
      <dc:creator>Michael Mazzone</dc:creator>
      <pubDate>Sat, 09 Nov 2024 02:07:10 +0000</pubDate>
      <link>https://dev.to/michael_mazzone_87d595a97/modular-react-architecture-157n</link>
      <guid>https://dev.to/michael_mazzone_87d595a97/modular-react-architecture-157n</guid>
      <description>&lt;h2&gt;
  
  
  On modular architecture
&lt;/h2&gt;

&lt;p&gt;What's modular architecture? Let's go through an example of what it isn't, and&lt;br&gt;
we'll work towards transforming it. By the end you may be convinced of its&lt;br&gt;
merits or that it's a colossal waste of time.&lt;/p&gt;

&lt;p&gt;This is a real scenario I growth-mindsetted through at work. Names and details&lt;br&gt;
anonymized, but a real-world example of a common concept should be fun to walk&lt;br&gt;
through, if nothing else.&lt;/p&gt;


&lt;h3&gt;
  
  
  Requirements, and how to find them
&lt;/h3&gt;

&lt;p&gt;Our site has a button that lives in the site header. It displays how many&lt;br&gt;
V-Bucks the user has left, but also has some business logic baked into it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If this is their first time visiting the site, open a popover to welcome them
&amp;amp; show something they can do with their V-Bucks&lt;/li&gt;
&lt;li&gt;If they have &amp;lt; 5 V-Bucks remaining, show a popover upselling more&lt;/li&gt;
&lt;li&gt;If they are a Basic user, show one style of button; if SuperDuper user, show
another, fancier button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on. There are many such cases our product managers and project managers&lt;br&gt;
and design managers and Group V-Bucks Directors have dreamed up that we need to&lt;br&gt;
handle.&lt;/p&gt;

&lt;p&gt;Jimbo the intern has been tasked with implementing this because it's just a&lt;br&gt;
button!&lt;br&gt;&lt;br&gt;
He sifts through fifteen conflicting iterations of Figma designs. He finds&lt;br&gt;
requirements in as many separate Word docs as there are PMs. He organizes and&lt;br&gt;
endures seven knowledge transfer sessions with seven teams to uncover the&lt;br&gt;
ancient, proprietary knowledge of which services will provide the data he needs&lt;br&gt;
for user type and V-Bucks count. The content team has reassured him that the&lt;br&gt;
final version of all the strings will be approved by legal and marketing by end&lt;br&gt;
of week, and with that, he's ready to build this button.&lt;/p&gt;


&lt;h3&gt;
  
  
  The hacker approach
&lt;/h3&gt;

&lt;p&gt;Here's the first iteration of his V-Bucks button, popovers, and relevant&lt;br&gt;
business logic.&lt;/p&gt;

&lt;p&gt;Jimbo is pleased with the simple directory structure he's come up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;/v-bucks-button
├── button.tsx
├── index.ts
└── /v-bucks-popover
│ ├── popover.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So he starts building this button, and it begins innocently enough.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VBucksButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VBBProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set up state&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authConfig&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;authConfig&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;vBucks&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetVBucks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;telemetry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vBucksButton.content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useButtonStyles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Derive some state via business logic&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonText&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vBucks&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ERROR&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vBucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// About 25 more lines of various button state, error handling,&lt;/span&gt;
  &lt;span class="c1"&gt;// conditional rendering, with comments throughout explaining&lt;/span&gt;
  &lt;span class="c1"&gt;// why we're showing or hiding something or other&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;popoverProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// About 200 lines of typical popover handling,&lt;/span&gt;
    &lt;span class="c1"&gt;// telemetry, business logic, content to display, etc&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tooltipProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Another 100 lines of the same for tooltip&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;VBucksPopover&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;popoverProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tooltip&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tooltipProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
            &lt;span class="na"&gt;ariaLabel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ariaLabel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`
              about seven-hundred classnames for responsive design,
              accessibility, conditional premium styles, et cetera`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;He's implemented a first go at it. The &lt;code&gt;VBucksPopover&lt;/code&gt; has similarly complex&lt;br&gt;
business logic, error handling, state management, styling, and comments excusing&lt;br&gt;
tech debt in the name of shipping.&lt;/p&gt;

&lt;p&gt;At just under 400 lines, this button is trivially simple. Even if the popover is&lt;br&gt;
another 500 lines of spaghetti. Does "cleaning" it up or splitting it up really&lt;br&gt;
benefit us, or our users, in any way? It depends. If this is all we'll need for&lt;br&gt;
this button, who cares. Let's move on!&lt;/p&gt;

&lt;p&gt;But two months have passed and a PM and designer from another product team love&lt;br&gt;
your button and want it in their app's header. They have a &lt;em&gt;simple&lt;/em&gt; list, no&lt;br&gt;
pressure from their end, of some changes they'd like you to accommodate and if&lt;br&gt;
you could please give an ETA by end of day for LT that'd be great, thanks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update the button's styling and display text based on the app it's shown in&lt;/li&gt;
&lt;li&gt;Show a completely different set of popovers, per app&lt;/li&gt;
&lt;li&gt;Open a new company-wide, standard upsell modal when the user's out of V-Bucks,
but only in some regions, and only to users age 16+, and only if they're in
experiment group A&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Can Jimbo cram all of this new functionality into the same components?&lt;br&gt;&lt;br&gt;
Yes. Will splitting or refactoring benefit the users or impress your managers?&lt;br&gt;&lt;br&gt;
No. But refactoring has some strong arguments at this level of complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dev sanity&lt;/li&gt;
&lt;li&gt;The sanity of the dev who replaces Jimbo when he's PIPed for not refactoring&lt;/li&gt;
&lt;li&gt;More reps, so you do better from the start next time&lt;/li&gt;
&lt;li&gt;Something to blog about later&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  The modular architecture approach
&lt;/h3&gt;

&lt;p&gt;The morals of the Clean Code initiates, and other anal types who know enough to&lt;br&gt;
answer on Stack Overflow regularly, and even your grandparents, look something&lt;br&gt;
like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KISS, DRY, &amp;amp; other acronym blankets&lt;/li&gt;
&lt;li&gt;Separation of concerns&lt;/li&gt;
&lt;li&gt;Atomicity! Decoupling! Onomatopoeia!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are great, and help inform Jimbo's next attempt. He didn't get PIPed after&lt;br&gt;
all, and actually got a promo for delivering ahead of schedule and for sharing&lt;br&gt;
so many meetings and documents.&lt;br&gt;&lt;br&gt;
But he's wiser now and learned a cool way to implement those adages. It looks&lt;br&gt;
something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;/vBucksButton
├── /hooks
│ ├── index.ts
│ └── useButtonState.hook.ts
├── /vBucksPopover
│ ├── /app1Popover
│ │ ├── /hooks
│ │ │ ├── index.ts
│ │ │ └── usePopoverState.hook.ts
│ │ ├── ...
│ ├── /app2Popover
│ ├── index.ts
│ ├── popover.renderer.tsx
│ ├── popover.styles.ts
│ ├── popover.tsx
│ └── popover.types.ts
├── /utils
│ ├── experimentation.util.ts
│ ├── store.util.ts
│ ├── telemetry.util.ts
│ └── vBucks.businessLogic.util.ts
├── button.renderer.tsx
├── button.styles.ts
├── button.tsx
├── button.types.ts
└── index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like tons of boilerplate for a button and popover. Why would this be&lt;br&gt;
better?&lt;br&gt;&lt;br&gt;
It depends. Here's Jimbo's brief overview with rationale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split each component into a container and renderer&lt;/li&gt;
&lt;li&gt;Move state and business logic into hooks&lt;/li&gt;
&lt;li&gt;The container uses hooks and passes along any props to the renderer&lt;/li&gt;
&lt;li&gt;The renderer is concerned only with rendering what it's provided&lt;/li&gt;
&lt;li&gt;Common functionality, business logic, or constants can live in utils&lt;/li&gt;
&lt;li&gt;Separate files for types; they tend to be imported in multiple files and
become circular deps that you need to extract anyways&lt;/li&gt;
&lt;li&gt;Extracted TailwindCSS -- more on this below&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's &lt;strong&gt;infinitely scalable!&lt;/strong&gt; These building blocks aren't broken down by&lt;br&gt;
arbitrary rules like lines of code or "complexity". They're broken down by&lt;br&gt;
purpose: each conceptual boundary serves a single purpose.&lt;/p&gt;

&lt;p&gt;A PM wants you to make 10 new popovers? No problem -- Jimbo's architecture can&lt;br&gt;
handle it.&lt;br&gt;&lt;br&gt;
Leadership wants better metrics on sales in some apps, but other teams don't&lt;br&gt;
have the funding to build out telemetry to support this. Great! We have&lt;br&gt;
telemetry utils that we can horizontally scale to meet various, changing&lt;br&gt;
requirements.&lt;br&gt;&lt;br&gt;
A sweeping redesign means every single popover needs to display different stuff,&lt;br&gt;
based on different conditions. It's typically &lt;em&gt;much&lt;/em&gt; simpler now that all of the&lt;br&gt;
stuff we render, and all the logic we use to render it, exist in well-defined&lt;br&gt;
blocks. They're no longer commingled in a giant pile of conflict and logic&lt;br&gt;
chains 20 lines long.&lt;/p&gt;

&lt;p&gt;Here's a sample of this container / renderer pattern:&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VBucksButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContainerProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// State comes from hooks&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useButtonState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VBucksPopover&lt;/span&gt;
      &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;VBucksButtonRenderer&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;buttonProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VBucksButtonRenderer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RendererProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tooltip&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;tooltipProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
      &lt;span class="nx"&gt;ariaLabel&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ariaLabel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vBucksButton&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tooltip&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* button.styles.ts */&lt;/span&gt;
&lt;span class="nc"&gt;.vBucksButton&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;all-those&lt;/span&gt; &lt;span class="err"&gt;same&lt;/span&gt; &lt;span class="err"&gt;styles-go;&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="py"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;here&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;to-make-it-manageable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="py"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;as-these-grow-ever-larger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Aside&lt;/em&gt;&lt;/strong&gt;: The &lt;a href="https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply" rel="noopener noreferrer"&gt;TailwindCSS docs&lt;/a&gt; explicitly recommend against using &lt;code&gt;@apply&lt;/code&gt; to extract common classes like this. This causes almost zero difference in bundle size, and no other difference than that aside from "you have to come up with class names." Production-grade CSS almost always ends up being dozens of lines long, multiplied by however many elements need styling in a given component. This tradeoff seems worth it 90% of the time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the rest of the existing, and new, business logic lives in hooks &amp;amp; utils!&lt;/p&gt;

&lt;p&gt;This new architecture satisfies the zealots and makes things easier to scale or&lt;br&gt;
delete or move around.&lt;br&gt;&lt;br&gt;
Writing unit tests becomes less painful because you've got well-defined&lt;br&gt;
boundaries. Your renderer no longer needs to mock ten different services to&lt;br&gt;
validate that it shows some set of shinies given some input. Your hooks can&lt;br&gt;
test, in isolation, that they match your intended business logic.&lt;br&gt;&lt;br&gt;
Did your entire state layer just change? It'd be a shame if the code in your&lt;br&gt;
hook was tightly coupled with the code that uses it, but now it's a simpler&lt;br&gt;
change and your renderer is still just expecting some input.&lt;/p&gt;



&lt;h3&gt;
  
  
  Final thoughts
&lt;/h3&gt;

&lt;p&gt;This modular architecture adds a lot of boilerplate and can ultimately provide&lt;br&gt;
zero benefit.&lt;/p&gt;

&lt;p&gt;I can't practically recommend it if you're working on a passion project or&lt;br&gt;
prioritize shipping &amp;amp; providing value above all. If you've got something that&lt;br&gt;
seems like it might expand in scope over time, or that you may want to&lt;br&gt;
completely overhaul after a POC, it can reduce tech debt... sometimes.&lt;br&gt;&lt;br&gt;
You can use tools like &lt;a href="https://plopjs.com/" rel="noopener noreferrer"&gt;Plop&lt;/a&gt; to generate this boilerplate.&lt;/p&gt;

&lt;p&gt;So what did I really learn from Jimbo's work &amp;amp; modular architecture?&lt;br&gt;&lt;br&gt;
Clean Code and acronyms we learn in school and the Well Ackshuallys of the world&lt;br&gt;
are one end of a spectrum. Hacking together functional spaghetti code is another&lt;br&gt;
end, and often works quite well, because ultimately all code is tech debt.&lt;/p&gt;

&lt;p&gt;The best solution exists in some quantum state or combination of these ends, and&lt;br&gt;
the path we choose will likely be decided based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much we care about the thing we're building&lt;/li&gt;
&lt;li&gt;How frequently management is asking for updates and ETAs&lt;/li&gt;
&lt;li&gt;Reading something like this and one approach happens to bubble up into your
consciousness when you build your next thing&lt;/li&gt;
&lt;li&gt;Frustration, pain&lt;/li&gt;
&lt;li&gt;The spaghetti becomes such a perf bottleneck that you're forced to rewrite it&lt;/li&gt;
&lt;li&gt;The boilerplate becomes so draining that you cut corners&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>softwaredevelopment</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
