<?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: Favor Charles Owuor</title>
    <description>The latest articles on DEV Community by Favor Charles Owuor (@fcharles).</description>
    <link>https://dev.to/fcharles</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3718960%2F9eea2752-24cf-48f5-bdf3-c9d3385cbd68.png</url>
      <title>DEV Community: Favor Charles Owuor</title>
      <link>https://dev.to/fcharles</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fcharles"/>
    <language>en</language>
    <item>
      <title>SOLID</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 12 Oct 2026 11:07:06 +0000</pubDate>
      <link>https://dev.to/fcharles/solid-5eme</link>
      <guid>https://dev.to/fcharles/solid-5eme</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvcvm6rxca16bv9kkaycd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvcvm6rxca16bv9kkaycd.png" alt=" " width="656" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm not talking about a state or matter but a set of five design principles for object-oriented programming:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Single Responsibility&lt;/li&gt;
&lt;li&gt; Open/Closed&lt;/li&gt;
&lt;li&gt; Liskov Substitution&lt;/li&gt;
&lt;li&gt; Interface Segregation&lt;/li&gt;
&lt;li&gt; Dependency Inversion.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Introduced by Robert C. Martin, they describe how classes and modules should be structured so that code stays maintainable, extensible, and testable as it grows.&lt;/p&gt;

&lt;p&gt;Each principle addresses a different aspect of class design — how much a class should do, how it should handle change, how sub-types should behave, how interfaces should be shaped, and how dependencies between modules should be organized.&lt;/p&gt;

&lt;p&gt;Together they form a general vocabulary for describing what "good" object-oriented design looks like, and why certain structures tend to hold up better than others over time.&lt;br&gt;&lt;br&gt;
These principles are as follows:&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Single Responsibility Principle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgq4p7axx5yy2ywh7kxnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgq4p7axx5yy2ywh7kxnw.png" alt=" " width="656" height="399"&gt;&lt;/a&gt;&lt;br&gt;
A class should have only one reason to change — meaning it should be responsible for a single part of the system's functionality.&lt;/p&gt;

&lt;p&gt;Suppose you need to build a class that handles a customer's order: it validates the order, calculates the total price, and sends a confirmation email once the order is placed. Take this for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Order {
  constructor(
    private items: { name: string; price: number; quantity: number }[],
    private customerEmail: string
  ) {}

  validate(): boolean {
    return this.items.length &amp;gt; 0 &amp;amp;&amp;amp; this.items.every(item =&amp;gt; item.quantity &amp;gt; 0);
  }

  calculateTotal(): number {
    return this.items.reduce((sum, item) =&amp;gt; sum + item.price * item.quantity, 0);
  }

  sendConfirmationEmail(): void {
    const total = this.calculateTotal();
    console.log(`Sending email to ${this.customerEmail}: Your order total is $${total}`);
    // actual email-sending logic would go here
  }
}

const order = new Order(
  [{ name: "Keyboard", price: 50, quantity: 1 }],
  "customer@example.com"
);

