<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Felix Ndunda (Efen) on Medium]]></title>
        <description><![CDATA[Stories by Felix Ndunda (Efen) on Medium]]></description>
        <link>https://medium.com/@efenstakes101?source=rss-e43897f484------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*rYInpm_fyra2VNrvsG4Kuw.jpeg</url>
            <title>Stories by Felix Ndunda (Efen) on Medium</title>
            <link>https://medium.com/@efenstakes101?source=rss-e43897f484------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 06 Jun 2026 01:56:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@efenstakes101/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Flutter SQLite Essentials Guide in 5 Minutes]]></title>
            <link>https://medium.com/@efenstakes101/flutter-sqlite-essentials-guide-in-5-minutes-3073799fc430?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/3073799fc430</guid>
            <category><![CDATA[sqlite]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[offline-first]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Wed, 14 Aug 2024 15:28:17 GMT</pubDate>
            <atom:updated>2024-08-14T15:28:17.398Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2GBsERxBcEj_uv3KG3x5-g.png" /><figcaption>Flutter SQLite</figcaption></figure><p>A while ago I wrote an article on <a href="https://medium.com/p/f031527dd649">offline first apps</a>. This is a follow up which offers more details on how to use SQLite in Flutter apps. Hopefully I can get time to write one on React Native in the future.</p><p>SQLite is a lightweight database that is perfect for mobile apps, allowing you to store and query data locally. SQFLite is a Flutter plugin that provides an interface for using SQLite databases in Flutter applications. This guide includes experience and knowledge I have learn’t while working at <a href="https://heylixir.com/">Heylixir</a> and building our <a href="https://apps.apple.com/us/app/heylixir/id6504341128">mobile app</a> which is designed to be offline-first.</p><h3>Setting Up</h3><h4>Step 1: Create a New Flutter Project</h4><p>First, create a new Flutter project:</p><pre>flutter create my_app<br>cd my_app</pre><h4>Step 2: Add Dependencies</h4><p>Open pubspec.yaml and add the sqflite and path dependencies:</p><pre>dependencies:<br>  flutter:<br>    sdk: flutter<br>  sqflite: ^2.0.0+4<br>  path: ^1.8.0</pre><p>Run flutter pub get to install the dependencies.</p><h3>Database Setup</h3><h4>Step 3: Create a Database Helper Class</h4><p>In your lib/services folder, create a new file called database_helper.dart. This file will handle all database operations.</p><pre>import &#39;dart:async&#39;;<br>import &#39;package:path/path.dart&#39;;<br>import &#39;package:sqflite/sqflite.dart&#39;;<br><br>class DatabaseHelper {<br>  static final DatabaseHelper _instance = DatabaseHelper._internal();<br>  factory DatabaseHelper() =&gt; _instance;<br><br>  DatabaseHelper._internal();<br><br>  static Database? _database;<br><br>  Future&lt;Database?&gt; get database async {<br>    if (_database != null) return _database;<br><br>    _database = await _initDatabase();<br>    return _database;<br>  }<br><br>  Future&lt;Database&gt; _initDatabase() async {<br>    String path = join(await getDatabasesPath(), &#39;todo.db&#39;);<br>    return await openDatabase(<br>      path,<br>      version: 1,<br>      onCreate: _onCreate,<br>    );<br>  }<br><br><br>  Future _onCreate(Database db, int version) async {<br>    await db.execute(<br>      &#39;&#39;&#39;<br>      CREATE TABLE todos (<br>        id INTEGER PRIMARY KEY AUTOINCREMENT,<br>        title TEXT,<br>        deadline TEXT<br>      )<br>      &#39;&#39;&#39;,<br>    );<br>  }<br><br>}</pre><h3>4. CRUD Operations</h3><p>Now that we have our database set up, let’s add the methods to perform CRUD (Create, Read, Update, Delete) operations.</p><h4>Step 4: Insert Data</h4><p>To add items to the database, we utilize the <strong>insert</strong> method. This method accepts the <strong>table name</strong> and a <strong>Map</strong> with the data we intent to add to the table as the parameters.</p><pre>Future&lt;int&gt; insertItem(Map&lt;String, dynamic&gt; item) async {<br>  final db = await DatabaseHelper.database;<br>  return await db!.insert(&#39;todos&#39;, item);<br>}</pre><h4>Step 5: Retrieve Data</h4><p>To retrieve all items from the database, we use the update method of SQL Database class. This method accepts a few parameters to allow us to specify which data we are interested in. <strong>where</strong> parameter allows us to define the fields we are querying by and then <strong>whereArgs</strong> is a list of the parameters matching the where fields.</p><pre>Future&lt;List&lt;Map&lt;String, dynamic&gt;&gt;&gt; getItems() async {<br>  final db = await DatabaseHelper.database;<br>  return await db!.query(&#39;todos&#39;);<br>}</pre><h4>Step 6: Update Data</h4><p>To update an item, we use the <strong>update</strong> method of SQL Database class. This method accepts a few parameters to allow us to specify the update criterion:</p><pre>Future&lt;int&gt; updateItem(int id, Map&lt;String, dynamic&gt; item) async {<br>  final db = await DatabaseHelper.database;<br>  return await db!.update(<br>    &#39;todos&#39;,<br>    item,<br>    where: &#39;id = ?&#39;,<br>    whereArgs: [id],<br>  );<br>}</pre><h4>Step 7: Delete Data</h4><p>To delete an item from the database, we use the delete method. It takes paramters similar to get function. <strong>where</strong> parameter allows us to specify the deletion criterion and <strong>whereArgs</strong> is a list of the parameters matching the where fields.</p><pre>Future&lt;int&gt; deleteItem(int id) async {<br>  final db = await DatabaseHelper.database;<br>  return await db!.delete(<br>    &#39;todos&#39;,<br>    where: &#39;id = ?&#39;,<br>    whereArgs: [id],<br>  );<br>}</pre><h4>Step 8: Create a Service</h4><p>In todos/repo.dart, we create a simple service to interact with the database. This service can be imported into your UI or state management class (<a href="https://medium.com/p/3c303cf5e615">Provider</a> or <a href="https://bloclibrary.dev/">Bloc</a>) and used to add data into the database.</p><pre>class TodosRepoService {<br>  static String tableName = &quot;todos&quot;;<br><br>  static Future&lt;int&gt; insertItem(Map&lt;String, dynamic&gt; item) async {<br>    final db = await DatabaseHelper.database;<br>    return await db!.insert(TodosRepoService.tableName, item);<br>  }<br>  <br>  static Future&lt;List&lt;Map&lt;String, dynamic&gt;&gt;&gt; getItems() async {<br>    final db = await DatabaseHelper.database;<br>    return await db!.query(TodosRepoService.tableName);<br>  }<br><br>  static Future&lt;int&gt; updateItem(int id, Map&lt;String, dynamic&gt; item) async {<br>    final db = await DatabaseHelper.database;<br><br>    return await db!.update(<br>      TodosRepoService.tableName,<br>      item,<br>      where: &#39;id = ?&#39;,<br>      whereArgs: [id],<br>    );<br>  }<br><br>  static Future&lt;int&gt; deleteItem(int id) async {<br>    final db = await DatabaseHelper.database;<br>    <br>    return await db!.delete(<br>      TodosRepoService.tableName,<br>      where: &#39;id = ?&#39;,<br>      whereArgs: [id],<br>    );<br>  }<br><br>}</pre><h3>5. Run the App</h3><p>To run the app, use the following command:</p><pre>flutter run</pre><p>This simple guide allows you to insert, update, and delete items in the local SQLite database. You can expand this to include more complex operations, multiple tables, and more advanced features as you grow more comfortable with SQFLite. In the future, I will write another guide on how to update the tables themselves in production. This, while seemingly daunting, is not as complex as one might think and it’s a fairly expected activity for apps that are in production.</p><h4>Conclusion</h4><p>This tutorial provides a basic introduction to using SQFLite in a Flutter application.</p><p>Happy coding! 🎉 and as always Long Live The Code 🚀.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3073799fc430" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Top Tips to Fix Common Flutter Bugs & Issues]]></title>
            <link>https://medium.com/@efenstakes101/top-tips-to-fix-common-flutter-bugs-issues-2fd26062139b?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/2fd26062139b</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[engineering-tips]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Sat, 01 Jun 2024 18:08:20 GMT</pubDate>
            <atom:updated>2024-06-07T12:28:52.818Z</atom:updated>
            <content:encoded><![CDATA[<p>Supercharge you productivity for Flutter mobile engineers</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/393/1*fPYmNvnwJBYTA1BMsUeHXA.png" /><figcaption>A snapshot of Heylixir mobile app by <a href="https://heylixir.com/">Heylixir</a>.</figcaption></figure><p>Productivity has been one of the most popularly used words in 2023 and 2024. Behind every layoff or AI buzzword usage has been productivity. In Flutter, as engineers start building large apps with tens of thousands of lines of code, animations and other performance intensive features, there are common pitfalls they get to.</p><p>In this article, I want to discuss some of these common issues in a more granular fashion. This article will be the first of many that cover things that engineers ought to know to stay ahead of common traps. Let’s go 🚀.</p><h4>When using Provider, prefer context.watch and context.read</h4><p>When using provider, you have a couple of options that allow you to access you store data.</p><p><strong>Consumer</strong></p><p>Example</p><pre>return Consumer&lt;MyActivitiesProvider&gt;(<br>      builder: (context, MyActivitiesProvider activitiesProvider, child) {<br>        List&lt;Activity&gt; activities = activitiesProvider.activities;<br>        bool isLoading= activitiesProvider.isLoading;<br>        String? error = activitiesProvider.error;<br>        <br>        if( isLoading ) {<br><br>          return LoaderWidget();<br>        }<br>        if( error != null ) {<br><br>          return ErrorWidget();<br>        }<br>        if( activities.isEmpty ) {<br><br>          return NoDataWidget();<br>        }<br>        return ListView.builder(<br>          itemCount: activities.length,<br>          itemBuilder: (context, index) {<br>            <br>            return ActivityCard(activity: activities[index]);<br>          },<br>        );<br>      },<br>    );</pre><p>This is all good but the code is more verbose and it definitely reminds most people of Java. Is there a way out? Yes. you could access the data using context. Here’s how:</p><pre>MyActivitiesProvider myActivitiesProvider = context.watch&lt;MyActivitiesProvider&gt;();<br>List&lt;Activity&gt; activities =  myActivitiesProvider.activities;<br>bool isLoading =  myActivitiesProvider.isLoading;<br>String? error =  myActivitiesProvider.error;<br>    <br>if( isLoading ) {<br><br>   return LoaderWidget();<br>}<br>if( error != null ) {<br><br>   return ErrorWidget();<br>}<br>if( activities.isEmpty ) {<br><br>   return NoDataWidget();<br>}<br>return ListView.builder(<br>  itemCount: activities.length,<br>  itemBuilder: (context, index) {<br>        <br>     return ActivityCard(activity: activities[index]);<br>   },<br>);</pre><p>The clarity here is undeniable. In this case, i used <strong>context.watch</strong> because I need to be notified of any changes to the state in realtime but if that’s not a requirement, <strong>context.read</strong> would suffice.</p><h4><strong>Use Builder widgets when creating lists</strong></h4><p>Flutter builder widgets offer a performance boost and efficiently than plain ListViews and GridViews. ListView and GridViews create all items at once, the but their builder counterparts create items as they&#39;re scrolled onto the screen, definitely using less resources and offering better UX for users.</p><pre>return ListView(<br>  children: activities.map((e) {<br><br>        return ActivityCard(activity: activities[index]);<br>      }).toList(),<br>);<br><br>// PREFER builder alternative <br>return ListView.builder(<br>  itemCount: activities.length,<br>  itemBuilder: (context, index) {<br>        <br>    return ActivityCard(activity: activities[index]);<br>  },<br>);</pre><h4><strong>Fixing ListTile animation bug when it has tileColor</strong></h4><p>When you have a ListTile with background color then add animations to it, the background color either disappears or it’s shown outside the widget. This issue has definitely hit many Flutter engineers. The first time I encountered this, I had to recreate flutter ListTile with Card to fix the bug.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HgCOmBST_sFtOsEdfPREVg.jpeg" /><figcaption>An image from <a href="http://heylixir.com">Heylixir</a> Social, an animated ListTile without card. Background is janky. Wrapping with Card fixes this bug.</figcaption></figure><p>The fix is very simple and involves little to no code. Wrap the <strong>ListTile</strong> with a <strong>Card</strong> then set the Card’s <strong>color to Colors.transparent</strong> and elevation to 0 if you don’t require the elevation.</p><pre>Card(<br>  color: Colors.transparent,<br>  elevation: 0,<br>  child: Listtile(<br>    ....<br>  ),<br>);</pre><h4>Ensuring Text Inputs are Shown Above Keyboard Always</h4><p>It’s really annoying when users are trying to enter data but the keyboard springs up and obstructs hiding the text input below the keyboard. The user in this case has to scroll the text input into view to see what they are entering. This is a common issue engineers face and a common question in git and stackoverflow.</p><p>The fix? If you are using Scaffold, set <strong>resizeToAvoidBottomInset</strong> to <em>true</em>. Even if you have the text input in a modal bottom sheet without a Scaffold, add it and set the property. I’ve tested the other suggested approaches to fix the issue but this has been the most consistent approach that works in all situations I tested.</p><pre>return Scaffold(<br>  resizeToAvoidBottomInset: true,<br>  ...<br>);</pre><p>Additionally, android has another option that can be set in AndroidManifest.xml to fix the issue:</p><pre>&lt;activity<br>  android:name=&quot;.MainActivity&quot;<br>  android:launchMode=&quot;singleTop&quot;<br>  android:theme=&quot;@style/LaunchTheme&quot;<br>  android:configChanges=&quot;orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode&quot;<br>  android:hardwareAccelerated=&quot;true&quot;<br>  android:windowSoftInputMode=&quot;adjustResize&quot;&gt;<br>  &lt;!-- ...rest of configuration here --&gt;<br>&lt;/activity&gt;</pre><p>While also this works but I don’t prefer it because it’s a platform config that still leaves iOS with the same challenge. In some scenarios, even with the setting, Android still misbehaves and the keyboard hides the currently focused text input which leaves <strong>resizeToAvoidBottomInset: true,</strong> as the more consistent fix.</p><h4>Replace empty container with SizedBox.shrink</h4><p>It’s common to have situations where based on a condition you show a widget with content or an empty container. In this case you could use <strong>Container</strong> by instinct but, <strong>SizedBox.shrink()</strong> should be the Flutter widget of choice.</p><pre>return isPremium ? AnalyticsList() : const SizedBox.shrink();</pre><p>Avoid calling function multiple times when in loading and user clicks it multiple time</p><p>In situations where the user clicks a button and loading begins, there is still a chance that they click the button again especially for long running tasks even when you show them a loader.</p><p>In this case, you could have a state variable isLoading that you set to true when loading begins. While loading, you could set <strong>onPressed</strong> or <strong>onTap</strong> to null.</p><pre><br>class LoginScreen extends StatefulWidget {<br>  const LoginScreen({super.key});<br><br>  @override<br>  State&lt;LoginScreen&gt; createState() =&gt; _LoginScreenState();<br>}<br><br>class _LoginScreenState extends State&lt;LoginScreen&gt; {<br>  bool isLoading = false;<br><br>  @override<br>  Widget build(BuildContext context) {<br>    return ElevatedButton.icon(<br>      onPressed: isLoading ? null : _login,<br>      icon: isLoading ? const CircularProgressIndicator() : const Icon(Icons.join_inner_sharp),<br>      label: const Text(&quot;Login&quot;),<br>    );<br>  }<br><br>  _login() async {<br>    setState(()=&gt; isLoading = true);<br><br>    try {<br>      <br>    } catch (e) {<br>      <br>    }<br>    setState(()=&gt; isLoading = true);<br>  }<br>  <br>}</pre><h4>Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is x.x.x, expected version is x.x.x.</h4><p>This is a common gotcha sometimes when using packages from pub.dev. Recently I had to fix this and while there are alot of questions about this, the fixes are somewhat unreliable.</p><p>A common theme that even the flutter cli will recommend is updating <strong>ext.kotlin_version</strong>. This however does not work on its own. even flutter clean and clearing pub_cache may not work.</p><p>The fix lies in <strong>android/settings.gradle</strong>. here is what its <strong>plugins</strong> section may look like:</p><pre><br>plugins {<br>    id &quot;dev.flutter.flutter-plugin-loader&quot; version &quot;1.0.0&quot;<br>    id &quot;com.android.application&quot; version &quot;7.3.0&quot; apply false<br>    id &quot;org.jetbrains.kotlin.android&quot; version &quot;1.7.1&quot; apply false<br>}</pre><p>Assuming your error looks like:</p><blockquote>Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.9.0, expected version is 1.7.1.</blockquote><p>The fix is to set the version here “id “org.jetbrains.kotlin.android” version “1.7.1” apply false” to 1.9.0. so the plugins section looks like:</p><pre>plugins {<br>    id &quot;dev.flutter.flutter-plugin-loader&quot; version &quot;1.0.0&quot;<br>    id &quot;com.android.application&quot; version &quot;7.3.0&quot; apply false<br>    id &quot;org.jetbrains.kotlin.android&quot; version &quot;1.9.0&quot; apply false<br>}</pre><p>Next, in <strong>android/buid.gradle</strong> in <em>buildscript</em> or allprojects section, add this line:</p><pre><br>ext.kotlin_version = &#39;1.9.0&#39;</pre><p>In my case, I was able to fix it by updating <strong>android/settings.gradle </strong>alone<strong>.</strong></p><p>That’s all for now. Hope this article offers some tips and fixes for common issues you may face in your Flutter engineering career. Remember, this will be an ever evolving article so when you visit the next time there may be more tips and fixes here.</p><p>Happy Building and as always Long Live The Code 🚀.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2fd26062139b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Boosting Next.js App Performance: A Guide to Optimization]]></title>
            <link>https://medium.com/@efenstakes101/boosting-next-js-app-performance-a-guide-to-optimization-20735bc5f09b?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/20735bc5f09b</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[nextjs]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[user-experience]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Mon, 27 May 2024 20:00:19 GMT</pubDate>
            <atom:updated>2024-05-27T20:01:08.902Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J9sZsv3qzrGHSzo3wCbM3Q.png" /><figcaption>Image of <a href="https://nextjs.org/">nextjs</a> website Lighhouse performance.</figcaption></figure><p>Next.js, a powerful React framework, excels in creating fast and SEO-friendly web applications. Performance and UX of these applications can however differ depending on the components used as well as an applications logic.</p><p>Recently while building <a href="https://heylixir.com/">Heylixir’s</a> website, we used 3D components and our website bundle turned out to be huge, the site loading took a long time and the user experience took a hit as a result. This is where I realized that we had to maximize user experience by doing some performance optimization to reduce the <a href="https://heylixir.com">website’s</a> loading time as well as the build bundle. This article explores various strategies to streamline your Next.js app and ensure its lightning-quick delivery.</p><h4>Leveraging Next.js Built-in Optimizations:</h4><p><strong>next/image:</strong> This versatile component streamlines image handling, offering:</p><ol><li><strong>Lazy Loading:</strong> Images are loaded only when they enter the viewport, minimizing initial page load time.</li><li><strong>Automatic Resizing:</strong> Images are resized to fit the device’s screen dimensions, reducing data usage and optimizing display.</li><li><strong>Responsive Images:</strong> Images are served in appropriate formats (WebP for modern browsers, JPEG for older ones) based on user device, enhancing compatibility.</li></ol><pre>import Image from &#39;next/image&#39;;<br><br>function MyImage() {<br>  return (<br>    &lt;Image<br>      src=&quot;/path/to/image.jpg&quot;<br>      alt=&quot;My Image&quot;<br>      width={640}<br>      height={480}<br>    /&gt;<br>  );<br>}</pre><p><strong>next/link</strong>: This component prefetches linked pages in the background, resulting in smoother page transitions when users navigate between them.</p><pre>import Link from &#39;next/link&#39;;<br><br>function MyLink() {<br>  return (<br>    &lt;Link href=&quot;/about&quot;&gt;<br>      &lt;a&gt;About Us&lt;/a&gt;<br>    &lt;/Link&gt;<br>  );<br>}</pre><p><strong>next/script</strong>: Manage third-party scripts efficiently with next/script. Control loading behavior (defer, beforeInteractive, etc.) and execution order for optimal performance.</p><pre>import Script from &#39;next/script&#39;;<br><br>function MyScript() {<br>  return (<br>    &lt;Script<br>      src=&quot;https://www.site.com/pytorchjs.js&quot;<br>      strategy=&quot;afterInteractive&quot;<br>    /&gt;<br>  );<br>}</pre><p><strong>next/dynamic</strong>: enables loading components only when required, further optimizing your application’s initial bundle size. This is particularly beneficial for components that are used conditionally or on specific routes. This is probably one of my favourite methods especially when I’m building websites with 3D components. It helps reduce the bundle size as well as improve overall UX for users for example with <a href="https://heylixir.com/">heylixir</a>.</p><pre>import dynamic from &#39;next/dynamic&#39;;<br><br>const Site3DExperienceComponent = dynamic(<br>  () =&gt; import(&#39;./components/experience&#39;),<br>  { ssr: false } // Disable server-side rendering if not needed<br>);<br><br>function MyPage() {<br>  const showConditionalComponent = true; // Or based on a prop or state<br><br>  return (<br>    &lt;div&gt;<br>      {/* Other content */}<br>      {showConditionalComponent &amp;&amp; &lt;Site3DExperienceComponent /&gt;}<br>    &lt;/div&gt;<br>  );<br>}</pre><h3>Advanced</h3><ol><li><strong>Code Splitting and Tree Shaking</strong>: Code splitting partitions your application’s JavaScript code into smaller bundles, ensuring only essential code loads on initial page render. This reduces initial load time. Tree shaking, a webpack optimization, eliminates unused code within your bundles, further minimizing bundle size.</li><li><strong>Font Optimization:</strong> Utilize tools like font-optimization or fontmin to compress font files.</li><li><strong>Third-Party Library Evaluation:</strong> Scrutinize third-party libraries for performance impact. Consider alternatives or only import necessary components.</li><li><strong>Code Analysis:</strong> Tools like webpack-bundle-analyzer help identify unused code within your bundles for targeted removal.</li><li><strong>Content Delivery Networks (CDNs):</strong> Utilize CDNs to serve static assets from geographically distributed servers, significantly reducing latency for users worldwide.</li><li><strong>Caching:</strong> Implement caching mechanisms for static assets and API responses to minimize server requests.</li></ol><p><strong>Remember</strong>, Balance is Key, optimize without sacrificing functionality. Measure and Iterate<strong>; r</strong>egularly evaluate performance and refine your approach based on data.</p><p>By following these techniques and continuously monitoring your Next.js application’s performance, you can create a noticeably faster and more responsive user experience.</p><p>Hope this helps. Happy Building 🚀 and as always Long Live The Code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=20735bc5f09b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Soft Skills Every Senior Engineer Needs in the Age of AI]]></title>
            <link>https://medium.com/@efenstakes101/soft-skills-every-senior-engineer-needs-in-the-age-of-ai-a65fe75f589a?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/a65fe75f589a</guid>
            <category><![CDATA[soft-skills]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[code]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Wed, 17 Apr 2024 09:49:34 GMT</pubDate>
            <atom:updated>2024-04-17T09:49:34.571Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2CMuHZlp3ZvGUgvPABfhhg.jpeg" /><figcaption>Soft Skills Every Senior Engineer Needs in the Age of AI</figcaption></figure><h3>The Soft Skills Every Senior Engineer Needs in the Age of AI</h3><p>The rise of AI has been a cause of concern for many and yes, that has been for a good reason. We are at the time of AI and investor satisfaction now which means that the workforce interests have taken a back seat.</p><p>While AI can automate certain tasks, the irreplaceable value of senior engineers lies not just in their technical expertise, but in their mastery of the often-overlooked soft skills. Here’s why communication, collaboration, and problem-solving are the secret weapons that will keep senior engineers at the forefront of the tech revolution.</p><h4><strong>Communication: From Binary to Boardrooms</strong></h4><p>Senior engineers are no longer isolated code wizards. We’re expected to translate complex technical concepts into clear, concise language for stakeholders, clients, and even junior team mates. This requires exceptional written and verbal communication skills.</p><p>Imagine explaining a new AI-powered recommendation system to a room full of business executives — being able to break it down into layman’s terms without sacrificing accuracy is a superpower.</p><h4><strong>Collaboration</strong></h4><p>Software development is rarely a one-man show. Senior engineers lead and mentor junior developers, creating a collaborative environment where products and services can be delivered as envisioned.</p><p>This requires active listening, the ability to delegate effectively, and a healthy dose of empathy. A senior engineer who can build strong relationships within the team gets the best out of everyone, leading to more innovative and efficient solutions.</p><h4><strong>Problem-Solving</strong></h4><p>AI might be impressive at pattern recognition, but it can’t replicate the human ability to think outside the box. Senior engineers are the ultimate problem-solvers, the ones who delve into intricate technical issues and emerge with better solutions. This requires critical thinking, the ability to analyze complex situations from multiple angles, and a relentless curiosity. A senior engineer who approaches every challenge with a fresh mindset is an invaluable asset more than a pre-trained model.</p><h4><strong>Sharpening Your Soft Skills</strong></h4><p>So how do you, the seasoned or new engineer, further grow these crucial soft skills? Here are a few tips:</p><ul><li><strong>Seek opportunities to present technical concepts to non-technical audiences.</strong> Volunteer for training sessions or write blog posts (like this one) explaining complex topics in a clear and engaging way.</li><li><strong>Become an active listener.</strong> Pay attention to what your teammates are saying, both verbally and non-verbally. Ask clarifying questions and be open to different opinions.</li><li><strong>Embrace mentorship.</strong> Share your knowledge and experience with junior developers. Use LinkedIn to share your knowledge and the interesting things you are working on. Additionally, help other engineers who have bugs while building.</li><li><strong>Never stop learning.</strong> Take courses, attend workshops, or join online communities focused on soft skills development.</li></ul><p>The future of engineering belongs to those who can wield both the power of code and the power of human connection. By strengthening your soft skills, you, the senior engineer, will not only ensure your own relevance but also become the architect of a more collaborative and innovative tech landscape.</p><p>Remember, your soft skills will be the reason more opportunities find you even after ChatGPT and Google drop their next best models.</p><p>Happy Building and as always Long Live The Code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a65fe75f589a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SwiftUI: A Beginner’s Guide]]></title>
            <link>https://medium.com/@efenstakes101/swiftui-a-beginners-guide-fa2dd7f5cdcc?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/fa2dd7f5cdcc</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Fri, 12 Apr 2024 09:25:22 GMT</pubDate>
            <atom:updated>2024-04-12T09:25:22.505Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nEaYV5btDCyv5bF8tw2_bQ.png" /><figcaption>SwiftUI: A Beginner’s Guide</figcaption></figure><p>So, you’ve decided to dive into the world of app development with SwiftUI? Welcome to the party 🎉. This framework from Apple makes building user interfaces for iPhones, iPads, Macs, and more, an easy process. Whether you’re a coding novice or an experienced developer, SwiftUI offers a powerful and intuitive approach to bring your app ideas to life.</p><p>This guide will equip you with the essential concepts to kickstart your SwiftUI journey.</p><h4>Swift</h4><p>Before you get anything done with SwiftUI, it’s important to learn Swift itself. This language is at the core of SwiftUI, it’s what you will be working with everyday. Great thing is if you know Java, TypeScript, Kotlin, Rust, Scala or even C++, you will get up and running pretty fast. Some concepts between these languages are shared so knowledge in any of them will give you an upper hand.</p><h4><strong>Declarative Power</strong></h4><p>Unlike traditional coding that dictates every step (imperative style), SwiftUI uses a declarative approach. You simply describe what your UI should look like, and SwiftUI handles the rest behind the scenes. This makes your code cleaner, easier to understand, and lets you focus on the desired outcome.</p><h4><strong>Views &amp; Modifiers: The Building Blocks</strong></h4><p>Imagine a world where everything you see on a screen was a lego block. In SwiftUI, that’s exactly the case. Buttons, text, images, and even layouts — all these are views. You can combine these views using stacks (think vertical stacks with <em>VStack</em> and horizontal ones with <em>HStack</em>) to create complex interfaces. To further customize these views, you have modifiers at your disposal. These let you change the look and feel with properties like color, font size, overlays, and even add animations.</p><h4><strong>State Management</strong></h4><p>Imagine an app that doesn’t update when you change something. It would not be ideal. To ensure your UI stays fresh with dynamic data, SwiftUI offers state management tools. For simple data within a single view, you can use the <em>@State</em> property wrapper. If you need to share data across multiple views, the <em>@ObservedObject</em> protocol comes into play. It helps keep data syncronized in multiple pages.</p><h4><strong>Navigation and Routing</strong></h4><p>SwiftUI provides built-in navigation features like <em>NavigationLink</em>. This lets you effortlessly guide users through your app&#39;s various screens, creating a smooth and intuitive user experience.</p><h4><strong>A Wealth of Learning Resources</strong></h4><p>Apple itself offers fantastic SwiftUI tutorials to get you started. Check the <a href="https://developer.apple.com/xcode/swiftui/">docs here</a>. The developer community is incredibly supportive as well, with tons of online resources, courses, and tutorials available to guide you further.</p><h4><strong>Embrace the Learning Curve</strong></h4><p>SwiftUI is a powerful tool, but like any skill, it takes practice. Start small, experiment frequently, and don’t hesitate to use the available resources. With dedication and these beginner-friendly tips, you’ll be well on your way to crafting beautiful and functional SwiftUI apps.</p><p>If you are curious about iOS development or want to get started, I hope this guide however short offered all the information you need to know to get going.</p><p>Happy Building 🚀 and as always, Long Live The Code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fa2dd7f5cdcc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Ultimate Guide To Surviving AI For Software Engineers]]></title>
            <link>https://medium.com/@efenstakes101/surviving-ai-as-a-software-engineer-637f0717b9a9?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/637f0717b9a9</guid>
            <category><![CDATA[langchain]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Tue, 09 Apr 2024 22:05:28 GMT</pubDate>
            <atom:updated>2024-05-01T12:47:12.358Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oQp8lqmtTa6_9J_MSbRMNQ.jpeg" /><figcaption>Surviving AI As A Software Engineer</figcaption></figure><p><em>How to get ahead of AI and thrive for engineers</em></p><p>The rise of AI has understandably caused concerns for many who wonder what the future holds for them and their livelihoods. For software engineers, things are not any different.</p><p>Visions of robots writing code with frightening efficiency paint a dystopian picture. Is AI here to steal your job? or is it more of a teammate?</p><p>By understanding its capabilities and limitations, and by strategically building your skillset, you can not only survive but thrive in the age of AI-powered engineering. Let’s see how this can be possible.</p><h4><strong>A Double-Edged Sword</strong></h4><p>AI brings a bunch of benefits to the table for engineers:</p><ul><li><strong>Efficiency on Autopilot:</strong> Imagine a tireless assistant handling repetitive tasks like unit testing and code generation. AI can automate these with superhuman speed, freeing you for the strategic aspects of engineering — system architecture, user experience design, and tackling complex problems. For most repetitive tasks, you can let AI do the hard work and then you can do the rest 🚀.</li><li><strong>Bug Fixer:</strong> AI can analyze vast amounts of code, pin-pointing bugs and security vulnerabilities that might escape even the best of engineers. This not only improves software quality but also saves you debugging headaches. Sometimes bugs show up and you have no idea how to fix them, asking AI could be the beginning of solving them ✅.</li><li><strong>Innovation Engine:</strong> AI can analyze user data and identify emerging trends, helping you design software that anticipates user needs and stays ahead of the curve.</li></ul><p>Now that we identified some benefits, lets see some limitations:</p><ul><li><strong>The Black Box Problem:</strong> AI’s decision-making processes can be opaque, making it difficult to understand how it arrives at solutions. Some LLMs have introduced the ability to show sources and the <em>thinking</em> process but for most, there is no transparency in the process. This lack of transparency can be a challenge for debugging and maintaining AI-powered systems without having to improve an existing LLM.</li><li><strong>Creativity Gap:</strong> While AI excels at automation and analysis, it currently lacks the human touch for genuine creative problem-solving. Your ability to craft great solutions and design user-friendly interfaces will remain invaluable.</li><li><strong>Edge Cases:</strong> AI is very fluent at many things. For example, I decided to build a game with Godot the last Christmas. Thing is, <a href="https://godotengine.org/">Godot Engine</a> was updated last year to <a href="https://docs.godotengine.org/en/stable/about/introduction.html">version 4</a> which meant a great amount of the API changed. Things like Kinematic Body are now Character Body, Particles is now GPUParticles3D etc. Asking AI to give me a new <a href="https://godotengine.org/">Godot</a> guide yielded junk results so I ended up building my own <a href="https://python.langchain.com/docs/get_started/introduction/">LLM</a> with the new docs to get things up and running. I imagine for engineers working with new technologies, AI may be less than useful.</li></ul><h4><strong>Thriving in the Age of AI</strong></h4><p>So how do we leverage AI as software engineers and not get left behind? Here are some key strategies:</p><ul><li><strong>Become an AI Engineer: </strong>Don’t shy away from AI. Take online courses, attend workshops, and actively engage with the world of AI. Understanding how AI works and its limitations will make you a better at you job; trust me, it’s a powerful tools.</li><li><strong>The Full Stack Specialist:</strong> While AI might handle specific tasks, a well-rounded software engineer with expertise across the development lifecycle, from design to deployment, will always be in demand. Remember, if you are looking to learn something new, AI can help bridge that gap fast.</li><li><strong>Soft Skills:</strong> Develop your <em>soft skills</em> like communication, collaboration, and critical thinking. The ability to communicate complex technical concepts to non-technical stakeholders and collaborate effectively within teams will be increasingly valuable.</li><li><strong>AI Architect:</strong> Instead of fearing AI, view it as an opportunity to become an “AI architect.” LEarn to integrate AI tools into existing workflows and design human-AI collaboration frameworks.</li></ul><p>The future of software development is not about humans being replaced by machines, at least not in my opinion. It’s about collaboration, a synergy between humans and AI.</p><p>It’s true that AI will take jobs including from engineers but that doesn’t mean that jobs will not exist. While companies cut jobs because of AI, they can also keep you because of it. For those who also love side projects like building SaSS services, AI can give you an edge.</p><p>Happy Building and as always Long Live The Code 🚀.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=637f0717b9a9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Beginner’s Guide to Design Patterns]]></title>
            <link>https://medium.com/@efenstakes101/a-beginners-guide-to-design-patterns-81c8960ec3b9?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/81c8960ec3b9</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[code]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Sun, 07 Apr 2024 11:44:57 GMT</pubDate>
            <atom:updated>2024-04-07T11:44:57.259Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NlLgsqgsrrKLP3snGhQ8Pg.png" /><figcaption>A Beginner’s Guide to Design Patterns</figcaption></figure><p><em>Surviving beyond 50k line of code</em></p><p>Ever look at a beautiful and intricate building and wonder how the architect planned it all out? Well, software design follows a similar principle. Just like blueprints guide construction, design patterns provide a tried-and-tested approach to structuring your code. At least, that is the simplest way I got to understand design patterns.</p><p>In this article, we’ll explore some of the most common design patterns that software engineers use to build robust, maintainable, and flexible software.</p><h4><strong>What are Design Patterns?</strong></h4><p>Imagine you’re building a house. You wouldn’t start from scratch every time, right? You’d likely use a pre-defined floor plan or adapt an existing one to fit your current needs. Design patterns work the same way for code. They are reusable solutions to common software development problems. This way engineers can be more productive and software can be more reliable and efficient.</p><p>There are three main categories of design patterns:</p><ul><li><strong>Creational Patterns:</strong> These patterns focus on how objects are created. A common example is the <strong>Singleton Pattern</strong>, which ensures only one instance of a class exists, useful for things like loggers or database connections.</li><li><strong>Structural Patterns:</strong> These patterns deal with the composition of classes and objects. The <strong>Adapter Pattern</strong> allows incompatible interfaces to work together, like using a round peg in a square hole with an adapter!</li><li><strong>Behavioral Patterns:</strong> These patterns define how objects communicate and interact with each other. The <strong>Observer Pattern</strong> is a great example, where one object (the subject) keeps track of others (observers) and notifies them of any changes it experiences.</li></ul><h4><strong>Benefits of Using Design Patterns</strong></h4><ul><li><strong>Improved Code Readability:</strong> By using established patterns, your code becomes easier for others (and future-you) to understand.</li><li><strong>Increased Maintainability:</strong> Well-designed patterns make modifications and bug fixes simpler. In the long term, most of the second guessing on what to do is reduced and thus, improving maintainability.</li><li><strong>Promotes Reusability:</strong> Patterns provide pre-built solutions that can be adapted and used in different parts of your code or even across projects. Think of the next time you are adding a feature, using design patterns, you would almost always already know what to do.</li></ul><h4><strong>Popular Design Patterns for Beginners</strong></h4><ol><li><strong>Singleton Pattern</strong></li></ol><p>Imagine a light switch that controls all the lamps in your house. Flipping the switch from anywhere turns them all on or off. The Singleton Pattern ensures only one instance of a class ever exists, and provides a central access point to that object. This is useful for things like loggers that track application activity, websocket connections or database connections that need to be shared across your program. There’s only ever one logger or one connection needed, so the Singleton Pattern enforces this rule and simplifies access.</p><p>2. <strong>Factory Pattern</strong></p><p>Think of a car factory that can produce different car models based on your needs. You wouldn’t have to know the exact steps to build a sedan versus a truck. With the Factory Pattern, you create objects without specifying the exact type upfront. Instead, you tell the <em>factory</em> what kind of object you need (sedan, truck, etc.), and it takes care of the behind-the-scenes logic of creating the right object. This approach offers flexibility in your code, especially when you might need to create different types of objects based on certain conditions.</p><p>3. <strong>Facade Pattern</strong></p><p>Have you ever interacted with a vending machine? The buttons and display provide a simple interface to a complex system that dispenses drinks and snacks.</p><p>The Facade Pattern hides the inner workings of a subsystem, making it easier to use. Imagine a complex library for image editing. The Facade Pattern would provide a simplified interface with common operations like resize or crop, hiding the underlying code that performs those actions. This makes your code cleaner and easier to understand for anyone using the library.</p><p>4. <strong>Strategy Pattern</strong></p><p>Imagine different payment methods at an online store, like credit card or cash. The Strategy Pattern lets you choose an algorithm at runtime. The core concept is separating the logic (how to pay) from the object that uses it (the shopping cart). This allows for flexible behavior. You can easily switch between payment methods without modifying the core shopping cart functionality.</p><p>5. <strong>Observer Pattern</strong></p><p>Ever receive notifications on your phone about news updates or social media activity? The Observer Pattern lets one object (like a news service) notify many others (subscribers) about any changes it experiences. Imagine a weather monitoring app. The weather data (subject) can notify various observers (widgets, news feeds) whenever there’s an update, ensuring everyone has the latest information.</p><p>This pattern promotes loose coupling between objects, making your code more modular and easier to maintain.</p><h3>Conclusion</h3><p>Design patterns are a deep topic that devolves in to dozens of other topic that have to do with engineering. The goal of this guide was to offer a starting point for engineers on what I have come to believe are the most common design pattersns. For senior engineers, use this as a refresher on the your design patterns knowledge.</p><p>Happy Building 🚀 and as always, Long Live The Code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=81c8960ec3b9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AWS CLI 101: Commands Every Engineer Needs]]></title>
            <link>https://medium.com/@efenstakes101/aws-cli-101-commands-every-engineer-needs-ca0984d59152?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/ca0984d59152</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cicd-pipeline]]></category>
            <category><![CDATA[aws-cli]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[api-development]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Wed, 03 Apr 2024 19:24:00 GMT</pubDate>
            <atom:updated>2024-04-03T19:24:00.802Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*N9en1vL2yBXji89AZkLuMw.png" /><figcaption>AWS CLI 101: Commands Every Engineer Needs</figcaption></figure><p>AWS Cloud is an engineers playground, offering tons of services for product and platform development. The AWS CLI (Command Line Interface) is the most common tool for interacting with these services directly from your terminal for most engineers.</p><p>Sure, some of us will have scripts or Terraform to automate the process but for a good number of times, the CLI is the common tool. It also empowers automation, scripting, and an overall smoother workflow.</p><p>This guide dives into some essential AWS CLI commands that every engineer should have in their toolbox.</p><h4>aws help</h4><p>No one will remember everything at every moment so considet this to be the only command you should not forget. This will allow you to get more information on commands that you want to use and get you up and running without a google search.</p><p>Use this command to explore all available services (S3, EC2, etc.) and their corresponding commands.</p><pre>aws help</pre><h4>aws configure</h4><p>This command sets your default AWS region and preferred output format (often JSON) and profile. This will generally be the first or second command you run when setting up AWS.</p><pre>aws configure</pre><h4>IAM Management</h4><p>Identity and Access Management (IAM) is the cornerstone of AWS security. This command provides a quick overview of all IAM users within your account. Run:</p><pre>aws iam list-users</pre><h4>S3 Bucket Management</h4><p>Simple Storage Service (S3) is a popular storage solution. To get buckets use:</p><pre>aws s3 ls</pre><p>To list lists the contents of a specific S3 bucket. For instance, to see what&#39;s inside <em>profile-avatars, </em>run:</p><pre>aws s3 ls profile-avatars</pre><h4>Working with Profiles</h4><p>Ever been in a situation where you have multiple aws accounts and still need to use them on the same device? Well, profiles sort that out for you. To add a new profile for example “<em>qa-dev</em>”, run:</p><pre>aws configure --profile qa-dev</pre><p>After that, use the --profile option with other commands to specify which profile you want to use when running CLI commands.</p><h4>Service-Specific Help: aws &lt;service&gt; help</h4><p>Need a deeper dive into a specific service’s commands? Use aws &lt;service&gt; help. For example, to explore all the options for S3:</p><pre>aws s3 help</pre><p>I could list the hundreds of commands that AWS CLI provides but more than 90% would not apply to you. The most common commands are the ones listed above. Depending on whether you are working with AWS Beanstalk, Bedrock, Cognito, Lambda or RDS the commands will differ.</p><p>To learn more about the commands, visit the <a href="https://docs.aws.amazon.com/cli/">AWS CLI documentation</a> <a href="https://docs.aws.amazon.com/cli/">here</a>.</p><p>Happy Building 🚀 and as always Long Live The Code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ca0984d59152" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The 5 Design Patterns For Every Flutter Engineer]]></title>
            <link>https://medium.com/@efenstakes101/the-5-design-patterns-for-every-flutter-engineer-a791bca05db7?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/a791bca05db7</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[engineering]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Wed, 03 Apr 2024 14:09:02 GMT</pubDate>
            <atom:updated>2024-08-24T15:46:49.249Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SdW6KweCfKYbLh4PuM7crw.png" /><figcaption>The 5 Design Patterns For Every Flutter Engineer</figcaption></figure><p><em>Level Up Your Engineering Skills.</em></p><p>Flutter, with its hot reload and tons of widgets, is a dream for crafting beautiful and engaging UIs. But as our apps grows, so does the complexity of managing data flow and keeping your code organized.</p><p>Remember, it’s always advisable to avoid technical debt which for most of the part, happens when your app codebase starts getting to the thousands of lines. This is where design patterns come in — they’re battle-tested solutions to common software development challenges that engineers have faced since system engineering and design began.</p><p>Think of design patterns as architectural blueprints for your code. They provide a structured approach to object creation, communication, and relationships, leading to more:</p><ul><li><strong>Reusability:</strong> Don’t reinvent the wheel! Design patterns offer pre-defined solutions that can be adapted across different parts of your app. Easy huh 😊.</li><li><strong>Maintainability:</strong> Clean and well-structured code is easier to understand, modify, and debug, saving you time and frustration in the long run 🚀.</li><li><strong>Testability:</strong> Design patterns often promote separation of concerns, making it easier to isolate and test individual components of your app ✅.</li></ul><p>Let’s check out some of the most common design patterns for Flutter engineers, along with practical examples to illustrate their power:</p><blockquote>The patterns and principles I share here are helping teams at <a href="https://heylixir.com/">Heylixir</a> build a scalable product with great user experience for both our customers and developers alike.</blockquote><h4><strong>Singleton Pattern</strong></h4><p>Ever needed a central place to store app-wide data like user preferences or a theme manager? The Singleton pattern ensures only one instance of a class exists throughout the application. Imagine a single “SettingsManager” class that controls the app’s theme. Any part of your UI can access this manager to retrieve the current theme settings and style its widgets accordingly. For apps using GraphQL, imagine a single GraphQL client that you can use to execute queries and mutations. An even more common example is a websocket connection, your app will almost always need only one.</p><p>This is where this pattern can be utilized.</p><pre>class SettingsManager {<br>  static final SettingsManager _instance = SettingsManager._internal();<br><br>  factory SettingsManager() =&gt; _instance;<br><br>  SettingsManager._internal();<br><br>  ThemeData _themeData = ThemeData.light();<br><br>  void switchTheme() {<br>    _themeData = _themeData.brightness == Brightness.light ? ThemeData.dark() : ThemeData.light();<br>    // Notify listeners of theme change (implementation omitted for brevity)<br>  }<br><br>  ThemeData getTheme() =&gt; _themeData;<br>}</pre><h4><strong>Factory Method Pattern</strong></h4><p>When you need to dynamically generate UI elements based on data, The Factory Method pattern provides an interface for creating objects without specifying the exact class upfront. This allows for greater flexibility — for instance, a factory class could create different types of buttons (primary, secondary) based on the data it receives.</p><p>For sports lovers think of a dashboard showing the bets a user has placed but depending on the game result, the user can see a won or lost widget.</p><pre>abstract class ButtonFactory {<br>  Widget createButton(String text);<br>}<br><br>class PrimaryButtonFactory implements ButtonFactory {<br>  @override<br>  Widget createButton(String text) =&gt; ElevatedButton(onPressed: null, child: Text(text));<br>}<br><br>class SecondaryButtonFactory implements ButtonFactory {<br>  @override<br>  Widget createButton(String text) =&gt; TextButton(onPressed: null, child: Text(text));<br>}<br><br>// Usage<br>ButtonFactory buttonFactory = (isPrimary) =&gt; isPrimary ? PrimaryButtonFactory() : SecondaryButtonFactory();<br>Widget myButton = buttonFactory(true).createButton(&quot;Click Me&quot;); // Creates a primary button</pre><h4><strong>Provider Pattern</strong></h4><p>The provider pattern is a lightweight state management solution ideal for efficient data management. It leverages InheritedWidget to propagate data changes down the widget tree.</p><p>Think os a global list of user expenses for an expense app. The Provider pattern allows you to create a single <em>ExpenseProvider</em> that holds the counter state and “listens” for changes. Any widget down the tree that needs to display the expenses can access it through the Provider.</p><pre><br>class MyExpensesProvider with ChangeNotifier {<br>  DateTime startDate = DateTime.now().subtract(const Duration(days: 30));<br>  DateTime endDate = DateTime.now();<br><br>  bool isLoading = false;<br>  String? error;<br><br>  List&lt;Expense&gt; expsenses = [];<br><br><br>  MyExpensesProvider() {<br><br>    getExpenses();<br>  }<br><br>  getExpenses() async {<br>    <br>  }<br><br>}</pre><h4><strong>Composition Pattern</strong></h4><p>Flutter’s main strength lies in its composable widget system. This aligns perfectly with the Composition Pattern, which promotes building complex UIs by assembling smaller, reusable widgets.</p><p>This pattern promotes reusability, flexibility and testability.</p><pre>class RoundedButton extends StatelessWidget {<br>  final String text;<br>  final VoidCallback onPressed;<br><br>  const RoundedButton({required this.text, required this.onPressed});<br><br>  @override<br>  Widget build(BuildContext context) {<br>    return TextButton(<br>      onPressed: onPressed,<br>      child: Container(<br>        padding: EdgeInsets.all(16.0),<br>        decoration: BoxDecoration(<br>          color: Colors.blue,<br>          borderRadius: BorderRadius.circular(10.0),<br>        ),<br>        child: Text(text, style: TextStyle(color: Colors.white)),<br>      ),<br>    );<br>  }<br>}<br><br>// Usage<br>Widget myScreen = Scaffold(<br>  body: Center(<br>    child: RoundedButton(text: &#39;Click Me&#39;, onPressed: () =&gt; print(&#39;Button Pressed&#39;)),<br>  ),<br>);</pre><h4><strong>Bloc Pattern</strong></h4><p>The Bloc pattern offers a structured approach for state management, separating the UI (presentation layer) from the business logic (data fetching, calculations, etc.). This leads to cleaner, more maintainable, and highly testable code.</p><p>It includes Blocks that handle events, update and emit state, Events that represent app actions, State which is data contained in an app and the BlocProvider to manage Block lifecycle and provide it to child widgets. For those who are familiar with TypeScript and React, this is very similar to React Redux in a number of ways.</p><pre><br>@immutable<br>abstract class CounterEvent {}<br><br>// Events<br>class IncrementEvent extends CounterEvent {}<br><br>class DecrementEvent extends CounterEvent {}<br><br>// State<br>class CounterState {<br>  final int counter;<br><br>  CounterState(this.counter);<br>}<br><br>// Bloc<br>class CounterBloc extends Bloc&lt;CounterEvent, CounterState&gt; {<br>  CounterBloc() : super(CounterState(0));<br><br>  @override<br>  Stream&lt;CounterState&gt; mapEventToState(CounterEvent event) async* {<br>    if (event is IncrementEvent) {<br>      yield CounterState(state.counter + 1);<br>    } else if (event is DecrementEvent) {<br>      yield CounterState(state.counter - 1);<br>    }<br>  }<br>}<br><br>// Usage (in UI)<br>Widget build(BuildContext context) {<br>  return BlocProvider(<br>    create: (context) =&gt; CounterBloc(),<br>    child: Scaffold(<br>      appBar: AppBar(title: Text(&#39;Counter&#39;)),<br>      body: Column(<br>        mainAxisAlignment: MainCenter,<br>        children: [<br>          BlocBuilder&lt;CounterBloc, CounterState&gt;(<br>            builder: (context, state) =&gt; Text(&#39;Count: ${state.counter}&#39;),<br>          ),<br>          Row(<br>            mainAxisAlignment: MainSpaceEvenly,<br>            children: [<br>              ElevatedButton(<br>                onPressed: () =&gt; BlocProvider.of&lt;CounterBloc&gt;(context).add(IncrementEvent()),<br>                child: Icon(Icons.add),<br>              ),<br>              ElevatedButton(<br>                onPressed: () =&gt; BlocProvider.of&lt;CounterBloc&gt;(context).add(DecrementEvent()),<br>                child: Icon(Icons.remove),<br>              ),<br>            ],<br>          ),<br>        ],<br>      ),<br>    ),<br>  );<br>}</pre><h4>Conclusion</h4><p>Most mobile engineers who work on mobile apps are not as familiar with design patterns and the goal of this guide was to offer a starting point for them as well as to give senior engineers a refresher on the most common patterns.</p><p>I created it for Flutter because the flutter docs don’t exactly offer these patterns in an explicit manner like Swift does for example. Additionally, these are patterns that I currently use at <a href="http://heylixir.com">Heylixir</a>.</p><p>Happy Building 🚀 and as always, Long Live The Code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a791bca05db7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The LLRT Runtime: The Runtime for Serverless APIs]]></title>
            <link>https://medium.com/@efenstakes101/the-llrt-runtime-the-runtime-for-serverless-apis-1e1fb4ce5fe4?source=rss-e43897f484------2</link>
            <guid isPermaLink="false">https://medium.com/p/1e1fb4ce5fe4</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[cloud]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Felix Ndunda (Efen)]]></dc:creator>
            <pubDate>Fri, 29 Mar 2024 20:31:27 GMT</pubDate>
            <atom:updated>2024-03-29T20:31:27.420Z</atom:updated>
            <content:encoded><![CDATA[<p><em>A look at the new entrant into the JavaScript runtime war</em></p><p>If you have been an engineer who uses JavaScript for at least the last 6 or so years then you are familiar with tons of JavaScript runtimes like Bun, Deno, Napa.JS, WasmEdge, NodeJS and probably a few others. Each of these were developed with a promise to make JavaScript a better language in a way; whether by making it lightweight, adding type checking, reducing memory consumption or making the runtime multi-threaded.</p><p>Now we have a new entrant in to this field and the developers are from AWS. This should not be a suprise because AWS engineers have built tons of tools that other engineers can use over time. Their experience working with the cloud and cloud infra has informed the new still experimental runtime called LLR (Low Latency Runtime).</p><p>As they put it:</p><blockquote>LLRT (Low Latency Runtime) is an experimental, lightweight JavaScript runtime designed to address the growing demand for fast and efficient Serverless applications.</blockquote><p>Yes, this is a rather nifty addition to the list especially with the rise of serverless platforms. Since 2020, almost all APIs I have build have been deployed to a serverless environment whether it’s a micro-service or a monolith.</p><p>As these kinds of APIs have increased, AWS saw the need to build their own runtime to try make serverless APIs run faster and effectively. One key issue that has been in everyones mind is, everytime your cloud function is executed for example, their is a cold starts happen.</p><blockquote>A cold start occurs when AWS Lambda needs to boot up a new instance of a function’s container before it can execute the function’s code.</blockquote><p>Given cold starts could take a few seconds, it can be alarming depending on the nature of platform using the API.</p><h4>A way out?</h4><p>Is there a way out of cold starts, yes. I have attached an article by Sean <a href="https://medium.com/analytics-vidhya/out-from-the-cold-a-simple-guide-to-avoiding-cold-boots-by-warming-your-aws-lambda-functions-66af38f286a0">here</a>. There are other ways like not using serverless functions but as we all know, that’s an awfully expensive ordeal that’s rarely justifiable. The most common advice for most people is to always keep serverless functions as nimble as possible, this allows cold starts to take less time.</p><p>And now we have LLRT, at least that’s the hope. The AWS team made a note that their runtime is not the silver bullet. LLRT is meant to be more efficient and faster for smaller serverless functions that don’t particularly run intensive tasks.</p><p>What this means for us is that we will still have to wait a while longer before we can get a runtime that works for all use cases.</p><p>Here are some screenshots from the AWS team showing LLRT vs NodeJS runtimes:</p><p>LLRT</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fqz-oRWL6TpdVexy3nJoYA.png" /></figure><p>NodeJS</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QtUmCeevq2FG1UEKk9-U4w.png" /></figure><h4>Benefits</h4><ul><li><strong>Low latency:</strong> LLRT’s design prioritizes fast startup times and execution, resulting in lower response times for your serverless functions. This is important for real-time applications and microservices.</li><li><strong>Small footprint:</strong> LLRT uses minimal resources, leading to better resource utilization and potentially lower costs on serverless platforms.</li><li><strong>Simplicity:</strong> Its focus on a specific subset of JavaScript features makes it easier to understand and develop for.</li></ul><p><strong>Pros</strong></p><ul><li><strong>Ideal for specific use cases:</strong> LLRT shines in smaller serverless functions like data transformation, real-time processing, authorization, and validation.</li><li><strong>Complementary:</strong> It’s designed to supplement existing components rather than replace everything, offering options for targeted performance gains.</li></ul><p><strong>Cons</strong></p><ul><li><strong>Limited scope:</strong> LLRT isn’t meant for complex applications or computationally intensive tasks, as its stripped-down nature might impact performance.</li><li><strong>Experimental stage:</strong> It’s still under development, so you might encounter bugs or changes in future versions.</li><li><strong>Limited API support:</strong> It adheres to a subset of Node.js APIs, potentially requiring adjustments in existing code.</li></ul><h4>Conclusion</h4><p>Cost, performance and speed have always been on top of my mind when I deploy any API so much so that I have used Go in the past to replace some functions whose performance was lack-luster.</p><p>I was excited to see the new runtime especially because it comes from AWS and it promises to make serverless APIs faster and more efficient. Yes this also means reduced bills from AWS but with the caveat that your functions are also efficient.</p><p>LLRT is still in development so if you want to try it in production, ensure you test it on your QA environment to validate your expectations when you go live.</p><p>When I get some time to do my own benchmark on the runtime, I will be sure to update this article or write a new one with more details on my observations.</p><p>For the curious, the github code for the runtime can be found <a href="https://github.com/awslabs/llrt">here</a>.</p><p>Happy Building and as always, Long Live The Code.</p><p>#aws #cloud #engineering #API #serverless</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1e1fb4ce5fe4" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>