MoreRSS

site iconThe Practical DeveloperModify

A constructive and inclusive social network for software developers.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of The Practical Developer

Beginner's Guide to Git and GitHub: Version Control Made Simple

2026-01-17 17:47:25

Introduction
Git and GitHub are essential tools for developers, data scientists, and anyone working with code. This guide will help beginners understand how to track changes, push and pull code, and use version control effectively.

What is Git
Git is a version control system that acts like a time machine for your code. *It tracks every change you make to your files*, so you can:

  • Go back to a previous version if something breaks.
  • Track what changes were made.
  • Work safely on multiple projects at the same time.

Example:
Imagine you wrote a program yesterday, but it stopped working today. Git lets you revert to yesterday’s version quickly.

What is GitHub?
GitHub is an online platform for storing Git projects. It allows you to:

  • Share your code with others
  • Collaborate on projects
  • Backup your work online

Think of GitHub as a *cloud version of your Git projects*

What is Version Control?
Version control helps you track changes in your files over time. It’s useful because:

  • You never lose your work
  • You can see who made changes and when
  • You can safely work with others on the same project.

Git Workflow for Beginners

  1. Check Git Version: Before starting, make sure Git is installed: Bash code git --version The double hyphen (--version) is required Shows which version of Git is installed on your computer.
  2. Check the Status of Your Project: To see which files have changed or are ready to be saved: Bash code git status Shows files that are modified, untracked, or staged for commit. Helps you understand what Git is tracking, an essential part of version control.
  3. Add Files to Be Tracked: Bash code git add. The . tells Git to stage all files in the folder Staging files prepares them to be saved in your project history
  4. Commit Your Changes: Bash code git commit -m "Describe your change here" The -m flag (single hyphen) is for your commit message Commits save a snapshot of your project locally Each commit is part of version control, so you can revert if needed.
  5. Push Changes to GitHub: Bash code git push Uploads your committed changes to your GitHub repository Keeps your work backed up online Makes your project available to collaborators.
  6. Pull Changes from GitHub: Bash code git pull Downloads the latest changes from GitHub to your local project Ensures your work is up to date before making new changes
  7. See the History of Your Project: Bash code git log
  • Shows all previous commits with messages
  • Let's you review the history of changes
  • A key part of understanding version control in action

Beginner Friendly Daily Workflow
Here’s a simple workflow that combines all the above commands:
Bash code
git --version # Check Git version
git status # See changes
git add . # Stage files for commit
git commit -m "Describe what you changed" # Save snapshot locally
git push # Upload changes to GitHub
git pull # Download latest changes from GitHub
git log # Review history
Every command above is part of version control, tracking your files, saving snapshots, sharing and reviewing history.

SQL Queries Every Developer Should Know

2026-01-17 17:46:33

Introduction to SQL
If you are a web developer, chances are you have worked with a database at some point. It might be PostgreSQL, MySQL, SQLite, or something else. No matter the stack, SQL is always there behind the scenes.And let’s be honest, few things feel better than writing a single SQL query that returns exactly the data you need. Extra points if it runs fast.In this article, we’ll walk through essential SQL queries every developer should know. Whether you are building APIs, dashboards, or debugging a production issue at 2 AM, these queries are your daily tools.

  1. SELECT & The Foundation If SQL were a movie, SELECT would be the origin story. Every meaningful query starts here.

Use SELECT to fetch only the data you actually need. While SELECT * looks convenient, it can slow down queries and waste bandwidth, especially on large tables.

The real power of SELECT comes when you combine it with WHERE, JOIN, and ORDER BY.

SELECT id, name, email
FROM users;

  1. WHERE Filtering the Noise Databases can store millions of rows. WHERE helps you narrow things down to what actually matters.

You can filter using:

Comparison operators: =, !=, <, >, <=, >=
Logical operators: AND, OR, NOT
Without WHERE, things can get dangerous. A query like DELETE FROM users; without a condition will delete everything. Always double-check.

SELECT *
FROM orders
WHERE status = 'completed';

  1. INSERT Adding New Data Whenever a user signs up, places an order, or uploads something, you’ll need INSERT.

Best practices:

Always specify column names
Use bulk inserts when possible for better performance
Never trust user input. Use parameterized queries or an ORM to prevent SQL injection
INSERT INTO users (name, email)
VALUES ('Alice', '[email protected]');

  1. UPDATE Changing Existing Data Emails change, addresses change, and bugs happen. That’s where UPDATE comes in.