if (order.validate()) {
  order.sendConfirmationEmail();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a small system that's easy to write and easy to read.&lt;/p&gt;

&lt;p&gt;Now suppose the business wants to switch email providers, or add a second notification channel like SMS. That logic lives inside &lt;code&gt;Order&lt;/code&gt;, so changing it means editing the &lt;code&gt;Order&lt;/code&gt; class directly. Anyone doing so is also touching the same class responsible for validation and price calculation — a change intended only for notifications now carries risk for unrelated logic.&lt;/p&gt;

&lt;p&gt;The same problem appears in reverse: a change to how totals are calculated (say, adding tax) also happens inside a class that has nothing to do with tax rules conceptually, and everything to do with orders, emails, and validation all at once.&lt;/p&gt;

&lt;p&gt;As &lt;code&gt;Order&lt;/code&gt; grows, the probability of it getting bloated is 1.0. To prevent this, the various feature inside need to be placed separately as shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Order {
  constructor(
    public items: { name: string; price: number; quantity: number }[],
    public customerEmail: string
  ) {}
}

class OrderValidator {
  validate(order: Order): boolean {
    return order.items.length &amp;gt; 0 &amp;amp;&amp;amp; order.items.every(item =&amp;gt; item.quantity &amp;gt; 0);
  }
}

class OrderCalculator {
  calculateTotal(order: Order): number {
    return order.items.reduce((sum, item) =&amp;gt; sum + item.price * item.quantity, 0);
  }
}

class OrderNotifier {
  constructor(private calculator: OrderCalculator) {}

  sendConfirmationEmail(order: Order): void {
    const total = this.calculator.calculateTotal(order);
    console.log(`Sending email to ${order.customerEmail}: Your order total is $${total}`);
  }
}

const order = new Order(
  [{ name: "Keyboard", price: 50, quantity: 1 }],
  "customer@example.com"
);

const validator = new OrderValidator();
const calculator = new OrderCalculator();
const notifier = new OrderNotifier(calculator);

if (validator.validate(order)) {
  notifier.sendConfirmationEmail(order);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Order&lt;/code&gt; is now just a data structure. Validation, total calculation, and notification are each handled by a separate class, and each of those classes has exactly one reason to change: &lt;code&gt;OrderValidator&lt;/code&gt; changes only if validation rules change, and the same is true for the others.&lt;/p&gt;

&lt;p&gt;Each class is now easier to test in isolation — testing &lt;code&gt;OrderCalculator&lt;/code&gt; no longer requires a valid email address or triggering an email send, since those concerns no longer live in the same object.&lt;/p&gt;

&lt;p&gt;This is the core of the Single Responsibility Principle: not that a class should have only one method, but that everything inside a class should change for the same reason. When it doesn't, splitting the class along those reasons is usually the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Open/Closed Principle
&lt;/h2&gt;

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

&lt;p&gt;Software entities (classes, modules, functions) should be open for extension but closed for modification — you should be able to add new behavior without changing existing code.&lt;/p&gt;

&lt;p&gt;Suppose the order system needs to support two payment methods: credit card and PayPal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PaymentProcessor {
  processPayment(method: string, amount: number): void {
    if (method === "credit_card") {
      console.log(`Charging $${amount} to credit card`);
      // credit card charging logic
    } else if (method === "paypal") {
      console.log(`Charging $${amount} via PayPal`);
      // PayPal charging logic
    } else {
      throw new Error("Unsupported payment method");
    }
  }
}

const processor = new PaymentProcessor();
processor.processPayment("credit_card", 100);
processor.processPayment("paypal", 50);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This handles both payment methods correctly, and adding a condition for a new one seems simple enough on the surface.&lt;/p&gt;

&lt;p&gt;Now the business wants to add cryptocurrency as a payment option. The easiest fix is another &lt;code&gt;else if&lt;/code&gt; branch inside &lt;code&gt;processPayment&lt;/code&gt;, right?. That means opening a class that already works, editing a method that already handles two other payment types correctly, and hoping the new branch doesn't interact badly with the existing ones.&lt;/p&gt;

&lt;p&gt;As more payment methods get added, this method keeps growing, and every addition means modifying code that has nothing to do with the new payment type but sits in the same function. A typo or an unintended side effect in the new branch also risks breaking the branches already in production, since they all now live in the same block of conditional logic.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PaymentProcessor&lt;/code&gt; isn't closed to modification — every new payment method requires changing it directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface PaymentMethod {
  pay(amount: number): void;
}

class CreditCardPayment implements PaymentMethod {
  pay(amount: number): void {
    console.log(`Charging $${amount} to credit card`);
  }
}

class PayPalPayment implements PaymentMethod {
  pay(amount: number): void {
    console.log(`Charging $${amount} via PayPal`);
  }
}

class CryptoPayment implements PaymentMethod {
  pay(amount: number): void {
    console.log(`Charging $${amount} via cryptocurrency`);
  }
}

class PaymentProcessor {
  processPayment(method: PaymentMethod, amount: number): void {
    method.pay(amount);
  }
}

const processor = new PaymentProcessor();
processor.processPayment(new CreditCardPayment(), 100);
processor.processPayment(new PayPalPayment(), 50);
processor.processPayment(new CryptoPayment(), 25);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PaymentProcessor&lt;/code&gt; no longer contains any knowledge of specific payment types. It depends only on the &lt;code&gt;PaymentMethod&lt;/code&gt; interface and calls &lt;code&gt;.pay()&lt;/code&gt;, regardless of which implementation it receives. Adding a new payment method — say, bank transfer — means writing a new class that implements &lt;code&gt;PaymentMethod&lt;/code&gt;, without touching &lt;code&gt;PaymentProcessor&lt;/code&gt; or any of the existing payment classes at all.&lt;/p&gt;

&lt;p&gt;This is what "open for extension, closed for modification" means in practice: the system gains new behavior through new code, not through edits to code that already works. Each payment method is also isolated from the others, so a bug in &lt;code&gt;CryptoPayment&lt;/code&gt; has no way of affecting &lt;code&gt;CreditCardPayment&lt;/code&gt; or &lt;code&gt;PayPalPayment&lt;/code&gt;, since they no longer share a function body.&lt;/p&gt;

&lt;p&gt;The mechanism enabling this is polymorphism — &lt;code&gt;processPayment&lt;/code&gt; operates on the &lt;code&gt;PaymentMethod&lt;/code&gt; interface rather than on concrete classes, which is also the seed of Dependency Inversion, covered later in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Liskov Substitution Principle
&lt;/h2&gt;

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

&lt;p&gt;Objects of a subtype must be usable anywhere the base type is expected, without breaking the correctness of the program. A subclass should honor every guarantee its parent class makes.&lt;/p&gt;

&lt;p&gt;Suppose the order system needs to support refunds. Standard orders can be refunded, and a gift card order is a special kind of order that gets created the same way and flows through the same system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initial code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Order {
  constructor(public id: number, public total: number) {}

  refund(): void {
    console.log(`Order ${this.id} refunded: $${this.total}`);
  }
}

class GiftCardOrder extends Order {
  refund(): void {
    throw new Error("Gift card orders cannot be refunded");
  }
}

function processReturns(orders: Order[]): void {
  for (const order of orders) {
    order.refund();
  }
}

const orders: Order[] = [
  new Order(1, 80),
  new GiftCardOrder(2, 50),
  new Order(3, 120),
];

processReturns(orders);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;GiftCardOrder&lt;/code&gt; is an &lt;code&gt;Order&lt;/code&gt; as far as TypeScript is concerned, so it fits into the array without complaint, and the code compiles.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;processReturns&lt;/code&gt; refunds order 1, then throws on order 2, and order 3 is never processed. The function was written against &lt;code&gt;Order&lt;/code&gt;, and &lt;code&gt;Order&lt;/code&gt; promises that &lt;code&gt;refund()&lt;/code&gt; works. &lt;code&gt;GiftCardOrder&lt;/code&gt; accepts the type but breaks the promise.&lt;/p&gt;

&lt;p&gt;The compiler offers no help here, since the signatures match exactly. The failure only appears at runtime, and only when a gift card order happens to be in the list. The usual workaround is to add a check inside &lt;code&gt;processReturns&lt;/code&gt;, such as &lt;code&gt;if (order instanceof GiftCardOrder) continue;&lt;/code&gt;. That fixes the symptom but puts knowledge of a specific subtype into code that was supposed to work with any &lt;code&gt;Order&lt;/code&gt;. Every new non-refundable order type would need another check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changed code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Order {
  constructor(public id: number, public total: number) {}
}

interface Refundable {
  refund(): void;
}

class StandardOrder extends Order implements Refundable {
  refund(): void {
    console.log(`Order ${this.id} refunded: $${this.total}`);
  }
}

class GiftCardOrder extends Order {
  // no refund method: it makes no promise to refund
}

function processReturns(orders: Refundable[]): void {
  for (const order of orders) {
    order.refund();
  }
}

const standardOrders: Refundable[] = [
  new StandardOrder(1, 80),
  new StandardOrder(3, 120),
];

processReturns(standardOrders);

const giftCardOrder = new GiftCardOrder(2, 50);
// processReturns([giftCardOrder]); // compile error: not Refundable

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original design made a promise in the base class, &lt;code&gt;refund()&lt;/code&gt; works on every &lt;code&gt;Order&lt;/code&gt;, and then broke it in a subclass. The refactor stops making that promise at the &lt;code&gt;Order&lt;/code&gt; level. Refunding is now a capability described by the &lt;code&gt;Refundable&lt;/code&gt; interface, and only classes that can actually refund implement it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;processReturns&lt;/code&gt; now accepts &lt;code&gt;Refundable[]&lt;/code&gt;, so it can only receive objects that honor the contract. Passing a &lt;code&gt;GiftCardOrder&lt;/code&gt; is a compile-time error rather than a runtime crash, and the function needs no &lt;code&gt;instanceof&lt;/code&gt; checks. Any new refundable order type works with it automatically, and any non-refundable one is excluded by the type system.&lt;/p&gt;

&lt;p&gt;This is the Liskov Substitution Principle: wherever a type is expected, any of its subtypes must work without surprises. A subclass that throws on an inherited method, returns nonsense, or silently does nothing is a signal that the inheritance hierarchy is modeling the wrong relationship. The fix is usually to move the behavior out of the base type and into a narrower abstraction that only the compliant types share.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Interface Segregation Principle
&lt;/h2&gt;

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

&lt;p&gt;No class should be forced to implement methods it does not use. Interfaces should be small and focused, so that implementers only depend on what is relevant to them.&lt;/p&gt;

&lt;p&gt;Suppose the order system needs to handle two kinds of orders: physical orders, which are validated, paid for, shipped, and confirmed by email, and digital orders, such as software downloads, which go through the same flow except that there is nothing to ship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface OrderProcessor {
  validate(): boolean;
  chargePayment(): void;
  shipOrder(): void;
  sendConfirmation(): void;
}

class PhysicalOrder implements OrderProcessor {
  validate(): boolean {
    return true;
  }

  chargePayment(): void {
    console.log("Charging payment for physical order");
  }

  shipOrder(): void {
    console.log("Shipping physical order");
  }

  sendConfirmation(): void {
    console.log("Sending confirmation for physical order");
  }
}

class DigitalOrder implements OrderProcessor {
  validate(): boolean {
    return true;
  }

  chargePayment(): void {
    console.log("Charging payment for digital order");
  }

  shipOrder(): void {
    throw new Error("Digital orders cannot be shipped");
  }

  sendConfirmation(): void {
    console.log("Sending confirmation for digital order");
  }
}

function fulfill(order: OrderProcessor): void {
  if (order.validate()) {
    order.chargePayment();
    order.shipOrder();
    order.sendConfirmation();
  }
}

fulfill(new PhysicalOrder());
fulfill(new DigitalOrder());

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DigitalOrder&lt;/code&gt; satisfies the interface, so it compiles and can be passed anywhere an &lt;code&gt;OrderProcessor&lt;/code&gt; is expected.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OrderProcessor&lt;/code&gt; describes everything an order might do, and &lt;code&gt;DigitalOrder&lt;/code&gt; is forced to accept a method that has no meaning for it. The only options are to leave &lt;code&gt;shipOrder()&lt;/code&gt; empty, which hides the fact that nothing happened, or to throw, as above. Calling &lt;code&gt;fulfill&lt;/code&gt; on the digital order charges the payment and then crashes before the confirmation is sent.&lt;/p&gt;

&lt;p&gt;The interface also creates a dependency that serves no one. Any code that only needs to charge payments, for example, still has to accept an object carrying &lt;code&gt;shipOrder()&lt;/code&gt;, and any change to the shipping signature ripples out to every class implementing the interface, including those that never ship anything.&lt;/p&gt;

&lt;p&gt;This has the same symptom as the previous section, a subtype breaking a promise, but a different cause. There the inheritance hierarchy was modeling the wrong relationship. Here the interface itself is too broad, bundling capabilities that not every implementer has.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changed code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Validatable {
  validate(): boolean;
}

interface Payable {
  chargePayment(): void;
}

interface Shippable {
  shipOrder(): void;
}

interface Notifiable {
  sendConfirmation(): void;
}

class PhysicalOrder implements Validatable, Payable, Shippable, Notifiable {
  validate(): boolean {
    return true;
  }

  chargePayment(): void {
    console.log("Charging payment for physical order");
  }

  shipOrder(): void {
    console.log("Shipping physical order");
  }

  sendConfirmation(): void {
    console.log("Sending confirmation for physical order");
  }
}

class DigitalOrder implements Validatable, Payable, Notifiable {
  validate(): boolean {
    return true;
  }

  chargePayment(): void {
    console.log("Charging payment for digital order");
  }

  sendConfirmation(): void {
    console.log("Sending confirmation for digital order");
  }
}

function charge(order: Validatable &amp;amp; Payable): void {
  if (order.validate()) {
    order.chargePayment();
  }
}

function ship(order: Shippable): void {
  order.shipOrder();
}

function confirm(order: Notifiable): void {
  order.sendConfirmation();
}

const physical = new PhysicalOrder();
const digital = new DigitalOrder();

charge(physical);
ship(physical);
confirm(physical);

charge(digital);
confirm(digital);
// ship(digital); // compile error: DigitalOrder is not Shippable

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The single &lt;code&gt;OrderProcessor&lt;/code&gt; interface has been split into four, each describing one capability. &lt;code&gt;DigitalOrder&lt;/code&gt; implements only the three that apply to it, so it no longer carries a &lt;code&gt;shipOrder()&lt;/code&gt; method that it cannot honor. Attempting to ship a digital order is now a compile-time error instead of a runtime exception.&lt;/p&gt;

&lt;p&gt;Each function also declares only what it needs. &lt;code&gt;ship&lt;/code&gt; accepts anything &lt;code&gt;Shippable&lt;/code&gt; and knows nothing about payment or confirmation, while &lt;code&gt;charge&lt;/code&gt; requires &lt;code&gt;Validatable &amp;amp; Payable&lt;/code&gt; and nothing more. A change to the shipping interface affects only the classes that actually ship.&lt;/p&gt;

&lt;p&gt;This is the Interface Segregation Principle: clients should not be forced to depend on methods they do not use. In practice, an empty method, a method that throws "not supported," or an implementation that ignores half of its interface are all signs that the interface is bundling more than one role. The fix is to split it along those roles and let each class implement only the ones that describe it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Dependency Inversion Principle
&lt;/h2&gt;

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

&lt;p&gt;High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.&lt;/p&gt;

&lt;p&gt;Suppose the order system needs to charge customers through Stripe when an order is placed, and the logic that coordinates placing an order lives in an &lt;code&gt;OrderService&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initial code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class StripeGateway {
  charge(amount: number): void {
    console.log(`Charging $${amount} via Stripe`);
    // call to Stripe's API would go here
  }
}

class OrderService {
  private gateway = new StripeGateway();

  placeOrder(amount: number): void {
    this.gateway.charge(amount);
    console.log("Order placed");
  }
}

const service = new OrderService();
service.placeOrder(100);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; creates its own &lt;code&gt;StripeGateway&lt;/code&gt; and uses it directly. The code is short and does exactly what was asked.&lt;/p&gt;

&lt;p&gt;Now suppose the business moves to a different payment vendor. &lt;code&gt;OrderService&lt;/code&gt; is the class that decides how an order gets placed, yet it contains a hard reference to one specific vendor's class. Switching vendors means editing &lt;code&gt;OrderService&lt;/code&gt;, and so does every future switch. If the new vendor's method is named differently or takes different arguments, the call site inside &lt;code&gt;OrderService&lt;/code&gt; has to change as well.&lt;/p&gt;

&lt;p&gt;Testing has the same problem. &lt;code&gt;placeOrder&lt;/code&gt; cannot be run without triggering &lt;code&gt;StripeGateway&lt;/code&gt;, because the dependency is created inside the class and there is no way to replace it. In a real system that means a test either hits Stripe's API or cannot exist.&lt;/p&gt;

&lt;p&gt;The dependency direction is the issue: the high-level class that holds the business flow depends directly on a low-level class that holds vendor details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changed code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface PaymentGateway {
  charge(amount: number): void;
}

class StripeGateway implements PaymentGateway {
  charge(amount: number): void {
    console.log(`Charging $${amount} via Stripe`);
  }
}

class NewVendorGateway implements PaymentGateway {
  charge(amount: number): void {
    console.log(`Charging $${amount} via NewVendor`);
  }
}

class FakeGateway implements PaymentGateway {
  charged: number[] = [];

  charge(amount: number): void {
    this.charged.push(amount);
  }
}

class OrderService {
  constructor(private gateway: PaymentGateway) {}

  placeOrder(amount: number): void {
    this.gateway.charge(amount);
    console.log("Order placed");
  }
}

// production
const service = new OrderService(new StripeGateway());
service.placeOrder(100);

// switching vendors: no change to OrderService
const switched = new OrderService(new NewVendorGateway());
switched.placeOrder(100);

// testing: no network, and the result can be inspected
const fake = new FakeGateway();
new OrderService(fake).placeOrder(100);
console.log(fake.charged); // [100]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OrderService&lt;/code&gt; now depends on the &lt;code&gt;PaymentGateway&lt;/code&gt; interface and nothing else. It does not know which vendor sits behind it, and it does not create the gateway itself. The gateway is passed in through the constructor, a technique called dependency injection, and the decision about which implementation to use moves out to the code that builds the service.&lt;/p&gt;

&lt;p&gt;The dependency arrows have flipped. Before, &lt;code&gt;OrderService&lt;/code&gt; pointed at &lt;code&gt;StripeGateway&lt;/code&gt;. Now both point at &lt;code&gt;PaymentGateway&lt;/code&gt;: &lt;code&gt;OrderService&lt;/code&gt; uses it, and &lt;code&gt;StripeGateway&lt;/code&gt; implements it. The abstraction is owned by the high-level side, shaped by what the business flow needs, and the vendor classes conform to it. That reversal is where the name comes from.&lt;/p&gt;

&lt;p&gt;Switching vendors becomes a one-line change at the point where the service is constructed, and &lt;code&gt;OrderService&lt;/code&gt; is untouched. Testing becomes straightforward too, since &lt;code&gt;FakeGateway&lt;/code&gt; can stand in for a real vendor and record what was charged without any network call.&lt;/p&gt;

&lt;p&gt;This is the Dependency Inversion Principle: business logic should be written against abstractions, with concrete details supplied from outside. It is also the principle that makes the others pay off in practice. The &lt;code&gt;PaymentMethod&lt;/code&gt; interface from Section 2 follows the same pattern, and injecting it into a service would complete the picture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;These five principles describe different parts of class design, but they aren't independent of one another. &lt;strong&gt;Single Responsibility&lt;/strong&gt; splits code along the lines of what changes together. &lt;strong&gt;Open/Closed&lt;/strong&gt; lets new behavior arrive as new code rather than edits. &lt;strong&gt;Liskov Substitution&lt;/strong&gt; and &lt;strong&gt;Interface Segregation&lt;/strong&gt; keep the contracts between types honest, one at the level of inheritance and the other at the level of interfaces. &lt;strong&gt;Dependency Inversion&lt;/strong&gt; points the dependencies at abstractions, so the other four can hold up as the system grows.&lt;/p&gt;

&lt;p&gt;In practice they overlap. The &lt;code&gt;PaymentMethod&lt;/code&gt; interface from the Open/Closed section is also an abstraction in the Dependency Inversion sense, and the &lt;code&gt;Refundable&lt;/code&gt; interface from the Liskov section is a narrow interface in the Interface Segregation sense. A single refactor often satisfies two or three of them at once, which is why they tend to show up together.&lt;/p&gt;

&lt;p&gt;They are also guidelines rather than rules. Applied to a small script, splitting every class and adding an interface for every dependency produces more files and indirection than the problem warrants. A reasonable approach is to apply a principle when the code gives a concrete reason: a class that keeps changing for unrelated reasons, a conditional that grows with every new variant, a subtype that throws on an inherited method, an interface with methods some implementers can't honor, or a dependency that makes testing impossible. Used that way, SOLID works as a shared vocabulary for describing design problems and their fixes, and the examples above are meant to make that vocabulary easy to recognize in real code.&lt;/p&gt;

&lt;p&gt;For further reading, Robert C. Martin's &lt;em&gt;Agile Software Development: Principles, Patterns, and Practices&lt;/em&gt; is where the principles were laid out in full.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>solidprinciples</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Why Documentation Matters More Than You Think</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Sun, 26 Jul 2026 22:38:19 +0000</pubDate>
      <link>https://dev.to/fcharles/why-documentation-matters-more-than-you-think-4n4e</link>
      <guid>https://dev.to/fcharles/why-documentation-matters-more-than-you-think-4n4e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"Programs must be written for people to read, and only incidentally for machines to execute." — Donald Knuth&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You finally finish your project.&lt;/p&gt;

&lt;p&gt;After hours of debugging, Stack Overflow tabs, and one bug after another, it works. You push it to GitHub, close your laptop, and move on.&lt;/p&gt;

&lt;p&gt;A few months later, you come back to add a new feature.&lt;/p&gt;

&lt;p&gt;You open the repository. Dozens of files. A few variables with names that made perfect sense at the time. Now they don't. You scroll through your own code, trying to remember why you chose this approach over that one.&lt;/p&gt;

&lt;p&gt;Eventually you ask the question almost every developer asks:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Who wrote this?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You did.&lt;/p&gt;

&lt;p&gt;If that sounds familiar, you've already discovered why documentation matters. You don't write it for your teacher, your manager, or your teammates. You write it for your future self — the one who's forgotten everything you know right now.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1780253256194-34e5867ccb8c%3Fq%3D80%26w%3D870%26auto%3Dformat%26fit%3Dcrop%26ixlib%3Drb-4.1.0%26ixid%3DM3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%253D%253D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1780253256194-34e5867ccb8c%3Fq%3D80%26w%3D870%26auto%3Dformat%26fit%3Dcrop%26ixlib%3Drb-4.1.0%26ixid%3DM3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%253D%253D" alt="image" width="870" height="580"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;Photo by &lt;a href="https://unsplash.com/@allysphotos?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Alicia Christin Gerald&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/developer-typing-code-on-a-laptop-screen-xaWYIbNIOdw?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;br&gt;
      &lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Biggest Myth About Documentation
&lt;/h2&gt;

&lt;p&gt;Most developers treat documentation as something you write &lt;em&gt;after&lt;/em&gt; a project is done. That mindset is exactly how projects end up with no documentation at all — "later" rarely comes.&lt;/p&gt;

&lt;p&gt;Documentation isn't the final chapter. It's part of building the thing.&lt;/p&gt;

&lt;p&gt;You wouldn't wait until a house is finished to draw the blueprint — the blueprint guides the construction. Documentation does the same job for code: it records your decisions and explains your reasoning as you go, not after the fact.&lt;/p&gt;

&lt;p&gt;GitHub's own guidance backs this up: a README should explain what your project does, why it exists, how to get started, where to get help, and who maintains it — because for most visitors, it's the first thing they see and it shapes their whole impression of the project.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Documentation Actually Is
&lt;/h2&gt;

&lt;p&gt;Say "documentation" and people picture a massive technical manual. Sometimes it is that. More often, it's much smaller:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A README&lt;/li&gt;
&lt;li&gt;  Installation instructions&lt;/li&gt;
&lt;li&gt;  A comment explaining tricky logic&lt;/li&gt;
&lt;li&gt;  A troubleshooting note&lt;/li&gt;
&lt;li&gt;  A changelog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation is just information that helps someone understand your software — where "someone" might be you in six months, a teammate, a contributor, or a recruiter skimming your GitHub. Good documentation answers questions before people have to ask them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Most of Us Skip It And What It Costs
&lt;/h2&gt;

&lt;p&gt;Documentation isn't exciting. Watching your app finally run &lt;em&gt;is&lt;/em&gt; exciting. Writing a README is not. So beginners tell themselves "I'll document it later," and later rarely comes.&lt;/p&gt;

&lt;p&gt;By the time you return to the project, you've forgotten why you chose that library, what a function actually returns, which environment variables it needs, and which command fixed yesterday's bug. You end up solving the same problem twice — time you could've spent building something new.&lt;/p&gt;

&lt;p&gt;GitHub Star Monica Powell calls personal documentation a "second brain": instead of re-searching for the same answer every time, you write it down once, in a way that makes sense to you, and reuse it. That alone is worth the five minutes it takes.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Hidden Cost of Poor Documentation
&lt;/h2&gt;

&lt;p&gt;Picture two repositories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo A:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
├── README.md
├── src/
├── docs/
└── package.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The README explains what it does, how to install it, how to run it, how to contribute. You clone it and you're running the project in five minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo B:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
├── src/
└── package.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No instructions, no examples, nothing.&lt;/p&gt;

&lt;p&gt;Which one feels more trustworthy? Which one would you actually contribute to?&lt;/p&gt;

&lt;p&gt;Researchers who studied thousands of GitHub repositories found that the README is often what shapes a developer's first impression of a project and whether they can figure out how to use it at all. Documentation builds trust before anyone even opens your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  It Also Makes You a Better Developer
&lt;/h2&gt;

&lt;p&gt;It's easy to assume documentation is purely for other people. It isn't. Writing it forces you to answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  What problem does this actually solve?&lt;/li&gt;
&lt;li&gt;  Why this approach, and not another?&lt;/li&gt;
&lt;li&gt;  What am I assuming the reader already knows?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can't explain your project clearly, you probably don't understand it as well as you think you do. Writing it down is a forcing function for organizing your own thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good Documentation Is Short, Not Exhaustive
&lt;/h2&gt;

&lt;p&gt;The other common misconception: good documentation means &lt;em&gt;a lot&lt;/em&gt; of documentation. It doesn't. It means the &lt;em&gt;right&lt;/em&gt; information.&lt;/p&gt;

&lt;p&gt;GitHub's documentation team recommends writing in plain language, staying concise, and structuring content so people can scan for what they need — not covering every possible edge case. One clear paragraph or a single code example often teaches more than three pages of prose. Quantity isn't the goal; clarity is.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Habit You Can Start Today
&lt;/h2&gt;

&lt;p&gt;Every time you solve a problem that takes more than five minutes, write down four things:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Problem&lt;/span&gt;
The application crashed after deployment.

&lt;span class="gu"&gt;## Cause&lt;/span&gt;
The environment variables weren't configured.

&lt;span class="gu"&gt;## Solution&lt;/span&gt;
Added the missing variables to the production environment.

&lt;span class="gu"&gt;## Prevention&lt;/span&gt;
Add an environment variable checklist before deployment.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. That's documentation. Do this consistently and you'll build a personal knowledge base that gets more valuable every month — your own second brain, one entry at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the README
&lt;/h2&gt;

&lt;p&gt;A README is the entry point — both GitHub's and Google's engineering style guides treat it that way — but it's not the whole picture. Documentation also lives in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Code comments&lt;/li&gt;
&lt;li&gt;  Architecture diagrams&lt;/li&gt;
&lt;li&gt;  API references&lt;/li&gt;
&lt;li&gt;  Troubleshooting guides&lt;/li&gt;
&lt;li&gt;  Changelogs and design decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one saves someone (probably future you) from having to reverse engineer your reasoning from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Documentation is written for people, not computers.&lt;/li&gt;
&lt;li&gt;  Your future self is usually your first reader.&lt;/li&gt;
&lt;li&gt;  Small notes written consistently beat one giant document written at the end.&lt;/li&gt;
&lt;li&gt;  A good README shapes first impressions and builds trust before anyone reads your code.&lt;/li&gt;
&lt;li&gt;  Documentation is part of development — not something that happens after it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time you finish a piece of code, don't just ask "is it done?" Ask: &lt;em&gt;"Would someone else know how to use this?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If the answer is no, your next line shouldn't be code. It should be documentation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In Part 2, we'll build your first documentation habits; the small routines experienced developers follow without even thinking about them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>beginners</category>
      <category>development</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Learn Any New Language or Framework</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Sat, 06 Jun 2026 03:01:50 +0000</pubDate>
      <link>https://dev.to/fcharles/how-i-learn-any-new-language-or-framework-592h</link>
      <guid>https://dev.to/fcharles/how-i-learn-any-new-language-or-framework-592h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FynH5gvz3%2Froadmap.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FynH5gvz3%2Froadmap.jpg" alt="roadmap" width="799" height="533"&gt;&lt;/a&gt; &lt;a href="https://www.magnific.com/free-vector/professional-milestone-routeway-template-route-growth_411786072.htm" rel="noopener noreferrer"&gt;Image by starline on Magnific&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I pick up a new language or framework, I do not start with a course. I do not read documentation for hours. I learn the three things that every language shares, then I build five projects in a specific order.&lt;/p&gt;

&lt;p&gt;This article breaks down exactly what to learn and what to build so you are not wasting time on things that do not matter yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Foundation — Three Things First
&lt;/h2&gt;

&lt;p&gt;Every language, whether it is Python, Go, Rust, or a framework like React, is built on the same three concepts. Learn these first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variables&lt;/strong&gt; — how the language stores data. What types exist. Whether it is typed or not. How you declare something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data structures&lt;/strong&gt; — how the language groups related data. Arrays, lists, objects, dictionaries — whatever it is called. This is how you model things in code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Control structures&lt;/strong&gt; — how you manage decisions and repeat work. If statements, loops, switches. The logic backbone.&lt;/p&gt;

&lt;p&gt;That is the entire foundation. Once you can store data, shape it, and control the flow of your program, you understand enough to start building. Everything else — advanced typing, complex patterns, performance tricks — you can pick them up as you go.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Five Projects
&lt;/h2&gt;

&lt;p&gt;Here is the full arsenal. Each project introduces exactly one new concept. You never jump more than one layer at a time. By the end, you have covered the majority of what real-world development actually requires.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project 1 — The Calculator
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F23wRY33L%2Fcalc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F23wRY33L%2Fcalc.jpg" alt="calc" width="800" height="800"&gt;&lt;/a&gt; &lt;a href="https://www.magnific.com/free-vector/calculator_3232405.htm" rel="noopener noreferrer"&gt;Image by rawpixel.com on Magnific&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The calculator teaches you functions.&lt;/p&gt;

&lt;p&gt;A calculator forces you to write reusable logic. You cannot just write everything in one chunk. You need to take inputs, do something with them, and give back a result. That is the mental model for every function you will ever write.&lt;/p&gt;

&lt;p&gt;What you learn here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to define and use functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to handle inputs and return values&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to break logic into small, reusable pieces&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic error handling — what happens when someone divides by zero&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep it simple. Four operations. A working result. Add a simple interface if you are using a framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project 2 — The Todo List
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FBHDM1xsz%2Ftodolist.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FBHDM1xsz%2Ftodolist.jpg" alt="todolist" width="800" height="667"&gt;&lt;/a&gt; &lt;a href="https://www.magnific.com/free-vector/huge-clipboard-with-checklist-pencil_378116017.htm" rel="noopener noreferrer"&gt;Image by Kampus on Magnific&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The todo list is not about productivity apps. It is about managing data.&lt;/p&gt;

&lt;p&gt;Almost every real application you will ever build does four basic things with data: create it, read it, update it, delete it. A social feed, a shopping site, a dashboard — they all do this.&lt;/p&gt;

&lt;p&gt;What you learn here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to create new data and store it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to read and display a list of items&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to change an existing item&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to remove something you no longer need&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How data changes over time in your program&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you can build a todo list, you can build the data layer of most simple apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project 3 — The Weather App
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FpvmYCkTb%2Fweather.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FpvmYCkTb%2Fweather.jpg" alt="weather" width="800" height="377"&gt;&lt;/a&gt; &lt;a href="https://www.magnific.com/free-vector/meteorological-report-weather-forecast-concept_29156761.htm" rel="noopener noreferrer"&gt;Image by upklyak on Magnific&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where most beginners hit a wall. The calculator and todo list are self-contained — they do not talk to the outside world. The weather app fixes that.&lt;/p&gt;

&lt;p&gt;You call a real weather service. You handle data you did not create and cannot control. You will deal with waiting states, error states, and responses that sometimes do not look the way you expect.&lt;/p&gt;

&lt;p&gt;What you learn here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to handle tasks that take time to finish&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to get data from an outside source&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to show loading, success, and error states&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to work with the data you receive and turn it into something useful&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This single project unlocks more of real-world development than almost anything else you can build at this stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project 4 — The Expense Tracker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FPvXHyHSt%2Fexpense.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FPvXHyHSt%2Fexpense.jpg" alt="expense" width="800" height="533"&gt;&lt;/a&gt; &lt;a href="https://www.magnific.com/free-vector/hand-drawn-payday-template_111676319.htm" rel="noopener noreferrer"&gt;Image by pikisuperstar on Magnific&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The todo list taught you to manage data. The expense tracker teaches you to keep it.&lt;/p&gt;

&lt;p&gt;This project adds memory — data that survives after you close the app. It also introduces summaries: totals, filters, categories. You are not just storing items anymore, you are doing something meaningful with them.&lt;/p&gt;

&lt;p&gt;What you learn here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to save data so it is still there when you reopen the app&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to think about where your data actually lives&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to filter and add up values from a set of data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How a slightly richer list of items changes how you build your app&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Build on your todo list. Same basic approach, but now the data stays and you do more with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project 5 — Login and Protected Pages
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FtNS65Bq%2Fauth.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FtNS65Bq%2Fauth.jpg" alt="auth" width="800" height="533"&gt;&lt;/a&gt; &lt;a href="https://www.magnific.com/free-vector/phishing-account-concept-with-envelope-credit-card_8376570.htm" rel="noopener noreferrer"&gt;Image by freepik&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most apps have two kinds of content: things anyone can see and things only certain people can access.&lt;/p&gt;

&lt;p&gt;What you learn here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How login works in practice&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to remember that someone has logged in&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to hide a page or feature from someone who should not see it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to send someone to the login screen when they try to go somewhere they should not&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need to build a perfect, secure login system. You just need to understand the idea well enough that nothing surprises you when you see it on a real project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;p&gt;Most learning resources teach you everything before you need it. You spend weeks on concepts that only make sense once you have run into the problem they solve. This approach flips that. You learn the minimum needed to start building, then learn the rest when the project demands it.&lt;/p&gt;

&lt;p&gt;The three foundations get you reading and writing the language. The calculator teaches functions. The todo list teaches data management. The weather app teaches waiting for outside data. The expense tracker teaches memory and summaries. Login teaches access control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks and Documentation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Frameworks
&lt;/h3&gt;

&lt;p&gt;A framework is  &lt;em&gt;a set of pre-written code, guidelines, and tools&lt;/em&gt;  that simplify software development&lt;a href="https://mimo.org/blog/what-is-a-framework-definition-and-the-ultimate-guide#:~:text=is%20a%20Framework%3F-,A%20framework%20is%20a%20set%20of%20pre%2Dwritten%20code%2C%20guidelines%2C%20and%20tools%20that%20simplify%20software%20development,-.%20Explore%20our%20101" rel="noopener noreferrer"&gt;[mimo framwork blog]&lt;/a&gt;. React gives you components. Django gives you a database tool and a way to organize pages. None of that changes the three foundations above.&lt;/p&gt;

&lt;p&gt;When I learn a framework, I do the same thing I do with a language. I learn just enough to start building. That usually means learning three framework-specific things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to create a new screen or page&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to show dynamic data on that page&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to respond to a click or user action&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it. Everything else — state management libraries, build tools, advanced routing — can wait until you need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;Documentation is a reference, not a textbook. You do not learn a language by reading every page. You learn by trying to do something, getting stuck, and then looking up the one small thing you need. Think of documentation like a dictionary. You would not learn English by reading a dictionary from cover to cover. You learn by speaking, then checking a word when you do not know it.&lt;/p&gt;

&lt;p&gt;So skip the long reading sessions. Open the docs when you hit a specific problem. Find the answer. Close the docs. Keep building.&lt;/p&gt;

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

&lt;p&gt;Here is the truth most tutorials will not tell you: you do not need to know everything before you build anything. You never will. Even experienced developers look things up constantly. The difference is they do not let that stop them.&lt;/p&gt;

&lt;p&gt;The method here is simple. Learn three basics. Build five small projects in order. Use documentation only when you are stuck. That's it.&lt;/p&gt;

&lt;p&gt;You will forget syntax. You will write messy code. You will get errors that make no sense. But that's part of the learning process. Every error you fix teaches you something that no video or article could ever teach.&lt;/p&gt;

&lt;p&gt;So here is your challenge. Pick a language or framework today. Not next week. Today. Learn the three foundations. Build the calculator. Then the next one. Do not wait until you feel ready. &lt;strong&gt;You will never feel ready&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>devex</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Silent Skills Every Developer Should Build</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 17:06:20 +0000</pubDate>
      <link>https://dev.to/fcharles/silent-skills-every-developer-should-build-56fe</link>
      <guid>https://dev.to/fcharles/silent-skills-every-developer-should-build-56fe</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FMypDD1ZD%2Fskills.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FMypDD1ZD%2Fskills.jpg" alt="skills" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The coming generation of programmers are not those who know how to code, but those who have mastered soft skills."&lt;br&gt;
Co-Executive Director - &lt;a href="https://www.linkedin.com/in/caleb-nyoiro-4660a06a/" rel="noopener noreferrer"&gt;Caleb Nyoiro&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When people start learning software development, most of the attention goes to programming languages, frameworks, and tools.&lt;/p&gt;

&lt;p&gt;Which language should I learn? Should I learn React or Vue? Do I need Docker? What does docker even do?... These are common questions, and they're important. But after spending time around developers, I've noticed something interesting.&lt;/p&gt;

&lt;p&gt;The developers who grow the fastest are not always the ones who know the most frameworks. They're usually the ones who have developed a set of quiet habits that most people don't notice. &lt;/p&gt;

&lt;p&gt;One would call them soft skills. Others call them people skills. But I like calling these &lt;strong&gt;silent skills&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Effective Communication
&lt;/h2&gt;

&lt;p&gt;At first, I thought communication just meant explaining what I did. But Good communication is about reducing confusion for others.&lt;/p&gt;

&lt;p&gt;In a team, vague language creates delays. Saying: “The API is broken.” doesn’t help much. Instead, say: “The login endpoint returns 500 when the token is expired.” This helps someone fix the problem immediately.&lt;/p&gt;

&lt;p&gt;That difference saves time. Communication is not about talking more. It’s about making things clear the first time. &lt;/p&gt;

&lt;p&gt;And not just to tech savvy people but also to the other general public such as a client. Also knowing your audience and adjusting the way you pass information, can help them understand what you are doing. &lt;/p&gt;

&lt;p&gt;It also shows that you want them to understand what you are doing which would allow them to trust you more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teamwork and Collaboration
&lt;/h2&gt;

&lt;p&gt;Software development is rarely solo work. Even if you write code alone, your work connects to other people’s systems.&lt;/p&gt;

&lt;p&gt;Early on, I treated my tasks like isolated assignments. My job was to finish my part. That mindset causes friction.&lt;/p&gt;

&lt;p&gt;Real teamwork is about awareness. You think about how your changes affect QA, backend, frontend, and product decisions.&lt;/p&gt;

&lt;p&gt;You also accept feedback without turning it into conflict.  Good collaboration is simple. You should care about the shared goal more than being right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem-Solving
&lt;/h2&gt;

&lt;p&gt;Good problem-solvers slow down before they act. They ask: What exactly is wrong? When did it start? What changed? What is the smallest possible test case?&lt;/p&gt;

&lt;p&gt;I’ve seen developers fix bugs in 10 minutes because they understood the problem properly. I've also been able to do it recently and It was a really nice feeling being able to solve a problem and explain the solution to others&lt;/p&gt;

&lt;h2&gt;
  
  
  Emotional Intelligence
&lt;/h2&gt;

&lt;p&gt;This is the most ignored skill in tech. Code is logical. Teams are not.&lt;br&gt;
You will work with stressed people, rushed deadlines, and conflicting opinions.&lt;/p&gt;

&lt;p&gt;Emotional intelligence is about staying stable in that environment. It means: Not reacting emotionally to feedback. Not blaming others when things break. Understanding when someone is under pressure. &lt;/p&gt;

&lt;p&gt;A calm developer keeps the team stable. A reactive one creates tension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptability and Flexibility
&lt;/h2&gt;

&lt;p&gt;Nothing in tech stays still. Tools change. Requirements change. Even entire systems get replaced. Right now the big thing is AI and has replaced many roles&lt;/p&gt;

&lt;p&gt;Adaptability is simple in idea but hard in practice. It means: You don’t panic when tools change. You don’t cling to one way of doing things.&lt;/p&gt;

&lt;p&gt;You adjust and keep moving. The best developers are not the ones who know the most. They’re the ones who stay up to speed when things shift.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time Management
&lt;/h2&gt;

&lt;p&gt;Deadlines are real. Tasks stack up quickly. Without structure, work becomes chaos. Things can pile up and soon become overwhelming&lt;/p&gt;

&lt;p&gt;Time management is not about working more hours. It’s about deciding what matters first. Some tasks move the product forward. Some only look urgent. A strong developer learns to separate the two. &lt;/p&gt;

&lt;p&gt;They plan their day, break work into smaller parts, and finish what actually matters instead of what feels busy. This allows one to accomplish more in one day, than stay stuck on one thing and end up behind in other things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why These Skills Matter
&lt;/h2&gt;

&lt;p&gt;Technical skills get you in the door. Silent skills decide how far you go. &lt;br&gt;
You can write perfect code and still struggle in a team if communication is weak.&lt;/p&gt;

&lt;p&gt;You can know many frameworks and still miss deadlines if time management is poor. &lt;/p&gt;

&lt;p&gt;You can solve complex problems alone and still fail in a team if collaboration is missing.&lt;/p&gt;

&lt;p&gt;These skills shape how people experience working with you. And in most companies, that matters more than people expect.&lt;/p&gt;

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

&lt;p&gt;Silent skills are not optional extras. They are part of the job. &lt;br&gt;
They decide how well you work with others, how you handle pressure, and how you grow over time.&lt;/p&gt;

&lt;p&gt;Code solves technical problems. Silent skills solve everything around the code.&lt;/p&gt;

&lt;p&gt;Start paying attention to them early. They will stay useful long after specific tools become outdated.&lt;/p&gt;

</description>
      <category>developers</category>
    </item>
    <item>
      <title>Git Licenses</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 15:39:53 +0000</pubDate>
      <link>https://dev.to/fcharles/git-licenses-3e28</link>
      <guid>https://dev.to/fcharles/git-licenses-3e28</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FRKdKyRf%2F1ffc78d7-c39f-44f0-b007-0820e43bdc3f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FRKdKyRf%2F1ffc78d7-c39f-44f0-b007-0820e43bdc3f.jpg" alt="1ffc78d7 c39f 44f0 b007 0820e43bdc3f" width="800" height="640"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.magnific.com/free-vector/certificate-graduation-frame_189982726.htm" rel="noopener noreferrer"&gt;Image by djvstock on Magnific&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you upload a project to GitHub, do you ever stop to think that your project can be used elsewhere? The code is online. People can see it. People can fork it. So naturally, they can use it too... right? Not exactly.&lt;/p&gt;

&lt;p&gt;The thing is, without a license, your code is still protected by default copyright laws. Other developers can look at it, but legally they can't just copy it, modify it, or redistribute it.&lt;/p&gt;

&lt;p&gt;Let's try to understand why licenses exist. Let's talk about what they are and why every developer should know about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a License?
&lt;/h2&gt;

&lt;p&gt;A license is a legal document that tells other people what they are allowed to do with your code.&lt;/p&gt;

&lt;p&gt;It answers questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can someone modify your code?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can they use it in a commercial product?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do they need to open-source their changes?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can they redistribute it?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without a license, those questions don't have clear answers. Adding a license removes the guesswork and gives everyone a clear set of rules to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Licenses Matter
&lt;/h2&gt;

&lt;p&gt;Many developers focus on writing code and forget about the legal side of software. The problem is that other developers often won't use a project if the licensing situation isn't clear.&lt;/p&gt;

&lt;p&gt;Imagine finding an amazing open-source project that solves a problem you've been struggling with.&lt;/p&gt;

&lt;p&gt;At that point, many developers will simply move on because they don't know what they're legally allowed to do with the code.&lt;/p&gt;

&lt;p&gt;Most open-source licenses include liability clauses that prevent people from holding you responsible if something goes wrong while using your software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Types of Licenses
&lt;/h2&gt;

&lt;p&gt;When I first looked at licenses, the number of options felt overwhelming. Fortunately, most projects fall into a few common categories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive Licenses
&lt;/h3&gt;

&lt;p&gt;Licenses like MIT and Apache 2.0 are very flexible. They allow people to use, modify, distribute, and even sell software built from your code.&lt;br&gt;
In most cases, they simply require users to keep the original copyright notice and license information. The MIT License is one of the most popular choices on GitHub because it's simple and easy to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyleft Licenses
&lt;/h3&gt;

&lt;p&gt;Licenses such as GPL and AGPL take a different approach. They allow people to use and modify your code, but there's a condition. If someone distributes software based on your project, they must also make their source code available under the same license. This helps ensure that improvements remain open-source.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proprietary Licenses
&lt;/h3&gt;

&lt;p&gt;Sometimes you don't want people modifying or distributing your software. In that case, a proprietary license keeps all rights in your hands. Others must receive explicit permission before they can use, copy, or distribute the software. Most commercial software follow this model.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Add a License
&lt;/h2&gt;

&lt;p&gt;Adding a license to a GitHub repository is surprisingly easy. &lt;br&gt;
Create a file named &lt;code&gt;LICENSE&lt;/code&gt; in the root of your project.&lt;br&gt;
GitHub can generate license templates for you, making the process even simpler.&lt;br&gt;
Choose the license that matches your goals, review the text, and commit the file.&lt;br&gt;
Your repository now has clear legal terms attached to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which License Should You Choose?
&lt;/h2&gt;

&lt;p&gt;This is usually the first question people ask. The answer depends on what you want to achieve. If your goal is maximum adoption and you don't mind commercial use, MIT is often a good choice. If you want similar flexibility but also want patent protections, Apache 2.0 is worth considering.&lt;/p&gt;

&lt;p&gt;If you want improvements to remain open-source, GPLv3 may be a better fit. &lt;/p&gt;

&lt;p&gt;If you're building software that could be offered as a hosted service and you want modifications shared publicly, AGPLv3 provides stronger protections.&lt;/p&gt;

&lt;p&gt;And if you truly don't care what happens to the code, options like Unlicense or CC0 place it as close to the public domain as possible.&lt;/p&gt;

&lt;p&gt;There isn't a universally correct answer. The best license is the one that aligns with your goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens Without a License?
&lt;/h2&gt;

&lt;p&gt;Many new developers assume that no license means complete freedom. The reality is the opposite. Without a license, your code is protected by default copyright law.&lt;/p&gt;

&lt;p&gt;That means other developers have very limited legal rights to use it. As a result, people may avoid your project entirely.&lt;/p&gt;

&lt;p&gt;You also lose the opportunity to clearly define how others should interact with your work. A missing license creates uncertainty, and uncertainty tends to push contributors away.&lt;/p&gt;

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

&lt;p&gt;A license might seem like a small detail compared to writing features and fixing bugs. I used to think the same thing. The more I looked at open-source projects, the more I realized that a license is one of the most important files in a repository.&lt;/p&gt;

&lt;p&gt;It tells people how they can use your work, protects you from unnecessary liability, and creates a clear framework for collaboration.&lt;br&gt;
Before pushing your next project to GitHub, take a few minutes to choose a license.&lt;/p&gt;

</description>
      <category>git</category>
      <category>opensource</category>
      <category>developer</category>
    </item>
    <item>
      <title>Git Commit Messages</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 13:29:19 +0000</pubDate>
      <link>https://dev.to/fcharles/git-commit-messages-5f18</link>
      <guid>https://dev.to/fcharles/git-commit-messages-5f18</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2Fspc8Vv1j%2Fcommits.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2Fspc8Vv1j%2Fcommits.png" alt="commits" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A well-written commit message is one of the most underrated skills in software development. It turns a chaotic git history into a readable, searchable record of every decision you have ever made. This will guide in writing structured.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Understand the Standard Structure
&lt;/h2&gt;

&lt;p&gt;The industry standard is the &lt;strong&gt;Conventional Commits specification&lt;/strong&gt;, paired with the &lt;strong&gt;50/72 length rule&lt;/strong&gt;. Together they make your history easy to read for humans and easy to parse for automated tools.&lt;/p&gt;

&lt;p&gt;A complete commit message follows this template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;(&amp;lt;optional scope&amp;gt;): &amp;lt;short description in imperative mood&amp;gt;

[optional body — explains the what and why behind the change]

[optional footer — references issue trackers or declares breaking changes]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a real example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): add multi-factor authentication check

