<?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: Bernad Okumu</title>
    <description>The latest articles on DEV Community by Bernad Okumu (@bernad_okumu).</description>
    <link>https://dev.to/bernad_okumu</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%2F2985111%2F6dad69a8-390e-47bd-abbb-451627d540f4.png</url>
      <title>DEV Community: Bernad Okumu</title>
      <link>https://dev.to/bernad_okumu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bernad_okumu"/>
    <language>en</language>
    <item>
      <title>Product Design Isn’t Just UI/UX - Here’s Why That Matters</title>
      <dc:creator>Bernad Okumu</dc:creator>
      <pubDate>Tue, 01 Jul 2025 20:26:54 +0000</pubDate>
      <link>https://dev.to/bernad_okumu/product-design-isnt-just-uiux-heres-why-that-matters-44j</link>
      <guid>https://dev.to/bernad_okumu/product-design-isnt-just-uiux-heres-why-that-matters-44j</guid>
      <description>&lt;p&gt;Let’s settle this: &lt;strong&gt;product design is not just making things look nice and clickable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you think it stops at picking a font or aligning some buttons in Figma… we need to talk.&lt;/p&gt;

&lt;p&gt;Good product design isn’t about decorating features - it’s about &lt;strong&gt;deciding what to build&lt;/strong&gt;, why it matters, and how people actually use it.&lt;/p&gt;

&lt;p&gt;Because here’s the truth: you can have the slickest interface in the world, but if it doesn’t solve a real problem? It's just digital art.&lt;/p&gt;

&lt;p&gt;Let’s break down what product design really is - and why everyone on the team should care.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI/UX Is the Surface, Not the Strategy
&lt;/h2&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UI&lt;/strong&gt; is how it looks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UX&lt;/strong&gt; is how it feels.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product design&lt;/strong&gt; is &lt;em&gt;why it exists&lt;/em&gt; - and &lt;em&gt;whether it actually works&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can design the most elegant screen ever, but if it solves the wrong problem or confuses users… congrats, it’s a beautiful failure.&lt;/p&gt;

&lt;p&gt;Design that works isn’t just clean - it’s &lt;em&gt;clear&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good Design Starts with Questions
&lt;/h2&gt;

&lt;p&gt;Real product design begins before the first pixel is pushed.&lt;/p&gt;

&lt;p&gt;It asks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are we solving?&lt;/li&gt;
&lt;li&gt;Who’s using this?&lt;/li&gt;
&lt;li&gt;What’s the simplest way to help them succeed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes that means saying “no” to a feature. Or removing three steps no one needs. Or using a basic, boring button labeled &lt;em&gt;Start&lt;/em&gt; - because it gets the job done.&lt;/p&gt;

&lt;p&gt;Simple isn’t lazy. Simple is smart.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s Not Just the Designer’s Job
&lt;/h2&gt;

&lt;p&gt;Here’s the secret: product design isn’t owned by “the designer.” It’s shaped by &lt;em&gt;everyone&lt;/em&gt; building the thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers who suggest cleaner flows&lt;/li&gt;
&lt;li&gt;PMs who question a feature’s purpose&lt;/li&gt;
&lt;li&gt;Support teams who highlight user pain&lt;/li&gt;
&lt;li&gt;Testers who catch usability traps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re asking “why are we doing it this way?” - you’re helping design the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UI/UX is part of product design - but not the whole deal.&lt;/li&gt;
&lt;li&gt;Good design solves real problems, not just visual ones.&lt;/li&gt;
&lt;li&gt;Simplicity, clarity, and usefulness &amp;gt; fancy effects.&lt;/li&gt;
&lt;li&gt;Everyone on the team contributes to product design.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>C4.5 Decision Trees in Go: Optimizing for Performance and Scalability</title>
      <dc:creator>Bernad Okumu</dc:creator>
      <pubDate>Fri, 28 Mar 2025 09:35:00 +0000</pubDate>
      <link>https://dev.to/bernad_okumu/c45-decision-trees-in-go-optimizing-for-performance-and-scalability-g5p</link>
      <guid>https://dev.to/bernad_okumu/c45-decision-trees-in-go-optimizing-for-performance-and-scalability-g5p</guid>
      <description>&lt;p&gt;Decision trees are a fundamental machine learning algorithm used for classification and regression tasks. Among them, &lt;strong&gt;C4.5&lt;/strong&gt;, an improvement over &lt;strong&gt;ID3&lt;/strong&gt;, is widely known for handling both categorical and continuous data, pruning trees to reduce overfitting, and dealing with missing values. Implementing C4.5 in &lt;strong&gt;Go&lt;/strong&gt; presents unique challenges and opportunities, particularly in optimizing for performance and scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Implement C4.5 in Go?