The most common and most dangerous mistake is forgetting the WHERE clause. Without it, every row gets updated.

Tips:

You can update multiple columns at once
Use transactions in production to stay safe
UPDATE users
SET email = '[email protected]'
WHERE id = 42;

  1. DELETE Removing Data When it’s time to clean up old or unused data, DELETE does the job.

Use cases:

Removing expired sessions
Cleaning test data
Deleting old logs
Many production apps use soft deletes by adding a deleted_at column instead of permanently removing records.

DELETE FROM sessions
WHERE last_active < NOW() - INTERVAL '30 days';

  1. JOIN Combining Tables Real applications don’t live in a single table. JOIN lets you stitch data together.

Become a member
Common types:

INNER JOIN: Only matching rows
LEFT JOIN: All rows from the left table, even if there is no match
RIGHT JOIN: Opposite of left join
FULL JOIN: Everything from both tables
If your results suddenly double, chances are your join condition is wrong.

SELECT users.name, orders.amount
FROM users
JOIN orders ON users.id = orders.user_id;

  1. GROUP BY and Aggregate Functions Perfect for analytics and reports.

Common aggregates:

COUNT() – number of rows
SUM() – total
AVG() – average
MAX() / MIN() – highest or lowest values
Whenever you use aggregates with non-aggregated columns, GROUP BY is required.

SELECT status, COUNT(*) AS total
FROM orders
GROUP BY status;

  1. ORDER BY and LIMIT Sometimes you only need the latest or top results.

Use cases:

Latest blog posts
Top users by score
Recent transactions
This combo is also great for pagination when used with OFFSET.

SELECT *
FROM orders
ORDER BY created_at DESC
LIMIT 10;

  1. LIKE and Pattern Matching For basic search functionality, LIKE is simple and effective.

Patterns:

% matches any number of characters
_ matches a single character
Note: Case sensitivity depends on the database. PostgreSQL uses ILIKE for case-insensitive searches.

SELECT *
FROM users
WHERE email LIKE '%@gmail.com';

  1. Subqueries Sometimes one query needs the result of another. That’s a subquery.

They are great for readability, but joins are often faster. Use subqueries when clarity matters more than raw performance.

SELECT name, email
FROM users
WHERE id IN (
SELECT user_id
FROM orders
WHERE amount > 100
);
Final Thoughts: Mastering SQL
This article is part of the “SQL Queries Every Developer Should Know” series.

Mastering these queries will help you:

Debug faster by querying the database directly
Build better and faster APIs
Write cleaner backend logic
Impress teammates during code reviews
SQL is not scary. It’s a superpower. And like any skill, the more you practice it, the more confident and unstoppable you become.

Gas Inefficiencies Developers Don't Notice Until It's Too Late.

2026-01-17 17:44:43

In May 2023, a DeFi protocol launched its token claim contract. Within 48 hours, users had spent over $2 million in gas fees, not because the contract was complex, but because the developers hadn't optimized their loops. Each claim processed the same storage array 100+ times instead of caching it once.

The contract worked. It just costs users 10x more than it should have. This wasn't a hack. It wasn't a bug. It was inefficient code that silently compounded until real money started burning.

Here's the reality: Compute and storage are never free. On Ethereum, every opcode has a gas price. On Stellar's Soroban, computation and storage consume transaction budgets. Solana charges compute units. Polkadot weighs transactions. Different execution models, same outcome, inefficient code becomes a production problem fast.

If you're building on any blockchain, gas optimization isn't optional. It's the difference between a protocol users can afford to use and one they abandon for cheaper alternatives.

Why Gas Costs Soar Out of Control

The biggest culprit across all chains? Storage operations.

On EVM chains (Ethereum, Polygon, BSC, Arbitrum):

  • mload and mstore (memory): 3 gas per operation.

  • sload and sstore (storage): 100+ gas minimum.

As defined in the Ethereum Yellow Paper, storage operations cost over 100× more than memory operations.

On Non-EVM (Soroban, Solana):

  • Writing to a new storage entry allocates ledger space, consuming significant resources.

  • Storage reads/writes count against your transaction's CPU and memory budget.

  • Cross-program invocations (CPIs) add compute overhead.

The pattern is universal: Touching a persistent state is expensive. The exact mechanism differs by chain, but the principle holds.

The problem isn't just that storage costs more; it's that developers unknowingly trigger these operations repeatedly. A loop that runs 100 times and reads from storage on each iteration? That's 100 expensive reads instead of one cached value, whether you're on EVM or Non-EVM.