Introduce an intermediate step in the login pipeline to check for a
valid TOTP token. This protects user accounts against credential stuffing.

Closes JIRA-8422

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Know the Parts of a Commit Message
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Type&lt;/strong&gt; A lowercase prefix that categorizes the nature of your change (e.g., &lt;code&gt;feat&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;docs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope&lt;/strong&gt; &lt;em&gt;(optional)&lt;/em&gt; A modifier in parentheses that gives context on which part of the codebase is affected (e.g., &lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;api&lt;/code&gt;, &lt;code&gt;ui&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt; A short summary of what the commit accomplishes — written as a command, not a past-tense statement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Body&lt;/strong&gt; &lt;em&gt;(optional)&lt;/em&gt; Extended paragraphs explaining the problem being solved and the motivation behind your fix. Focus on &lt;em&gt;why&lt;/em&gt;, not &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Footer&lt;/strong&gt; &lt;em&gt;(optional)&lt;/em&gt; Metadata used to reference issue IDs (e.g., &lt;code&gt;Closes JIRA-8422&lt;/code&gt;) or declare breaking changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Learn the Core Formatting Rules
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For the subject line
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Keep it under 50 characters&lt;/strong&gt; for optimal display in GitHub and terminal interfaces.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use the imperative mood&lt;/strong&gt; — write it as a command (use &lt;code&gt;add&lt;/code&gt; not &lt;code&gt;added&lt;/code&gt; or &lt;code&gt;adding&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Drop the trailing period&lt;/strong&gt; — never end your subject line with a full stop.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Keep the type lowercase&lt;/strong&gt; — &lt;code&gt;feat:&lt;/code&gt; not &lt;code&gt;Feat:&lt;/code&gt; or &lt;code&gt;FEAT:&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For the body
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Leave one blank line&lt;/strong&gt; between the subject and the body.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Wrap lines at 72 characters&lt;/strong&gt; to avoid truncation in terminal windows.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Explain why, not how&lt;/strong&gt; — the code shows how; the message should explain why the old state was a problem.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 4: Learn the Standard Commit Types
&lt;/h2&gt;

&lt;p&gt;You don't need to memorize all of these on day one, but this is the full reference:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Introduces a brand-new feature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Corrects a bug or unintended behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;refactor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Restructures code without changing its behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Routine maintenance, config tweaks, or package updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Changes made exclusively to documentation or markdown files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Formatting or whitespace adjustments that leave logic unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Adding missing tests or repairing broken test suites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;perf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Performance optimizations designed to increase speed or efficiency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Step 5: Start Small — Master Three Types First
&lt;/h2&gt;

&lt;p&gt;Don't try to memorize all eight types immediately. For your first few weeks, use only these three:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;feat:&lt;/code&gt; — when you add something new (e.g., &lt;code&gt;feat: add submit button&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;fix:&lt;/code&gt; — when you repair something broken (e.g., &lt;code&gt;fix: correct broken nav link&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;docs:&lt;/code&gt; — when you write or update documentation (e.g., &lt;code&gt;docs: update setup guide&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these feel automatic, layer in the others one at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Use the Imperative Mood Test
&lt;/h2&gt;

&lt;p&gt;Write your subject line so it logically completes this sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If applied, this commit will &lt;strong&gt;[your message]&lt;/strong&gt;."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  Correct: &lt;code&gt;feat: add login page&lt;/code&gt; → "If applied, this commit will &lt;em&gt;add login page&lt;/em&gt;."&lt;/li&gt;
&lt;li&gt;  Incorrect: &lt;code&gt;feat: added login page&lt;/code&gt; or &lt;code&gt;feat: adding login page&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it doesn't complete that sentence naturally, rewrite it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Commit Small and Often
&lt;/h2&gt;

&lt;p&gt;The hardest habit for beginners to build is committing frequently. The rule is simple: &lt;strong&gt;make one commit for every one completed task.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Don't write code for three hours and then commit &lt;code&gt;fix: everything&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Do commit every time you finish a single small task — one component, one bug fix, one style correction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small commits are easier to review, easier to revert, and tell a much clearer story to your team.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Automate the Rules With Commitizen
&lt;/h2&gt;

&lt;p&gt;Once you want to enforce the format consistently, use &lt;strong&gt;Commitizen&lt;/strong&gt; — a command-line tool that guides you through writing a conventional commit with interactive prompts. You can run it immediately with &lt;code&gt;npx&lt;/code&gt; without any complex setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx commitizen init cz-conventional-changelog &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From then on, instead of writing &lt;code&gt;git commit -m "..."&lt;/code&gt;, run &lt;code&gt;git cz&lt;/code&gt; and answer the prompts. The tool assembles the correctly formatted message for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Build the Habit Now
&lt;/h2&gt;

&lt;p&gt;Mastering commit messages is about transitioning from a messy, hard-to-read history to a structured, predictable one that your whole team can rely on.&lt;/p&gt;

&lt;p&gt;Three things to take away:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Consistency trumps perfection.&lt;/strong&gt; It matters less which exact types you use and more that you and your team use the same format every single time.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Keep it short and purposeful.&lt;/strong&gt; Under 50 characters for the title, imperative mood, and use the body to explain the &lt;em&gt;why&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Start small, then automate.&lt;/strong&gt; Begin with just &lt;code&gt;feat&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, and &lt;code&gt;docs&lt;/code&gt;. Commit frequently. Then bring in Commitizen to handle the formatting automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best time to start writing better commit messages is on your very next commit.&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Testing Discipline: A Beginner's Guide</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 12:45:22 +0000</pubDate>
      <link>https://dev.to/fcharles/testing-discipline-a-beginners-guide-5ckb</link>
      <guid>https://dev.to/fcharles/testing-discipline-a-beginners-guide-5ckb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FC3SKPhyM%2F18824957.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FC3SKPhyM%2F18824957.jpg" alt="18824957" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.magnific.com/free-vector/code-testing-cartoon-banner-functional-test-methodology-programming-search-errors-bugs-website-platform-development-dashboard-usability-optimization-computer-pc-vector-illustration_10487786.htm" rel="noopener noreferrer"&gt;Image by upklyak on Magnific&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Run an application. Click a few buttons. If the terminal doesn't have errors, then everything is working. Right?&lt;/p&gt;

&lt;p&gt;What's the point of writing tests if all seems to be fine. Let's explore testing discipline and why it's a habit every developer should build early.&lt;/p&gt;


&lt;h2&gt;
  
  
  What is Testing Discipline?
&lt;/h2&gt;

&lt;p&gt;Testing discipline is the habit of verifying that your code works. It's not something you do at the end of a project. &lt;br&gt;
It's something you build into your development process.&lt;/p&gt;

&lt;p&gt;The goal is simple. Catch bugs as early as possible. A bug found while writing code usually takes minutes to fix.&lt;/p&gt;

&lt;p&gt;The same bug found in production can take hours to investigate, reproduce, and resolve.&lt;/p&gt;

&lt;p&gt;The earlier you find problems, the less expensive they become.&lt;/p&gt;


&lt;h2&gt;
  
  
  Different Types of Tests
&lt;/h2&gt;

&lt;p&gt;When people talk about testing, they're usually referring to three categories.&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;unit testing&lt;/strong&gt;.  A unit test checks a single piece of functionality, usually a function or method. These tests are fast and easy to write, making them the best place for beginners to start.&lt;/p&gt;

&lt;p&gt;Next are &lt;strong&gt;integration tests&lt;/strong&gt;.  These verify that different parts of your application work together correctly. For example, does your service communicate properly with the database?&lt;/p&gt;

&lt;p&gt;Finally, there are &lt;strong&gt;end-to-end tests&lt;/strong&gt;.  These simulate a real user interacting with the application from start to finish. They provide the most realistic results but are usually slower and more complex.&lt;/p&gt;

&lt;p&gt;As a beginner, I recommend that you should focus on unit tests first. &lt;/p&gt;


&lt;h2&gt;
  
  
  Different Testing Approaches
&lt;/h2&gt;

&lt;p&gt;As you continue learning, you'll come across different testing methodologies.&lt;/p&gt;

&lt;p&gt;One of the most popular is &lt;strong&gt;Test-Driven Development&lt;/strong&gt;, often called TDD.&lt;/p&gt;

&lt;p&gt;The idea is simple. Write the test first. Watch it fail. Write enough code to make it pass.&lt;/p&gt;

&lt;p&gt;Many developers like this approach because it forces them to think about requirements before writing implementation details.&lt;/p&gt;

&lt;p&gt;You may also hear about &lt;strong&gt;Behaviour-Driven Development&lt;/strong&gt;, or BDD.&lt;/p&gt;

&lt;p&gt;This approach focuses on describing behaviour in a way that both technical and non-technical people can understand.&lt;/p&gt;

&lt;p&gt;Then there is &lt;strong&gt;static testing&lt;/strong&gt; and &lt;strong&gt;dynamic testing&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Static testing involves reviewing code without running it. Code reviews and linters fall into this category.&lt;/p&gt;

&lt;p&gt;Dynamic testing involves running the application and verifying its behaviour.&lt;/p&gt;

&lt;p&gt;Both have their place in a healthy development process.&lt;/p&gt;


&lt;h2&gt;
  
  
  Writing Tests in Go
&lt;/h2&gt;

&lt;p&gt;One thing I like about Go is that testing support is already built into the language. You don't need to install any package just to write your first test.&lt;/p&gt;

&lt;p&gt;There are a few rules to remember.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test files must end with &lt;code&gt;_test.go&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Test functions must begin with &lt;code&gt;Test&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;They must also accept a &lt;code&gt;*testing.T&lt;/code&gt; parameter.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example:&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;TestCalculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// test logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you follow those rules, Go automatically recognizes your tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Example
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;You have a function that calculates discounts based on order value.&lt;/p&gt;

&lt;p&gt;Your code works for normal orders, but what happens if someone enters a negative amount?&lt;br&gt;
What happens at the discount threshold?&lt;br&gt;
What happens for large purchases?&lt;/p&gt;

&lt;p&gt;These are the kinds of questions tests help answer.&lt;/p&gt;

&lt;p&gt;A common pattern in Go is called &lt;strong&gt;table-driven testing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of writing separate tests for every scenario, you place inputs and expected outputs into a table and loop through them.&lt;/p&gt;

&lt;p&gt;This allows you to test multiple situations without repeating large amounts of code.&lt;/p&gt;

&lt;p&gt;It's one of the most common testing patterns you'll see in Go projects.&lt;/p&gt;


&lt;h2&gt;
  
  
  Running Tests
&lt;/h2&gt;

&lt;p&gt;Once you've written a test, running it is simple.&lt;/p&gt;

&lt;p&gt;To run all tests:&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see detailed output:&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;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check test coverage:&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;-cover&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're starting out, &lt;code&gt;go test -v&lt;/code&gt; is usually the most helpful because it shows exactly which tests passed and which failed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making Testing Part of Your Workflow
&lt;/h2&gt;

&lt;p&gt;Writing a few tests is useful. Whenever you add a feature, write tests for it.&lt;br&gt;
Whenever you fix a bug, consider adding a test that prevents the same bug from returning.&lt;/p&gt;

&lt;p&gt;Over time, your test suite becomes a safety net.&lt;br&gt;
You can refactor code, improve performance, and add features with much more confidence because the tests will alert you if something breaks.&lt;/p&gt;

&lt;p&gt;This becomes even more important when using CI/CD pipelines.&lt;br&gt;
Tests can run automatically whenever code is pushed, helping catch issues before they reach production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Testing Matters
&lt;/h2&gt;

&lt;p&gt;I know testing can feel slow at first.&lt;br&gt;
When you're excited about building features, writing tests can seem like extra work.&lt;/p&gt;

&lt;p&gt;But after spending hours debugging issues that a simple test could have caught in seconds, my perspective changed.&lt;/p&gt;

&lt;p&gt;Tests give you confidence. &lt;br&gt;
They make refactoring safer.&lt;br&gt;
They help identify bugs quickly.&lt;br&gt;
They also act as documentation by showing exactly how a function is expected to behave.&lt;br&gt;
Most importantly, they help you deliver software that actually works.&lt;/p&gt;




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

&lt;p&gt;Many beginners see testing as something they'll learn later.&lt;br&gt;
The truth is that testing is one of the habits that helps you grow from a beginner into a reliable developer.&lt;br&gt;
You don't need to test everything immediately.&lt;/p&gt;

&lt;p&gt;Pick a function you've already written and create a few test cases for it.&lt;br&gt;
Test the normal case.&lt;br&gt;
Test an edge case.&lt;br&gt;
Test an error case.&lt;br&gt;
Run the tests and see what happens.&lt;/p&gt;

&lt;p&gt;The more often you do this, the more confidence you'll have in your code and the less time you'll spend chasing bugs in production.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>code</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Working in Branches</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 12:12:56 +0000</pubDate>
      <link>https://dev.to/fcharles/working-in-branches-3h44</link>
      <guid>https://dev.to/fcharles/working-in-branches-3h44</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FHL9M8ZJx%2Fgit-branches.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FHL9M8ZJx%2Fgit-branches.jpg" alt="git branches" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I first started using Git, I did everything on the &lt;code&gt;main&lt;/code&gt; branch. It seemed easier. I would make changes, commit them, push them, and move on. For solo projects, it didn't seem like a problem.&lt;/p&gt;

&lt;p&gt;I failed my first ever interview. I had the first round which was good, then moved on to the second round which was a home assignment. I was tasked to create a simple Django English-Swahili translator. It was simple enough. I created it, and submitted. To me I felt like I had passed.&lt;/p&gt;

&lt;p&gt;I sought feedback as to why I failed. There were a bunch of reasons but one of them was that I only worked on the &lt;code&gt;main&lt;/code&gt; branch. &lt;/p&gt;

&lt;p&gt;From that experience, I decided to start working in branches for every significant and sometimes non-significant task.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Branches?
&lt;/h2&gt;

&lt;p&gt;A branch is an isolated version of your codebase. It allows you to work on a feature, bug fix, or experiment without affecting the main code that everyone relies on.&lt;/p&gt;

&lt;p&gt;Think about building a login page. Instead of changing the main branch directly, you create a separate branch and do all your work there. If something breaks, only the branch is affected. The main branch remains safe.&lt;/p&gt;

&lt;p&gt;Once the feature is complete and tested, you merge it back into the main branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Typical Branch Workflow
&lt;/h2&gt;

&lt;p&gt;Most development work follows a simple process.&lt;/p&gt;

&lt;p&gt;First, make sure your local repository is up to date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
git pull

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures you're working from the latest version of the project.&lt;/p&gt;

&lt;p&gt;Next, create a branch for your task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature-login-page

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're working in your own isolated environment.&lt;/p&gt;

&lt;p&gt;Make your changes, then check what has been modified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're ready, stage and commit your work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add login page"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The branch still exists only on your machine at this point.&lt;/p&gt;

&lt;p&gt;To publish it to GitHub, push it to the remote repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin feature-login-page

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the branch is online, you can open a Pull Request.&lt;/p&gt;

&lt;p&gt;A Pull Request allows other developers to review your work before it becomes part of the main codebase.&lt;/p&gt;

&lt;p&gt;After approval, the branch can be merged into &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Branches?
&lt;/h2&gt;

&lt;p&gt;At first, branches can feel like extra work. Creating them, switching between them, and opening Pull Requests adds a few more steps to your workflow.&lt;/p&gt;

&lt;p&gt;The benefits outweigh that small effort. The biggest advantage is &lt;strong&gt;safety&lt;/strong&gt;. If a feature breaks, the main branch remains untouched.&lt;/p&gt;

&lt;p&gt;Users continue using a stable version of the application while you fix the issue. Branches also make teamwork much easier.&lt;/p&gt;

&lt;p&gt;Imagine three developers working on different features at the same time. Without branches, everyone would constantly overwrite each other's changes.&lt;/p&gt;

&lt;p&gt;With branches, each person can work independently and merge their work when it's ready.&lt;/p&gt;

&lt;p&gt;Another benefit is &lt;strong&gt;cleaner code reviews&lt;/strong&gt;. Instead of reviewing weeks of mixed changes, reviewers can focus on one feature or bug fix at a time. That makes mistakes easier to spot and feedback easier to give.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branches and CI/CD
&lt;/h2&gt;

&lt;p&gt;If you're using a CI/CD pipeline, branches become even more useful. Whenever code is pushed to a branch, automated tests can run before the code reaches production.&lt;/p&gt;

&lt;p&gt;This helps catch problems early.Finding those issues before deployment saves a lot of headaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Commands
&lt;/h2&gt;

&lt;p&gt;As you work with branches, a few commands become part of your daily routine.&lt;/p&gt;

&lt;p&gt;List local branches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List local and remote branches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switch to an existing branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout branch-name

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temporarily save uncommitted work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete a local branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-d&lt;/span&gt; branch-name

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to memorize every Git command. These few commands are enough to handle most day-to-day branch management.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens Without Branches?
&lt;/h2&gt;

&lt;p&gt;Many beginners skip branching because they work alone. The problem appears when projects start growing.&lt;br&gt;
A single mistake on the main branch can introduce bugs into working features.&lt;/p&gt;

&lt;p&gt;Testing becomes harder because unfinished work gets mixed with stable code.&lt;br&gt;
Eventually, you're afraid to make changes because every update feels risky.&lt;/p&gt;

&lt;p&gt;Branches solve that problem by creating a safe space for development.&lt;br&gt;
You can experiment, test ideas, and fix bugs without putting the primary codebase at risk.&lt;/p&gt;

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

&lt;p&gt;Working in branches is one of the habits that separates small projects from professional development workflows.&lt;/p&gt;

&lt;p&gt;It keeps your main branch stable, makes collaboration easier, and gives you the freedom to experiment without fear of breaking existing functionality.&lt;/p&gt;

&lt;p&gt;If you're still making all your changes directly on &lt;code&gt;main&lt;/code&gt;, try creating a branch for your next feature. Make it a habit. It will boost your productivity and make you more confident in exploring what your projects can do without fear of failure.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>productivity</category>
      <category>coding</category>
    </item>
    <item>
      <title>Proper Variable Naming</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 11:09:07 +0000</pubDate>
      <link>https://dev.to/fcharles/proper-variable-naming-27h</link>
      <guid>https://dev.to/fcharles/proper-variable-naming-27h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FyFhQrgT5%2Fvariable-naming.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FyFhQrgT5%2Fvariable-naming.png" alt="variable naming" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I started programming, naming variables was the last thing on my mind. I would use the variables given in YouTube tutorials, that was enough for me.&lt;/p&gt;

&lt;p&gt;I would use names like &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;temp&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;num&lt;/code&gt;, etc. The code ran, so I didn't see the problem.&lt;/p&gt;

&lt;p&gt;I would come back to the same project later and spend several minutes trying to remember what those variables actually stored.&lt;/p&gt;

&lt;p&gt;That's when I realized variable names are not for the computer. They're for the people reading the code. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Variable Naming Matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A variable is a named storage location&lt;/strong&gt; in a computer's memory that holds data or values which can change during program execution. To a computer there is no difference when you name a variable &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;total_price&lt;/code&gt;. To the compiler, both are just labels pointing to data.&lt;/p&gt;

&lt;p&gt;The opposite is true for Humans. Imagine opening a project you worked on six months ago and finding something like this:&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;if&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;withdraw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What are &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt;, and &lt;code&gt;a&lt;/code&gt;? Without context, it's difficult to tell.&lt;/p&gt;

&lt;p&gt;Now compare that to:&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;if&lt;/span&gt; &lt;span class="n"&gt;account_balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withdrawal_amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;is_withdrawable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second example tells a story. You immediately understand what the code is trying to do.&lt;/p&gt;

&lt;p&gt;Good variable names improve readability, reduces confusion, and makes maintenance much easier. They also help when debugging.&lt;/p&gt;

&lt;p&gt;When an error appears, it's much easier to trace a problem through variables named &lt;code&gt;user_id&lt;/code&gt;, &lt;code&gt;total_price&lt;/code&gt;, or &lt;code&gt;transaction_date&lt;/code&gt; than through variables named &lt;code&gt;id&lt;/code&gt;,   &lt;code&gt;price&lt;/code&gt;, and &lt;code&gt;date&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This becomes even more important when working with other developers. A clear variable name can save several minutes of explanation every time someone reads your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Naming Mistakes
&lt;/h2&gt;

&lt;p&gt;One mistake many beginners make is choosing names that are too short.&lt;/p&gt;

&lt;p&gt;For example:&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;tp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1500&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does &lt;code&gt;tp&lt;/code&gt; mean?&lt;/p&gt;

&lt;p&gt;It could mean total price, transaction processed, temporary product, or something else entirely.&lt;/p&gt;

&lt;p&gt;A more descriptive name removes the guesswork:&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;total_price&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1500&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another common mistake is leaving out important context.&lt;br&gt;
Imagine you have a timeout value:&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;timeout&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thirty what? Seconds? Minutes? Hours? &lt;br&gt;
Adding the unit makes the meaning clear:&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;timeout_seconds&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small details like this prevent mistakes that can be surprisingly difficult to track down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming Boolean Variables
&lt;/h2&gt;

&lt;p&gt;Boolean values deserve special attention.&lt;/p&gt;

&lt;p&gt;Since they can only be true or false, it's usually best to name them like questions.&lt;/p&gt;

&lt;p&gt;For example:&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;is_logged_in&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;has_permission&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When these variables are used in conditions, the code becomes easy to read:&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;if&lt;/span&gt; &lt;span class="n"&gt;is_logged_in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// continue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The statement almost reads like plain English.&lt;br&gt;
Compare that to:&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;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// continue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does status mean? You have to inspect more code before you understand it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency Matters
&lt;/h2&gt;

&lt;p&gt;One thing that's often overlooked is consistency.&lt;/p&gt;

&lt;p&gt;Most programming languages and teams have naming conventions.&lt;/p&gt;

&lt;p&gt;Some use camelCase:&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;userAge&lt;/span&gt;
&lt;span class="n"&gt;totalPrice&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Others prefer snake_case:&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;user_age&lt;/span&gt;
&lt;span class="n"&gt;total_price&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The choice matters less than being consistent. &lt;br&gt;
Mixing different styles throughout a project makes the code look messy and harder to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple Rule
&lt;/h2&gt;

&lt;p&gt;When naming a variable, ask yourself: "If someone else reads this six months from now, will they immediately understand what it contains?"&lt;/p&gt;

&lt;p&gt;If the answer is no, choose a better name. You don't need extremely long variable names. You simply need names that clearly communicate the purpose.&lt;/p&gt;

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

&lt;p&gt;Proper variable naming seems like a small detail when you're focused on building features. The longer I spent working on projects, the more I realized that poorly named variables create confusion, slow down debugging, and make maintenance harder than it needs to be.&lt;/p&gt;

&lt;p&gt;Good names make your code easier to read, easier to understand, and easier to work with. The next time you're creating a variable, spend a few extra seconds choosing a meaningful name.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>coding</category>
    </item>
    <item>
      <title>UI/UX in Design</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Mon, 01 Jun 2026 10:37:29 +0000</pubDate>
      <link>https://dev.to/fcharles/uiux-in-design-2273</link>
      <guid>https://dev.to/fcharles/uiux-in-design-2273</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FDHwkFDdC%2F16683353-5757453.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FDHwkFDdC%2F16683353-5757453.jpg" alt="16683353 5757453" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.magnific.com/free-vector/gradient-ui-ux-background_16683353.htm" rel="noopener noreferrer"&gt;Image by freepik&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Design is not just what it looks like and feels like. Design is how it works."&lt;/p&gt;

&lt;p&gt;— Steve Jobs, Co-founder of Apple&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I started building projects, my process was simple. Open VS code, create a database, build features, then figure out the interface later.&lt;/p&gt;

&lt;p&gt;It worked. At least that's what I thought.&lt;/p&gt;

&lt;p&gt;The problem came when I wanted to add new features or change existing ones. It happened when I was creating a personal finance tool. I created a simple database, and the backend was solid, but I only thought of the core features, not the full scope. So I kept adding features and complicating my workflow.&lt;/p&gt;

&lt;p&gt;That's when I realized I had skipped an important step: planning the experience before writing the code.&lt;/p&gt;

&lt;p&gt;Let's talk about UI/UX and why it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is UI/UX?
&lt;/h2&gt;

&lt;p&gt;UI/UX stands for User Interface and User Experience.&lt;/p&gt;

&lt;p&gt;User Experience (UX) focuses on how a product works. It answers questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What problem are we solving?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What does the user want to achieve?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What steps will they take?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;User Interface (UI) focuses on how the product looks. This includes layouts, colors, typography, buttons, and other visual elements.&lt;/p&gt;

&lt;p&gt;A simple way to think about it is this:&lt;/p&gt;

&lt;p&gt;UX makes up the structure.&lt;/p&gt;

&lt;p&gt;UI makes up the appearance.&lt;/p&gt;

&lt;p&gt;Both work together to create a product that is useful and easy to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why UI/UX Matters
&lt;/h2&gt;

&lt;p&gt;Many developers jump straight into coding. After all, writing code feels like progress.&lt;/p&gt;

&lt;p&gt;The issue is that code is expensive to change once a project grows.&lt;/p&gt;

&lt;p&gt;Imagine spending weeks building a feature only to realize users cannot find it or do not understand how it works. Now you have to revisit your database, backend logic, frontend pages, and tests.&lt;/p&gt;

&lt;p&gt;A simple wireframe could have exposed that problem in minutes.&lt;/p&gt;

&lt;p&gt;Good UI/UX helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Find usability problems before development begins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build features users actually need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce development time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a clear roadmap for the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose technologies based on requirements instead of assumptions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Initial Design Process
&lt;/h2&gt;

&lt;p&gt;When planning a product, there are several stages that help turn an idea into something usable.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Discovery and Research
&lt;/h3&gt;

&lt;p&gt;Before designing anything, you need to understand the problem.&lt;/p&gt;

&lt;p&gt;Who are the users?&lt;/p&gt;

&lt;p&gt;What challenges do they face?&lt;/p&gt;

&lt;p&gt;How are competitors solving the same issue?&lt;/p&gt;

&lt;p&gt;This stage helps prevent building solutions nobody will use.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. User Flows
&lt;/h3&gt;

&lt;p&gt;Once you understand the problem, map out how users will interact with the product.&lt;/p&gt;

&lt;p&gt;For example, if someone wants to create an account, what happens first?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open website&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click sign up&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access dashboard&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seeing the entire journey helps identify unnecessary steps early.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Wireframing
&lt;/h3&gt;

&lt;p&gt;A wireframe shows individual screens.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F93nLJq9k%2Fwireframe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F93nLJq9k%2Fwireframe.jpg" alt="wireframe" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wireframes focus on structure rather than appearance. They answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Where should navigation go?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Where should important information appear?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What actions should be most visible?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools like Figma and Miro are commonly used for this stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Interactive Prototyping
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fr115idoc%2Fproduction%2Fd4f83f22f0004bf581e6b40e9b86cc9c8d7ded55-1536x1024.png%3Fw%3D640%26q%3D80%26fit%3Dclip%26auto%3Dformat" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fr115idoc%2Fproduction%2Fd4f83f22f0004bf581e6b40e9b86cc9c8d7ded55-1536x1024.png%3Fw%3D640%26q%3D80%26fit%3Dclip%26auto%3Dformat" width="640" height="427"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://clay.global/blog/ux-guide/prototyping" rel="noopener noreferrer"&gt;Image from clay.global/blog/ux-guide/prototyping&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A prototype shows how those screens creating in wireframing are connected.&lt;/p&gt;

&lt;p&gt;Users can click through the design and simulate real interactions before any code is written.&lt;/p&gt;

&lt;p&gt;This makes testing ideas much faster and cheaper.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Visual Design and Handoff
&lt;/h3&gt;

&lt;p&gt;After validating the structure, visual elements are added.&lt;/p&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Colors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Typography&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Icons&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Buttons&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spacing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Developers Should Learn UI/UX
&lt;/h2&gt;

&lt;p&gt;You do not need to become a professional designer. But understanding UI/UX makes you a better developer.&lt;/p&gt;

&lt;p&gt;I've made projects with excellent code but poor usability. Technically they worked, but users struggled to achieve basic tasks.&lt;/p&gt;

&lt;p&gt;Learning design helps you think from the user's perspective rather than the system's perspective.&lt;/p&gt;

&lt;p&gt;Some benefits include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Higher Demand
&lt;/h3&gt;

&lt;p&gt;Companies want products that people enjoy using. Developers who understand users bring additional value to a team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Less Rework
&lt;/h3&gt;

&lt;p&gt;A few hours spent designing can save days of rewriting code later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stronger Portfolio Projects
&lt;/h3&gt;

&lt;p&gt;Employers are often interested in how you think, not just what you build.&lt;/p&gt;

&lt;p&gt;Showing research, wireframes, and user flows demonstrates problem-solving ability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful Across Industries
&lt;/h3&gt;

&lt;p&gt;Design thinking applies to technology, business, marketing, and product development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy to Start
&lt;/h3&gt;

&lt;p&gt;You can begin learning UI/UX without writing a single line of code.&lt;/p&gt;

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

&lt;p&gt;I used to think that design is only meant for the designers and front end developers. Now I'm not an expert because I only recently leant this, but I realized that planning before coding saves a lot of time and frustration.&lt;/p&gt;

&lt;p&gt;A good design helps you understand the problem, organize your ideas, and create products people can actually use. It also allows one to view the scope of what's possible and what's not. &lt;br&gt;
Before starting your next project, try spending some time on research, user flows, and wireframes first.&lt;/p&gt;

&lt;p&gt;You might be surprised by how much simpler your work will be even before writing your first line of code.&lt;/p&gt;

</description>
      <category>ux</category>
      <category>ui</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why you should Deploy early and often</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Fri, 29 May 2026 14:15:19 +0000</pubDate>
      <link>https://dev.to/fcharles/why-you-should-deploy-early-and-often-27ie</link>
      <guid>https://dev.to/fcharles/why-you-should-deploy-early-and-often-27ie</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FCGDTJS8%2F7090038.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FCGDTJS8%2F7090038.jpg" alt="7090038" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.magnific.com/free-vector/hand-drawn-flat-design-api-illustration_25632103.htm" rel="noopener noreferrer"&gt;Image by freepik&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a project and ensure it has all the features first then and only then can I deploy it. That's something most of us have done, right? Though you may have not thought or said the same thing word for word, but it's something that just happens sub-consciencely. Basically like habit and it does not seem to have any issues. So why would you change your current normal balance to now start deploying work that's incomplete? Let's explore this question together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy early and often
&lt;/h2&gt;

&lt;p&gt;This is a software development philosophy that prioritizes frequent, smaller releases over long, feature-heavy development cycles. This approach creates a rapid, tight feedback loop with users while eliminating the risk of building software no one actually wants. It's also known as RERO: Release Early, Release Often&lt;/p&gt;

&lt;p&gt;The thing is, your project might work fast and efficiently in your local host environment. Where there is one user, the hardware would be dedicated to that task alone at the time of testing, and no major issues. But when you deploy there's differences in latency, infrastructure and the users. &lt;/p&gt;

&lt;p&gt;I heard from another developer that he once deployed a website and minutes later the site crashed. Reason being, one of the users had sent many requests in a short period of time. Another one's account creation failed because they added an emoji to their user name. &lt;/p&gt;

&lt;p&gt;These are all variables that would not be considered in a local environment. Putting your work out there as you develop it allows you to identify weak points and problems you normally wouldn't experience alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Deploy Early and Often?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;  &lt;strong&gt;Faster Feedback Loops:&lt;/strong&gt; 
Getting a Minimum Viable Product (MVP) to users early ensures customer preferences guide the product, saving hundreds of hours of guesswork. They can also show errors and issues that the product may have that you may not have seen in the planning or creation process&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Easier Debugging:&lt;/strong&gt;
Deploying smaller batches of code makes tracking down and fixing bugs easier, as there are fewer variables and lines of code changed at any given time.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Reduced Release Stress:&lt;/strong&gt; 
Long periods between releases generate pressure, making deployments risky and complicated. Making deployments a normal, frequent occurrence turns them into a routine, and low risk.
When you have many features at hand and want to release them all at once the likely hood of one of them failing silently is high. 
I once deployed a project and there were many silent errors in different parts, but when looking at the code, there were no error indicators anywhere. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Higher Quality:&lt;/strong&gt; 
It shifts the mindset from chasing "full-featured perfection" to continuous improvement and user-defined validation. 
It's better to work step by step and "perfect" features as you go. Since you will be sure of the working features, your attitude towards the project rises as stress reduces since you have the time and effort dedicated to making the next thing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Implement It Effectively
&lt;/h2&gt;

&lt;p&gt;Deploying isn't just one and done. You need to implement and use the proper tools and practices to ensure a smooth development journey. If done right It will allow you to focus on creation and innovation. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; &lt;br&gt;
Use a CI/CD (Continuous Integration/Continuous Deployment) pipeline that automatically builds, tests, and deploys code changes. This makes it so that you always deploy projects that are stable and work according to spec&lt;br&gt;
   &lt;strong&gt;Feature Flags:&lt;/strong&gt;&lt;br&gt;
 Utilize feature flags (toggles) to merge features into the main branch but hide them from users until they are officially ready. This allows continuous deployment without exposing incomplete features. You may have select users as testers. They will ascertain if the features that you have pushed work as intended.&lt;br&gt;
  &lt;strong&gt;Solid Rollback Plans:&lt;/strong&gt; &lt;br&gt;
 When automating deployments, ensure your infrastructure allows you to quickly roll back to the previous stable version if something breaks. This is more frequent than one might realize. You might push a feature to production, then it breaks everything. It's important to note that having versions that are close in terms of times they were developed makes it easier to restore. That's why having updates that are few and far between can really hurt when the rollback happens.&lt;/p&gt;

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

&lt;p&gt;A product that “works but", fails at the critical moment is  of eploy early and often help you frustrating, and most developers have experienced it. That’s why the ideaa bitter experience I'm sure most of us have experienced. But having the concept of "Deploy early and often” matters. It" though long can helps you catch issues sooner, improve reliability, and keep your system ready for real use at any timebuild better and working systems always ready for action. If you haven’t started doing this yet, now is a good time as any. It'll save you a lot of stress and worries in the long run.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>devops</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Beginner steps into CI/CD</title>
      <dc:creator>Favor Charles Owuor</dc:creator>
      <pubDate>Tue, 26 May 2026 09:28:22 +0000</pubDate>
      <link>https://dev.to/fcharles/beginner-steps-into-cicd-55df</link>
      <guid>https://dev.to/fcharles/beginner-steps-into-cicd-55df</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FGwHv0tx%2Fherro.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FGwHv0tx%2Fherro.jpg" alt="herro" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.magnific.com/free-vector/flat-design-technology-devops-illustration_24746653.htm" rel="noopener noreferrer"&gt;Image by freepik&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most people me included, just use Github as kind of like an online store for code. But this application has more to it than meets the eye. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is CI/CD
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FHfQJzj2F%2Fci-cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FHfQJzj2F%2Fci-cd.png" alt="ci cd" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Continuous Integration (CI):&lt;/strong&gt; Is the of automation of the process of merging code changes. It's typically trigged on every &lt;code&gt;push&lt;/code&gt; or &lt;code&gt;pull request&lt;/code&gt;, running automated tests and builds to detect bugs early.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Continuous Deployment/Delivery (CD):&lt;/strong&gt; Automatically prepares or pushes tested code to a production environment once the CI checks pass&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These series of events can help cut down on the time and effort spent on the manual tasks. They can be summarized in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FqFjgjR70%2Fproper-ci-cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FqFjgjR70%2Fproper-ci-cd.png" alt="proper ci cd" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How you can do it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create your workflows
&lt;/h3&gt;

&lt;p&gt;In CI, there's four key concepts one should know i.e. trigger, workflow, job and step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A trigger is what will cause the CI process to start&lt;/li&gt;
&lt;li&gt;Workflow is the automation file(.yml)&lt;/li&gt;
&lt;li&gt;Job is a group of steps on one machine&lt;/li&gt;
&lt;li&gt;Step is a single command or action&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To begin we first create a .github directory. Inside we create a workflows folder. Inside we create out ci.yml file. The structure should look like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FwZZS52BQ%2FScreenshot-2026-05-26-083904.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FwZZS52BQ%2FScreenshot-2026-05-26-083904.png" alt="Screenshot 2026 05 26 083904" width="286" height="196"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Define triggers
&lt;/h3&gt;

&lt;p&gt;For this instance we want the process to start when someone performs a pr but you can set it to push as well&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI Pipeline&lt;/span&gt;

&lt;span class="c1"&gt;# TRIGGERS&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Define Jobs
&lt;/h3&gt;

&lt;p&gt;Jobs work in Isolated Environments. Every job runs inside its own fresh virtual machine (called a runner), such as Ubuntu, Windows, or macOS.&lt;br&gt;
If your workflow has multiple jobs, GitHub runs them at the same time to save time.&lt;br&gt;
 A job groups together a series of sequential tasks (steps) that handle the actual work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# JOBS&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt; &lt;span class="c1"&gt;# The machine to use&lt;/span&gt;

        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Define Steps
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Steps&lt;/strong&gt; are the individual, sequential tasks that execute inside a single job. They run one after another, in the exact order they are listed in the YAML file.&lt;br&gt;
All steps in a single job run on the same virtual machine instance. If Step 1 creates a file or installs a package, Step 2 can use it.&lt;br&gt;
In case any step fails (returns an error code), the job stops immediately, and the remaining steps are skipped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Step 1: Get the code&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Github code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="c1"&gt;# Step 2: Set up Node.js&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node.js&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&lt;/span&gt;
        &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That there was a simple CI pipeline now of to the CD.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Deployment cycle
&lt;/h3&gt;

&lt;p&gt;Similar to the CI structure, the CD is also made in the same structure but the steps differ. &lt;br&gt;
They go from tests, if they pass then to the build. Upon successful build the project is then staged and finally pushed to production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Prevent multiple deployments at once&lt;/span&gt;
&lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deployment&lt;/span&gt;
  &lt;span class="na"&gt;cancel-in-progress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# First: Run tests&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;

  &lt;span class="c1"&gt;# Second: Build the project&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="s"&gt;...&lt;/span&gt;

  &lt;span class="c1"&gt;# Third: Deploy to staging&lt;/span&gt;
  &lt;span class="na"&gt;deploy-staging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Staging&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;staging&lt;/span&gt;        &lt;span class="c1"&gt;# Requires environment approval (optional)&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="s"&gt;...&lt;/span&gt;

  &lt;span class="c1"&gt;# Fourth: Deploy to production (manual approval)&lt;/span&gt;
  &lt;span class="na"&gt;deploy-production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Production&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy-staging&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;     &lt;span class="c1"&gt;# Can require manual approval in GitHub settings&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is just an example, to better understand see the video &lt;a href="https://www.youtube.com/watch?v=0PbxpIao_EU" rel="noopener noreferrer"&gt;here&lt;/a&gt; or see this &lt;a href="https://github.com/shazforiot/github-actions-demo" rel="noopener noreferrer"&gt;github repo&lt;/a&gt;. It will provide a wider view and context&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do this
&lt;/h2&gt;

&lt;p&gt;Short answer: Speed. Organizations that have mastered the CI/CD, build and deploy products faster than others. Since products are always being rated and feedback being provided. Developers commit smaller changes more often, hence keeping up with customer demands.&lt;br&gt;
With ongoing feedback, developers are constantly making small changes. &lt;br&gt;
Automated continuous testing ensures that the codebases remain stable and ready for deployment at all times. Since the manual tasks are taken care of with this automation, developers can focus on creation, innovation, and other important tasks&lt;/p&gt;

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

&lt;p&gt;I'm also still learning about this concept and implementing it into my own workflow. It's a core skill that I believe every developer should enforce in their workflows especially junior developers. It's a major time saver and also ensures you always have working code ready for production.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