&lt;/h2&gt;

&lt;p&gt;Go is well-suited for high-performance computing due to its:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;: Go compiles directly to machine code, avoiding runtime interpretation overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency Model&lt;/strong&gt;: Goroutines and channels allow parallel execution, crucial for large datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Management&lt;/strong&gt;: A balance between garbage collection and low-level memory handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Go’s lightweight nature makes it ideal for handling large datasets efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Concepts of C4.5 Algorithm
&lt;/h2&gt;

&lt;p&gt;C4.5 builds a decision tree using &lt;strong&gt;entropy&lt;/strong&gt; and &lt;strong&gt;information gain ratio&lt;/strong&gt; as key metrics for splitting nodes. The key steps include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Calculate Entropy&lt;/strong&gt;: Measure impurity in a dataset.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute Information Gain Ratio&lt;/strong&gt;: Evaluate the usefulness of a feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose the Best Split&lt;/strong&gt;: Select the feature with the highest gain ratio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle Continuous Values&lt;/strong&gt;: Convert numerical data into discrete bins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pruning&lt;/strong&gt;: Reduce overfitting by removing irrelevant branches.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Optimizing C4.5 in Go
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Efficient Data Structures
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;structs and slices&lt;/strong&gt; instead of traditional object-oriented classes keeps memory footprint low.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Decision Tree Node&lt;/span&gt;
 &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;Feature&lt;/span&gt;      &lt;span class="kt"&gt;int&lt;/span&gt;
     &lt;span class="n"&gt;Threshold&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;
     &lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Right&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;
     &lt;span class="n"&gt;Label&lt;/span&gt;       &lt;span class="kt"&gt;string&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Parallelizing Training with Goroutines
&lt;/h3&gt;

&lt;p&gt;Instead of iterating through all possible splits sequentially, we can use goroutines for parallel computation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;computeGain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gain&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;calculateGain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Custom function&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;gain&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By spawning multiple goroutines, we improve efficiency when working with large datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Memory Optimization
&lt;/h3&gt;

&lt;p&gt;Go’s garbage collector is efficient, but large datasets can cause overhead. Using &lt;strong&gt;sync.Pool&lt;/strong&gt; helps reuse memory and reduce allocations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nodePool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Efficient Sorting for Continuous Values
&lt;/h3&gt;

&lt;p&gt;Sorting is required for handling continuous data splits. Instead of a naive sort, Go’s &lt;strong&gt;sort.Slice()&lt;/strong&gt; function is optimized for performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;feature&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;h2&gt;
  
  
  Visualization: Understanding the Decision Tree Structure
&lt;/h2&gt;

&lt;p&gt;To better visualize the structure of a trained C4.5 tree, here’s an example of a simple decision tree graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        [Feature1 &amp;lt; 5.0]
       /              \
  [Feature2 &amp;lt; 3.5]    [Class: Yes]
  /          \
[Class: No]   [Feature3 &amp;lt; 2.0]
              /           \
        [Class: No]     [Class: Yes]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For performance visualization, tools like &lt;strong&gt;pprof&lt;/strong&gt; in Go can be used to analyze memory and CPU usage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-cpuprofile&lt;/span&gt; cpu.prof
 go tool pprof cpu.prof
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scaling Up: Handling Large Datasets
&lt;/h2&gt;

&lt;p&gt;For large datasets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batch Processing&lt;/strong&gt;: Instead of loading all data into memory, stream data in chunks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Execution&lt;/strong&gt;: Integrate with frameworks like &lt;strong&gt;Ray&lt;/strong&gt; (via Go bindings) or &lt;strong&gt;gRPC&lt;/strong&gt; for parallel computation across multiple nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence with SQLite&lt;/strong&gt;: Store intermediate results in SQLite or a key-value store for checkpointing.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Implementing &lt;strong&gt;C4.5 Decision Trees in Go&lt;/strong&gt; is a powerful approach for creating scalable and efficient classification models. By leveraging Go’s concurrency, memory management, and efficient data structures, we can significantly optimize performance. &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