Small inefficiencies multiply. And by the time you notice in production, your users are already paying for it.

The 6 Gas Killers (And How to Fix Them)

Most gas bloat comes from patterns developers don't recognize as problems until deployment. These patterns appear across all blockchain architectures; the syntax changes, but the inefficiencies remain the same.

Let's break down the worst offenders with examples across different chains:

1. Unnecessary Storage Writes.

The mistake: Writing default or zero values when they're not needed, or writing data that hasn't actually changed.

Why it's expensive:
EVM chains: Each storage write costs ~20,000 gas. Even after EIP-3529 reduced refunds, writing to an already-zero slot still costs ~2,900 gas on warm slots.

Non-EVM chains (e.g., Soroban): Every storage write consumes part of your transaction budget. Writing unchanged values wastes CPU instructions and ledger I/O.

How to fix it:
On EVM (Solidity):

// ❌ Bad: Always writes
balances[user] = 0;

// ✅ Good: Only writes if needed
if (balances[user] != 0) {
    delete balances[user]; // Triggers gas refund
}
On Non-EVM (Rust/Soroban):

// ❌ Bad: Always writes
env.storage().instance().set(&USER_BALANCE, &0);

// ✅ Good: Check before writing
if env.storage().instance().has(&USER_BALANCE) {
    env.storage().instance().remove(&USER_BALANCE);
}

Additional optimizations:

  • EVM: Pack booleans and small integers into the same 256-bit slot, save entire storage slots (~20,000 gas each).

  • Non-EVM (Soroban): Use temporary storage for data that doesn't need to persist across ledgers.
    Both: Use events/logs instead of storage for infrequently accessed data.

2. Loops That Access Storage Repeatedly

The mistake:Reading from or writing to storage inside loops. Each storage operation costs resources, so if your loop touches storage on every iteration, costs multiply quickly.

Why it's expensive:
A loop that processes 100 items and reads from storage each time equals 100 expensive operations instead of 1 cached read.

How to fix it:
On EVM (Solidity):

// ❌ Bad: Reads storage 100 times
for (uint i = 0; i < users.length; i++) {
    totalBalance += balances[users[i]]; // sload every iteration
}

// ✅ Good: Cache values
uint length = users.length;
uint tempBalance;
for (uint i = 0; i < length; i++) {
    tempBalance += balances[users[i]];
}
totalBalance = tempBalance; // Single sstore
On Non-EVM (Rust/Soroban):

// ❌ Bad: Reads storage in loop
let mut total = 0;
for user in users.iter() {
    total += env.storage().instance().get::<_, i128>(&user).unwrap_or(0);
}


// ✅ Good: Batch reads or cache
let total: i128 = users.iter()
    .map(|u| env.storage().instance().get::<_, i128>(u).unwrap_or(0))
    .sum();

3. Not Validating Inputs Early

The mistake: Performing expensive operations before checking if inputs are even valid.

Why it's expensive:
If a transaction is going to fail anyway, you want it to fail as cheaply as possible. Order matters.

How to fix it:
On EVM (Solidity)

 // ❌ Bad: Expensive check first
require(balances[msg.sender] >= amount); // Storage read
require(amount > 0); // Memory check

// ✅ Good: Cheap checks first
require(amount > 0); // Fails fast if zero
require(balances[msg.sender] >= amount); // Only runs if amount valid
On Non-EVM (Rust/Soroban):

// ❌ Bad: Storage check first
let balance = env.storage().instance().get::<_, i128>(&user).unwrap_or(0);
if amount <= 0 {
    panic!("Invalid amount");
}

// ✅ Good: Validate inputs first
if amount <= 0 {
    panic!("Invalid amount"); // Fails immediately
}
let balance = env.storage().instance().get::<_, i128>(&user).unwrap_or(0);
if balance < amount {
    panic!("Insufficient balance");
}

**Universal principle: **Validate cheaply (bounds checks, null checks) before expensive operations (storage reads, cryptographic operations).

4. Making Multiple Transactions Instead of Batching.

** The mistake:** Splitting work across many transactions instead of grouping operations.

Why it's expensive:

EVM chains:Each transaction has a base fee (~21,000 gas). 100 transactions = 100 base fees.

Non-EVM (eg, Soroban):Each transaction consumes base CPU/memory budget overhead.

How to fix it:
On EVM (Solidity):

// ❌ Bad: 100 transactions = 100 base fees
// User calls transfer() 100 times

// ✅ Good: 1 transaction, 1 base fee
function batchTransfer(address[] calldata recipients, uint[] calldata amounts) external {
    require(recipients.length == amounts.length, "Length mismatch");
    for (uint i = 0; i < recipients.length; i++) {
        _transfer(msg.sender, recipients[i], amounts[i]);
    }
}

On Non-EVM (Soroban/Rust):

// ✅ Good: Batch operations in single contract call
pub fn batch_transfer(
    env: Env,
    from: Address,
    transfers: Vec<(Address, i128)>
) -> Result<(), Error> {
    from.require_auth();

    for (to, amount) in transfers.iter() {
        transfer_internal(&env, &from, to, *amount)?;
    }
    Ok(())
}

5. Inefficient Data Handling

The mistake: Copying data unnecessarily or using the wrong data location for function parameters.

Why it's expensive:
Memory operations and data copies cost resources across all chains.

How to fix it:
On EVM (Solidity):

// ❌ Bad: Copies array to memory
function sum(uint[] memory numbers) public returns (uint) {
    uint total;
    for (uint i = 0; i < numbers.length; i++) {
        total += numbers[i];
    }
    return total;
}

// ✅ Good: Reads directly from calldata
function sum(uint[] calldata numbers) public pure returns (uint) {
    uint total;
    for (uint i = 0; i < numbers.length; i++) {
        total += numbers[i];
    }
    return total;
}
On Non-Evm (Soroban/Rust):

// ❌ Bad: Cloning data unnecessarily
pub fn process_data(env: Env, data: Vec<i128>) -> i128 {
    let copied = data.clone(); // Unnecessary clone
    copied.iter().sum()
}

// ✅ Good: Use references
pub fn process_data(env: Env, data: Vec<i128>) -> i128 {
    data.iter().sum() // No clone needed
}

Additional tips:

EVM (Solidity): Mark read-only functions as view or pure (can be called off-chain for free).
Non-EVM (Rust): Use & references instead of cloning Vec or Map structures.

Your Gas Optimization Checklist

Before you deploy on any chain, run through this checklist:

  • Storage usage:

a. No unnecessary writes to storage.
b. Variables/data packed efficiently.
c. Old entries deleted/removed for refunds (EVM) or budget recovery.
d. Events/logs used instead of storage for infrequently accessed data.

  • Loops:

a. No storage reads/writes inside loops
b. Array lengths and values cached beforehand
c. Heavy computation moved off-chain or batched

  • Data locations:

a. EVM (Solidity): Large inputs use calldata, not memory.
b. Non-Evm (Rust): Use references (&) instead of cloning.

  • Control flow:

a. Cheap validation checks before expensive operations.
b. Conditions structured to short-circuit away from costly paths.

  • Redundant operations:

a. Current values checked before writing.
b. Conditional checks skip no-op writes.
c. State is cleared explicitly when no longer needed.

  • Profiling:

a. Gas/resource reporter integrated into test suite.
b. Functions profiled during development.
c. Static analysis in CI/CD pipeline.

  • Chain-specific optimizations:

a. EVM: Storage packing, immutable/constant usage, library calls.
b. Non-EVM (Rust): Storage tier usage, WASM size, Rust efficiency patterns.

Alright, real talk.

Gas optimization isn't glamorous. It doesn't lend itself to flashy demos or impressive pitch decks. But it's the difference between a protocol users can actually afford to use and one they abandon after the first transaction.

I've seen great projects die because their gas costs were five times higher than those of their competitors. Not because the code was bad, but because it wasn't efficient.

Every blockchain has its quirks, but the fundamentals are universal: plan for efficiency or pay the price.

Whether you're deploying to Ethereum mainnet, launching on Stellar, or building on any other Non-EVM chains, the same patterns apply: minimize storage, batch operations, validate early, and compute off-chain.

I built a free focus timer with visual themes and ambient sounds

2026-01-17 17:42:15

Hey! I built this because every online timer I found was either ugly, bloated with ads, or required signup.

VibeTimers is a free, no-signup focus timer with:

  • Visual themes (anime, sports, nature) instead of plain white backgrounds
  • Built-in ambient sounds (lofi, rain, forest, coffee shop)
  • Daily quests to gamify tasks
  • Preset and custom timers

Built with React + TypeScript. No tracking, no accounts, works on mobile.

Would love feedback on the UX or feature ideas. Thanks for checking it out!

A NEWBIE'S GUIDE TO GIT(gitbash).

2026-01-17 17:35:53

Git

Are you a newbie on git like me?

Check out this article on how you can install and configure Git also known as gitbash and connect it to your GitHub account on a Windows operating system, using commands and prompts.

Definitions:

  • Github - This is a virtual control platform that allows you to create, store, manage, track, and share your code with other developers. It enables collaborations on projects.

  • Git/Gitbash - This is a command-line version control interface that allows you to communicate with your GitHub account using prompts and commands.

Fun fact about git:

Git uses the SHA-1 (and increasingly SHA-256) cryptographic hashing algorithm to identify every commit. This ensures that the code cannot be altered or corrupted without detection.

  • Commit - Is a permanent record of your code at a specific point in time. A code checkpoint that can be secured using cryptography.

Now that you know the tools, let's get started!

How to Install GitHub Locally:

Step 1:
Open your default browser and search github, click the first link, and sign up. OR follow this link to Github and sign up

Step 2:
Create a Profile on Github and sign up
Fill in all the necessary fields, e.g., profile picture, name, and Bio information.

Congratulations! You have successfully created a GitHub account.

How to Install Git / Gitbash :

Step 1:

Open your browser and search for Git. OR follow this Link Git Install

Step 2:

Select the Operating system you are installing git on, i.e., Windows/ Mac os / Linux, etc

Step 3:

Click the hyperlink "click here to download" (as shown below)

Git download

Step 4:

Once the program has finished downloading on your machine. Open and run the program.

Be sure to pick Visual Studio as your default code editor on git when going through the steps of installation

Follow each step carefully as instructed until you successfully finish installing it.

How to connect your Git to your Gitbash account using commands.

Follow the following steps

Step 1: Launch your git

Step 2: Use the commands listed below in the following order.

  • Command to check your git version

git --version

  • Command to configure your name and email

git config --global user.name "enter your name"
git config --global user.email "enter your email"

Please use the same name and email used to create your github account

  • Command to check that your configurations are successful

git config --list

  • Command to generate an SSH key ( This is your unique digital identity)

ssh-keygen -t ed25519 -C "email"

  • Command to make an agent for your sshkey

eval "$(agent-ssh -s)"

  • Command to add the agent.

ssh-add ~/.ssh/id_ed25519

  • Command to print or publish the agent

cat ~/.ssh/id_ed25519.pub

Now let's connect gitbash to github

  1. Follow the path provided by git to where your key is stored >> Open it using Visual Studio and copy it to your clipboard

  2. Open your github account >> Go to settings >> Got to SSH & GPG keys.

  3. Click add new SSH key >> Paste the key you had copied earlier in VS stduio.

Congratulations! you successfully connected your git and GitHub accounts

Command to verify connection

ssh -T [email protected]

You should get a confirmation like shown below:

Git

Now Let's learn a few more commands on git!

1. Version Control on git

Git is the most commonly used software for version control because of the following features:

  • It takes a snapshot of every commit in the entire project.

  • It provides an audit trail of all changes made to the code, who made the changes, what was changed in the code, and the date and time it was changed.

  • It can restore any version of the project because it keeps a permanent, unaltered record of every commit made in the entire project.

2. Push and Pull code on git.

Pushing and pulling are terms used to refer to the communication between your local machine and a remote server repository where code is stored (git in this case).

  • Pushing - is using a specific command or an inbuilt graphical interface tool, like in Visual Studio, to send your commits/code to a shared repository (like on GitHub) where other developers can see and interact with it. Can be referred to as upload

An example of a command to push code

git add
  • Pulling - is using a specific command or inbuilt GUI tool to retrieve specific changes made from a remote repository and downloads and merges them into your code.

An example of a command to pull code

git pull --rebase

3. Tracking code on git.

Tracking code on git is monitoring any unsaved modifications and the history of any permanent changes that have been made to the project.

Below are a few commands to track any changes in your work directory.

  • To check the project's current overall status

git status

  • To view exact code changes

git diff

  • To check the changes waiting to be committed (staged)

git diff --staged

  • To check full history or logs
    git log

  • For a condensed view of your history

git log --oneline

  • For history of a specific file

git log --[filename]

  • To show a detailed view of all your commits

git show --[commit-hash]

Thank you for reading my article to the end !!

I hope you find it informative and educational. Please comment and let me know what you think about my article!!

Adios, until the next one.

Signed
Jules.