Friday, July 25, 2025

🛰️ NASA’s DSOC: Laser Communications for Deep Space

 NASA’s Deep Space Optical Communications (DSOC) system is a revolutionary leap in how we send and receive data across space. Instead of traditional radio waves, DSOC uses lasers — offering faster, more efficient communication with spacecraft traveling millions of kilometers from Earth.


🔭 Why DSOC?

Traditional deep space missions (like Voyager or Mars rovers) rely on radio-frequency (RF) communications, which are reliable but limited in bandwidth. As missions demand more data — high-resolution images, scientific sensor output, even HD video — radio just isn't fast enough.

DSOC uses infrared lasers, which:

  • Transmit data with much higher bandwidth

  • Use narrower beams, reducing signal loss

  • Require less power per bit compared to RF


⚙️ How It Works

  • Onboard Laser Transmitter: The spacecraft carries a laser that sends data back to Earth.

  • Ground-Based Telescope Receiver: Large telescopes on Earth (like those at NASA’s Jet Propulsion Lab) equipped with sensitive detectors capture the faint laser signal.

  • Pointing Accuracy: DSOC must align precisely — the beam is narrow, like aiming a laser pointer at a coin from thousands of kilometers away.


📡 Achievements

In November 2023, DSOC successfully transmitted data from NASA’s Psyche spacecraft — aimed at a metal-rich asteroid between Mars and Jupiter — back to Earth using lasers over 16 million kilometers away. The experiment hit record-breaking data rates, showcasing the future of interplanetary communication.


🚀 Applications

  • Mars missions: Faster uploads/downloads of scientific data and even high-def video.

  • Lunar Gateway: Reliable, high-bandwidth link to the Moon’s orbital station.

  • Future human missions: Supports communication for astronauts and AI systems.


✅ Conclusion

NASA’s DSOC proves that laser communication is not just science fiction — it’s the next step in space exploration. With faster, clearer data links, future missions will send back more science, more detail, and perhaps one day, real-time video from other planets.

🔧 Wave Soldering: The Fast Lane of PCB Assembly

 Wave soldering is a high-speed method used to solder electronic components to printed circuit boards (PCBs) — especially in through-hole and some surface-mount assembly processes. It's called "wave" soldering because it uses a molten wave of solder to create clean, consistent connections across an entire board.


⚙️ How Wave Soldering Works

The process involves several key steps:

  1. Flux Application
    The PCB is sprayed with a chemical flux to clean metal surfaces and prevent oxidation.

  2. Preheating
    The board is heated gradually to activate the flux and prevent thermal shock.

  3. Solder Wave
    The PCB is passed over a wave of molten solder (usually lead-free alloys). The wave makes contact with the component leads and PCB pads, forming permanent solder joints.

  4. Cooling
    The board is cooled in a controlled environment to solidify the joints and maintain alignment.


🔩 Where It's Used

  • Through-hole PCBs with pins or leads that pass through holes.

  • Mixed-technology boards that include both surface-mount and through-hole components.

  • High-volume production, where speed and consistency are critical.


✅ Advantages

  • 🔄 Efficient: Can solder hundreds of joints at once.

  • 🧩 Consistent quality: Automated process reduces human error.

  • 🕒 Fast: Ideal for mass production lines.


⚠️ Limitations

  • Not suitable for fine-pitch surface-mount components.

  • Requires precise board design to avoid defects like bridging or cold joints.

  • Flux residues may need cleaning after soldering.


📌 Conclusion

Wave soldering revolutionized electronics manufacturing by making fast, reliable mass soldering possible. Though it's been partly replaced by reflow soldering for surface-mount devices, it's still a workhorse method for assembling durable, large-scale PCBs in power electronics, appliances, and industrial systems.

🛠️ WD-40: From Rocket Science to Squeaky Hinges

WD-40 is a household name today — found in garages, toolboxes, and workshops worldwide. But its origins are surprisingly high-tech: it started in the aerospace industry, not as a general-purpose lubricant.


🚀 Born from Rocket Science

WD-40 was first created in 1953 by a small San Diego company called Rocket Chemical Company. Their original mission? To develop rust-prevention solvents and degreasers for the AeroShell missile program. One of the biggest challenges was keeping missile casings free from corrosion, especially during storage and flight.


💧 Why "WD-40"?

The name stands for "Water Displacement, 40th formula" — meaning it took 40 attempts to get the perfect formula that could displace water and prevent rust. The final concoction was a hit, so much so that employees began sneaking it home to use on household items.


🧴 From Lab Secret to Shelf Staple

Seeing its wider potential, the company began selling WD-40 in aerosol cans to the public in 1958. It quickly gained a reputation as a multi-purpose miracle spray — capable of:

  • Displacing moisture

  • Loosening stuck parts

  • Preventing rust

  • Cleaning grease and grime


đŸ§Ē What’s Inside?

While the full formula is still a secret, we know WD-40 contains:

  • A light oil

  • A solvent carrier

  • A propellant (in aerosol versions)

It's not a heavy-duty lubricant, but it works incredibly well for short-term fixes and corrosion prevention.


🔧 Fun Fact

WD-40 isn’t just for squeaky doors. People have used it for:

  • Removing crayon from walls

  • Untangling jewelry chains

  • Loosening zippers

  • Cleaning car engines

  • Even fishing bait enhancement (though not recommended!)


📌 Conclusion

From keeping missiles dry to fixing your bike chain, WD-40’s journey is a classic tale of innovation, adaptation, and practicality. It may have started as a solution to an aerospace problem, but it ended up becoming a can of everyday engineering magic.

Avalanche Breakdown and Avalanche Oscillator: A Brief Overview

 Avalanche breakdown is a phenomenon that occurs in semiconductor devices, particularly in diodes and transistors, when the reverse-bias voltage across a junction becomes so high that it causes a sudden increase in current. This is due to the impact ionization process, where high-energy carriers collide with atoms in the lattice and knock loose additional charge carriers. This creates a chain reaction, leading to a sharp rise in current, known as avalanche breakdown.

In a transistor, particularly in bipolar junction transistors, avalanche breakdown usually occurs at the collector-base junction when the transistor is reverse-biased beyond its rated breakdown voltage. While this condition is typically undesirable in digital circuits, it can be intentionally used in certain analog and timing applications, such as in avalanche oscillators.

An avalanche oscillator is a type of relaxation oscillator that utilizes the avalanche breakdown behavior of a transistor. In this circuit, a transistor is reverse-biased just below its breakdown voltage using a high-resistance path. When the voltage across the junction reaches the breakdown threshold, the transistor suddenly conducts, allowing a burst of current to flow. This sudden change rapidly discharges a capacitor in the circuit, and once the voltage drops, the transistor returns to its non-conducting state. The cycle then repeats, producing a waveform, often a sawtooth or sharp pulse.

The key relation is that the oscillator exploits the fast switching and regenerative nature of avalanche breakdown. The steep onset of current during breakdown provides a very sharp transition, making avalanche oscillators useful for generating fast pulses, high-frequency signals, or noise sources in random number generators and similar applications.

In essence, the avalanche breakdown is the physical principle, while the avalanche oscillator is a circuit design that uses this principle to generate periodic signals.

Understanding RAD50 Encoding in Embedded Systems

When working on embedded systems like Arduino, every byte of memory can matter. This is especially true when storing lots of short text, such as identifiers, filenames, or codes. That's where an old but clever technique called RAD50 encoding can help.

What is RAD50?

RAD50 is a way to compress 3 characters into 2 bytes. Normally, storing 3 characters in ASCII takes 3 bytes. But RAD50 packs those same characters into just 2 bytes, saving space. This works only for a limited set of characters, mostly uppercase letters, digits, and a few symbols.

How does it work?

RAD50 uses a math trick. Instead of storing each character separately, it treats the group of 3 characters as a single number using base-40 arithmetic. Here's the idea:

  • Each character is given a number from 0 to 39.

  • The first character is multiplied by 40 squared.

  • The second is multiplied by 40.

  • The third is added directly.

  • The result is a single number that fits within 16 bits (2 bytes).

When decoding, the process is reversed to get the original 3 characters back.

So you're not slicing bits per character. You're just combining values in a smart way that compresses the text into less space.

Why would you use RAD50?

You'd consider RAD50 in embedded systems if:

  • You're storing a lot of short text, like tags or codes.

  • You want to save RAM, EEPROM, or flash memory.

  • Your text only uses uppercase letters, numbers, and a few basic symbols.

  • You don’t need international characters or lowercase letters.

In these cases, RAD50 can reduce memory usage by about 33 percent. That means more data fits in the same space — and that can be a big deal on microcontrollers with limited memory.

When is RAD50 not a good idea?

RAD50 isn’t helpful if:

  • You need to store lowercase letters or special characters.

  • You're working with human-readable text or full sentences.

  • You need simple string handling — RAD50 adds encoding and decoding overhead.

Final Thoughts

RAD50 is a clever old-school trick that's still useful today — especially in tight memory environments where you need to pack as much information as possible. It's not for every project, but when you’re dealing with limited character sets and memory pressure, it's a neat tool to keep in your embedded toolbox.

Understanding Snubber Circuits for Inductive Loads

A snubber circuit is an electrical circuit used to suppress voltage spikes and transients caused when switching inductive loads. These spikes are dangerous to switching elements like relays, transistors, or triacs and can lead to electrical noise, contact pitting, and premature failure.

Why Snubber Circuits Are Needed

When a switch (mechanical or semiconductor) opens an inductive load, the collapsing magnetic field generates a high voltage spike due to the energy stored in the inductance. This can result in arcing across relay contacts or overvoltage damage to semiconductors.

This phenomenon is well-documented in engineering literature:

  1. The Art of Electronics by Paul Horowitz and Winfield Hill (3rd Edition) explains that snubber circuits are used to protect switching devices from inductive kickback. It specifically states that turning off inductive loads causes voltage spikes that must be suppressed by a diode or snubber.

  2. Power Electronics: Converters, Applications, and Design by Ned Mohan confirms that snubbers are essential to protect semiconductor devices from the effects of inductive switching.

  3. IEEE papers such as "Snubber Circuits: Theory, Design and Application" outline that snubbers suppress voltage transients that occur when current through an inductor is suddenly interrupted.

  4. Application notes from STMicroelectronics and Texas Instruments also support this, stating that snubbers are critical for switching inductive loads like motors and transformers. For example, ST’s AN308 and TI’s SLVA255 make direct statements about the role of snubbers in protecting switches from the energy stored in inductive loads.

When Snubbers Are Necessary

You should use a snubber circuit in the following cases:

  • Switching inductive loads such as motors, relays, solenoids, and transformers.

  • Using mechanical relays or triacs that control inductive AC loads.

  • Observing arcing or premature contact wear.

  • Experiencing false triggering or noise on nearby circuitry due to switching.

Snubbers are generally not necessary for resistive loads like incandescent bulbs or heating elements. However, capacitive-drop LED bulbs, while not inductive, can benefit from snubbers due to inrush currents and fast rise times, which can also damage mechanical contacts.

Types of Snubber Circuits

  1. RC Snubber: Used mainly with AC inductive loads or triacs. Consists of a resistor and capacitor in series connected across the switch.

  2. Flyback Diode: Used in DC circuits across inductive loads. This diode allows current to circulate through the load when the switch opens, safely dissipating stored energy.

How to Calculate RC Snubber Values

The goal is to suppress the voltage spike without creating too much power loss or delay in switching. Here’s a basic approach for RC snubbers:

  1. Capacitance (C)

Start with a value in the range of 100 nanofarads to 470 nanofarads. For 230V AC use, the capacitor must be rated for X2 class (safety-rated for across-the-line applications) with a voltage rating of 250V AC or higher.

  1. Resistance (R)

Calculate the resistance using the formula:


Why BJTs Are Current-Driven and MOSFETs Are Voltage-Driven

 A plain-language explanation of how these transistors work

Transistors are tiny electronic switches that help control the flow of electricity in circuits. There are two main types: BJTs and MOSFETs. Even though they both act like switches or amplifiers, they work in very different ways.

Let’s break it down.


First, What Does “Driven” Mean?

When we say a transistor is current-driven or voltage-driven, we’re talking about what it needs at its input to start working — to "turn on" or conduct electricity.

  • Current-driven means you need to send current into the transistor’s input to make it work.

  • Voltage-driven means you just need to apply a voltage at the input — no real current has to flow.


BJTs: The Current-Driven Transistor

BJT stands for Bipolar Junction Transistor. It has three parts: base, collector, and emitter.

To turn on a BJT, you need to push a small current into the base pin. This current controls a much larger current flowing from the collector to the emitter.

Think of it like a faucet handle. If you press the handle (the base current), it lets a lot of water (collector current) flow. No press, no flow.

So, BJTs are like valves that open when a small current is applied.

That’s why we call them current-driven — they need a continuous input current to work.


MOSFETs: The Voltage-Driven Transistor

MOSFET stands for Metal-Oxide-Semiconductor Field-Effect Transistor. It also has three parts: gate, drain, and source.

Here’s the difference: To turn on a MOSFET, you don’t need to push current into the gate. Instead, you just apply voltage to the gate.

The gate is separated from the rest of the transistor by a very thin layer of insulation, so no current flows in — like pressing a button that sends a signal through air, not a wire.

Once the voltage is high enough, the MOSFET turns on and allows current to flow between the drain and source.

So, MOSFETs are more like electronic switches that flip when they "feel" a certain voltage, not when they receive current.

That’s why we say they’re voltage-driven.


Why Does This Matter?

This difference affects how we use each transistor:

  • BJTs use more energy because they need current at their input all the time.

  • MOSFETs use almost no energy at their input — they’re great for power saving.

  • MOSFETs are often better for fast switching, like in computers or high-efficiency power circuits.

  • BJTs are still useful in simple circuits and analog amplifiers.


In Simple Terms

  • A BJT is like a water tap you open by letting a bit of water in — you need a small current to control a big one.

  • A MOSFET is like a touch-sensitive light switch — just a bit of voltage (like your finger) can flip it on, no current needed.


📘 Understanding Impedance and Related Concepts in Simple Words

In electronics, we often talk about resistance, capacitance, impedance, and phase shift — especially when working with AC signals or digital electronics like microcontrollers. These terms can seem confusing at first, but they all connect beautifully once you understand their basic meanings.

Let’s break them down in simple, everyday language.


🔌 What Is Resistance?

Resistance is the most basic and familiar idea. It simply means how much a component opposes the flow of electrical current. It works the same way for DC (direct current) and AC (alternating current).

Think of resistance like a narrow pipe in a water system — it limits how much water (current) can flow through. This opposition is measured in ohms (Ί).


🌊 What Is Impedance?

Impedance is like the AC version of resistance.

When you send AC signals, the current keeps changing direction — it goes back and forth. In this case, resistance alone is not enough to describe how the circuit behaves. That's where impedance comes in.

Impedance includes:

  • Resistance (the same kind from before)

  • Reactance (a new kind of opposition that depends on the signal’s frequency)

So, impedance is the total "opposition" a circuit gives to an AC signal — it's made of both resistance and reactance.


🔄 What Is Reactance?

Reactance is the part of impedance that comes from components like capacitors and inductors.

These don’t behave like simple resistors. Instead, they store and release energy as the current changes. This causes two important things:

  1. They oppose AC flow, but the amount depends on the frequency of the signal.

  2. They shift the timing of the voltage or current (this is called phase shift).

There are two types of reactance:

  • Capacitive Reactance – from capacitors (stronger at low frequencies)

  • Inductive Reactance – from inductors (stronger at high frequencies)


⚙️ What Is Capacitance?

A capacitor stores energy in an electric field. It:

  • Blocks DC (after charging up)

  • Slows down voltage changes in AC

  • Reacts more at lower frequencies

The more capacitance, the longer it can store energy before it’s “full.”


🔁 What Is Inductance?

An inductor stores energy in a magnetic field. It:

  • Passes DC easily (after a while)

  • Slows down current changes in AC

  • Reacts more at higher frequencies

The more inductance, the more it resists rapid changes in current.


⏱ What Is Phase Shift?

When capacitors and inductors react to changing signals, they cause a delay in current or voltage.

This is called a phase shift. It means the output wave is still a sine wave, but it starts a little later (or earlier) than the input.

The shape stays the same, but it's shifted in time.


🧰 What Is an RLC Circuit?

An RLC circuit has:

  • A Resistor (R)

  • An Inductor (L)

  • A Capacitor (C)

Together, they create interesting effects like:

  • Filtering certain frequencies

  • Resonance, where the circuit amplifies a specific frequency

  • Phase shifts

  • Damping (signal fading over time)

At the right frequency (called the resonant frequency), the inductor and capacitor cancel each other’s reactance, and the circuit allows the maximum current to flow.


🧠 Impedance in Digital Electronics

In digital or microcontroller circuits, when we say a pin is set to high impedance, it means:

  • The pin is not pushing or pulling any current.

  • It’s like the pin is disconnected or in “listen-only” mode.

  • This is useful for input pins or when sharing a wire (like I2C or SPI).

In this context, impedance just means very high resistance, not AC behavior.


⚡ Impedance in DC Circuits?

In pure DC circuits:

  • Capacitors block DC (after charging up)

  • Inductors act like normal wires after a while

So in DC, impedance is basically just resistance. We don’t really use the full concept of impedance unless the signal is changing — like AC or high-speed digital pulses.


đŸ§Ē Final Thought: Why It Matters

Understanding impedance and how it connects resistance, reactance, capacitance, and inductance helps you:

  • Design filters, amplifiers, and oscillators

  • Tune circuits to specific frequencies

  • Know why digital pins are “floating” or “high-Z”

  • Avoid mistakes when mixing analog and digital signals

Understanding the Linear Region in Transistors (Like a Runway for Amplification)

Imagine a transistor as a bridge between two worlds: one where it's either completely OFF or fully ON like a switch, and the other where it can act as a smooth, adjustable valve—precisely controlling how much current flows through it. That smooth in-between space is what we call the linear region.

What is the Linear Region?

The linear region of a transistor is where it behaves in a controlled, predictable way—perfect for amplifying signals. It’s not off. It’s not fully on. It’s just right. Think of it as the middle gear on a bike or the gentle throttle on a car, where your small changes in input lead to precise changes in output.

For a BJT (Bipolar Junction Transistor), this is the region where the base-emitter junction is forward biased, and the base-collector junction is reverse biased. For a MOSFET, it’s called the triode region, and it behaves like a voltage-controlled resistor.

Like an Airplane on a Runway

Here’s a fun analogy: picture a signal as an airplane and the transistor’s linear region as a runway.

  • If the runway is long and smooth (a well-chosen transistor with the right characteristics), the airplane (your signal) can safely take off and fly (get amplified).

  • If the runway is too short (narrow linear region), the plane might not take off properly—it might crash or never leave the ground. That’s distortion in electronics.

So when we design a circuit to amplify something—like sound, radio waves, or even sensor signals—we want to make sure our transistor has a long enough, stable runway for the signal to ride.

What Happens Outside the Linear Region?

Once the transistor moves out of the linear region, things change:

  • If we go into saturation (for BJTs) or fully-on mode (for MOSFETs), the transistor acts like a closed switch. No fine control. Great for turning things on or off, but useless for amplification.

  • If it’s in cutoff, the transistor is open—no current flows at all. It’s off.

So yes, when we use transistors as switches—like in logic circuits, relays, or microcontroller outputs—we intentionally drive them out of the linear region into full ON (saturation) or full OFF (cutoff).

Do MOSFETs Have a Linear Region Too?

Absolutely. While the terms differ slightly, MOSFETs also pass through a linear or triode region, where they act like adjustable resistors. This region is used less often in amplification, but it's key in analog applications like voltage-controlled resistors or current mirrors.

When a MOSFET is used as a switch, we drive it all the way into saturation (also called the ohmic region in power electronics) to act as a low-resistance connection.

The Bigger Picture: Patterns Everywhere

What’s beautiful is how this “linear region” idea shows up in other areas of life. Like the airplane analogy: there’s always a takeoff phase—a zone of careful control—before full flight. Similarly, in transistors, there’s a transition phase between off and on where magic happens: smooth control, fine-tuned amplification, and signal shaping.

It’s the same with pushing a swing, riding a bike, turning a faucet, or walking through a crowd. You can feel the difference between slow, smooth control and sudden jerks. That’s the feeling of analog behavior—and the transistor’s linear region lives right there.

Wednesday, April 23, 2025

Centralized Exception Handling with Unique IDs in Java.

 

When working with a large codebase or complex applications, tracking and managing exceptions efficiently is crucial. Here's how you can centralize exception handling while adding unique IDs to each exception for better traceability and debugging.

What is it?

Using a SafeRunner utility, we can wrap risky operations in a centralized exception handler, attaching a unique ID to each exception. This makes it easy to trace and manage exceptions across your application.

How it Works:

  • SafeRunner.run(): Wraps a task in a Callable, catches exceptions, and passes them to a centralized handler.

  • Exception IDs: Each exception is tagged with an ID to help track the specific context of errors.

  • Custom IdentifiedException: This custom exception class stores the exception ID for logging or reporting.

Code Example:

import java.util.concurrent.Callable;

// SafeRunner with exception ID
public class SafeRunner {
    public static <T> T run(Callable<T> task, String exceptionId) {
        try {
            return task.call();
        } catch (Exception ex) {
            handleGlobally(ex, exceptionId);
            return null;
        }
    }

    private static void handleGlobally(Exception ex, String exceptionId) {
        ex = new IdentifiedException(exceptionId, ex.getMessage(), ex);
        System.err.printf("Exception ID: %s\n", exceptionId);
        System.err.println("Global handler caught: " + ex);
        ex.printStackTrace(System.err);
    }
}

// Custom exception class with ID
class IdentifiedException extends RuntimeException {
    private final String id;

    public IdentifiedException(String id, String message, Throwable cause) {
        super(message, cause);
        this.id = id;
    }

    public String getId() {
        return id;
    }
}

// Example usage
public class App {
    public static void main(String[] args) {
        Integer result = SafeRunner.run(() -> divide(10, 0), "DIV-1234");
        SafeRunner.run(() -> { doSomethingRisky(); return null; }, "TASK-5678");
    }

    static int divide(int a, int b) {
        return a / b;  // Will throw ArithmeticException if b == 0
    }

    static void doSomethingRisky() throws Exception {
        throw new Exception("Oh no!");
    }
}

Benefits:

  • Traceability: Easily track which operation caused the exception.

  • Centralized Handling: Consolidates error handling logic in one place.

  • Better Debugging: Use exception IDs to correlate logs and errors across modules.

Use Cases:

  • Large Systems: Track errors across services and components.

  • Distributed Applications: Easily propagate error IDs across multiple services.

  • Debugging: Quickly trace specific issues through logs and support tickets.


This approach helps streamline exception management, providing a clear way to track and resolve issues quickly while keeping your codebase clean and maintainable.
-
git : https://github.com/stark9000/Centralized-Exception-Handling


Saturday, January 18, 2025

Code Smells āļ­ේāļģුāļ¸් āļœැāļąීāļ¸ āˇƒāˇ„ āļ’⎀ා ⎀⎅āļš්⎀ා āļœāļą්āļąේ āļšෙ⎃ේāļ¯?

 

Code Smells āļ­ේāļģුāļ¸් āļœැāļąීāļ¸ āˇƒāˇ„ āļ’⎀ා ⎀⎅āļš්⎀ා āļœāļą්āļąේ āļšෙ⎃ේāļ¯?
-
Code smells
āļēāļąු āļ”āļļේ āļšේāļ­āļēේ āļœැāļšුāļģු āļœැāļ§āˇ…ු āļ´ි⎅ිāļļāļŗ āļ¯āļģ්⎁āļš āˇ€ේ. āļ¯ෝ⎂ āļ…⎀⎁්‍āļēāļēෙāļą්āļ¸ āļąො⎀ුāļąāļ­්, āļ’⎀ා āļąāļŠāļ­්āļ­ු āļ¯ු⎂්āļšāļģāļ­ා, āļšිāļē⎀ීāļ¸ේ ⎄ැāļšිāļēා⎀ āļ…āļŠු ⎀ීāļ¸ āˇƒāˇ„ āļ­ාāļš්⎂āļĢිāļš āļĢāļē ⎀ැāļŠි ⎀ීāļ¸āļ§ āˇ„ේāļ­ු ⎀ිāļē ⎄ැāļšි āļ¯ුāļģ්⎀āļŊ āļąිāļģ්āļ¸ාāļĢ āļ­ේāļģීāļ¸් āļēෝāļĸāļąා āļšāļģāļēි. āļšේāļ­ āˇƒු⎀āļŗ āļšāļŊිāļą් ⎄āļŗුāļąා āļœැāļąීāļ¸ āˇƒāˇ„ āļ†āļ¸āļą්āļ­්‍āļģāļĢāļē āļšිāļģීāļ¸ āļšේāļ­ āļœුāļĢාāļ­්āļ¸āļšāļˇා⎀āļē ⎀ැāļŠි āļ¯ිāļēුāļĢු āļšāļģāļą āļ…āļ­āļģ āļ¯ිāļœුāļšාāļŊීāļą āˇ€්‍āļēාāļ´ෘāļ­ි ⎃ාāļģ්āļŽāļšāļ­්⎀āļē āˇƒāˇ„āļ­ිāļš āļšāļģāļēි.

-

āļ¸ෙāļ¸ āļŊිāļ´ිāļē Code smells āļēāļąු āļšුāļ¸āļš්āļ¯ැāļēි āļ´ැ⎄ැāļ¯ිāļŊි āļšāļģāļēි, āļ‹āļ¯ා⎄āļģāļĢ āˇƒāļ´āļēāļēි, āˇƒāˇ„ ⎃ාāļ¸ාāļą්‍āļē āļš්‍āļģāļ¸āļŊේāļ›āļąāļēේāļ¯ී āˇƒāˇ„ Arduino ⎃ං⎀āļģ්āļ°āļąāļēේāļ¯ී āļ’⎀ා ⎀⎅āļš්⎀ා āļœැāļąීāļ¸āļ§ āļ‹āļ´āļ¯ෙ⎃් āļŊāļļා āļ¯ෙāļēි.
-
Code smells
āļēāļąු āļšුāļ¸āļš්āļ¯?

Code smells āļēāļąු āļ”āļļේ āļšේāļ­āļē ⎃ැāļŊ⎃ුāļ¸් āļšිāļģීāļ¸ේāļ¯ී ⎄ෝ āļš්‍āļģිāļēාāļ­්āļ¸āļš āļšිāļģීāļ¸ේāļ¯ී āļēāļ¸් ⎀ැāļģැāļ¯්āļ¯āļš් ⎃ිāļ¯ු⎀ිāļē ⎄ැāļšි āļļ⎀āļ§ āļŊāļšුāļĢāļšි. āļ¸ෙāļ¸ āļœැāļ§āˇ…ු āļšේāļ­āļē āļ­ේāļģුāļ¸් āļœැāļąීāļ¸āļ§, āļ¯ිāļœු āļšිāļģීāļ¸āļ§ āˇ„ෝ āļ¯ෝ⎂⎄āļģāļĢāļē āļšිāļģීāļ¸āļ§ āļ…āļ´āˇ„āˇƒු āļšāļģāļēි. āļ¯ුāļģ්⎀āļŊ ⎃ැāļŊ⎃ුāļ¸් āļšිāļģීāļ¸, āļšāļŠිāļąāļ¸් ⎃ං⎀āļģ්āļ°āļąāļē ⎄ෝ āļšේāļ­āļąāļē āļšිāļģීāļ¸ේ ⎄ොāļŗāļ¸ āļ´ි⎅ි⎀ෙāļ­් āļ´ි⎅ිāļ´ැāļ¯ීāļ¸ āļąොāļ¸ැāļ­ිāļšāļ¸ āļ´ොāļ¯ු ⎄ේāļ­ු āļ…āļ­āļģ ⎀ේ.
-
āļ´ොāļ¯ු Code smells āˇƒāˇ„ āļ‹āļ¯ා⎄āļģāļĢ

1. āļ¯ිāļœු ⎁්‍āļģිāļ­

Smell: āļ…āļ°ිāļš āļŊෙ⎃ āļ¯ිāļœු ⎁්‍āļģිāļ­ āļ­ේāļģුāļ¸් āļœැāļąීāļ¸āļ§ āˇƒāˇ„ āļ¯ෝ⎂⎄āļģāļĢāļē āļšිāļģීāļ¸āļ§ āļ…āļ´āˇ„āˇƒු ⎀ේ.

āļ‹āļ¯ා⎄āļģāļĢāļē:
void handleSensorAndDisplayData() {

  // Read sensor

  // Process data

  // Update display

  // Handle errors

  // Log data

  // Send over network

}
-
⎀ි⎃āļŗුāļ¸: ⎁්‍āļģිāļ­āļē āļšුāļŠා, āļąාāļˇිāļœāļ­ āˇ්‍āļģිāļ­āˇ€āļŊāļ§ āļšāļŠා āļ¯āļ¸āļą්āļą.
-
void handleSensorAndDisplayData() {

  readSensor();

  processData();

  updateDisplay();

}
-
2.
āļ…āļąුāļ´ිāļ§āļ´āļ­් āļšේāļ­āļē

Smell: āļ‘āļšāļ¸ āļšේāļ­āļē ⎃්āļŽාāļą āļšි⎄ිāļ´āļēāļš āļ´ිāļ§āļ´āļ­් āļšāļģ āļ‡āļŊ⎀ීāļ¸ āļąāļŠāļ­්āļ­ු āļļāļģ ⎀ැāļŠි āļšāļģāļēි.

āļ‹āļ¯ා⎄āļģāļĢāļē:
if (sensorValue > 100) {

  digitalWrite(ledPin, HIGH);

} else {

  digitalWrite(ledPin, LOW);

}

 

if (buttonState == HIGH) {

  digitalWrite(ledPin, HIGH);

} else {

  digitalWrite(ledPin, LOW);

}
-
3.
āļ…āļ¯āˇ„āˇƒ් āļ•āļąෑ⎀āļ§ āˇ€āļŠා

Smell: āļ…āļ¯āˇ„āˇƒ් āļ•āļąෑ⎀āļ§ āˇ€āļŠා āļ…⎀⎁්‍āļē āļšāļģāļą āļšේāļ­āļē ⎃්⎀āļēං āļ´ැ⎄ැāļ¯ිāļŊි āļšිāļģීāļ¸āļš් āļąො⎀ිāļē ⎄ැāļšිāļē.

āļ‹āļ¯ා⎄āļģāļĢāļē:
// Turn on the LED

digitalWrite(ledPin, HIGH); 

// Wait for 1000ms

delay(1000); 

// Turn off the LED

digitalWrite(ledPin, LOW);
-
⎀ි⎃āļŗුāļ¸: āļ…āļ¯āˇ„āˇƒ් āļ¯ැāļš්⎀ීāļ¸ේ āļ…⎀⎁්‍āļēāļ­ා⎀āļē āļ…āļŠු āļšිāļģීāļ¸ āˇƒāļŗāˇ„ා āļ´ැ⎄ැāļ¯ිāļŊි, āļ…āļģ්āļŽāˇ€āļ­් ⎀ිāļ āļŊ්‍āļē āˇƒāˇ„ ⎁්‍āļģිāļ­ āļąāļ¸් āļˇා⎀ිāļ­ා āļšāļģāļą්āļą.
-
turnOnLED();

delay(1000);

turnOffLED();
-
4. āļ¯ෘāļĒ-āļšේāļ­āļœāļ­ āļ…āļœāļēāļą්

Smell: āļšේāļ­āļē āļ­ු⎅ āļšෙāļŊිāļą්āļ¸ āļ¸ැāļĸිāļš් āļ…ංāļš āˇ„ෝ āļąූāļŊ් āļˇා⎀ිāļ­ා āļšිāļģීāļ¸ āļ‘āļē āļ…āļŠු āļąāļ¸්‍āļē⎁ීāļŊී āļšāļģāļēි.

āļ‹āļ¯ා⎄āļģāļĢāļē:
if (temperature > 37.5) { 

  alert(); 

}
-
⎀ි⎃āļŗුāļ¸: āļ´ැ⎄ැāļ¯ිāļŊි āļļ⎀ āˇƒāˇ„ āļąāļŠāļ­්āļ­ු āļšිāļģීāļ¸ේ ⎄ැāļšිāļēා⎀ ⎃āļŗāˇ„ා āļąිāļēāļ­āļēāļą් ⎄ෝ ⎀ිāļ āļŊ්‍āļēāļēāļą් āļˇා⎀ිāļ­ා āļšāļģāļą්āļą.
-
const float feverThreshold = 37.5; 

if (temperature > feverThreshold) { 

  alert(); 

}
-
5. ⎀ි⎁ාāļŊ āļ´āļą්āļ­ි(Classes)

Smell: āļ•āļąෑ⎀āļ§ āˇ€āļŠා ⎀āļœāļšීāļ¸් āļ‡āļ­ි āļ´āļą්āļ­ි āļ­āļąි ⎀āļœāļšීāļ¸් āļ¸ූāļŊāļ°āļģ්āļ¸āļē (SRP) āļ‹āļŊ්āļŊංāļāļąāļē āļšāļģāļēි.

āļ‹āļ¯ා⎄āļģāļĢāļē:
class SmartHome {

  void controlLights();

  void controlThermostat();

  void monitorSecurity();

  void manageSchedules();

}
-
⎀ි⎃āļŗුāļ¸: āļšුāļŠා, āļ…āļģāļ¸ුāļĢු-āļąි⎁්āļ ිāļ­ āļ´āļą්āļ­ි⎀āļŊāļ§ āļļෙāļ¯āļą්āļą.
class LightController {};

class ThermostatController {};

class SecurityMonitor {};

class ScheduleManager {};
-
6. āļ…āļ°ිāļš If-Else āļ¯ාāļ¸

Smell: if-else ⎄ෝ switch āļ´්‍āļģāļšා⎁āļąāˇ€āļŊ āļ¯ිāļœු āļ¯ාāļ¸āļēāļą් āļšේāļ­āļē āļ…āļąුāļœāļ¸āļąāļē āļšිāļģීāļ¸ āļ¯ු⎂්āļšāļģ āļšāļģāļēි.

āļ‹āļ¯ා⎄āļģāļĢāļē:
if (command == "start") startMotor();

else if (command == "stop") stopMotor();

else if (command == "pause") pauseMotor();

else if (command == "resume") resumeMotor();
-
⎀ි⎃āļŗුāļ¸: ⎁්‍āļģිāļ­ āļ¯āļģ්⎁āļš āˇ„ෝ ⎁āļļ්āļ¯āļšෝ⎂āļēāļš් ⎀ැāļąි ⎃ිāļ­ිāļēāļ¸්āļšāļģāļĢ āļ´්‍āļģ⎀ේ⎁āļēāļš් āļˇා⎀ිāļ­ා āļšāļģāļą්āļą.
-
typedef void (*CommandFunc)();

std::map<String, CommandFunc> commands = {

  {"start", startMotor},

  {"stop", stopMotor},

  {"pause", pauseMotor},

  {"resume", resumeMotor}

};

commands[command]();
-
7.
āļ…āļ°ිāļš āˇƒංāļšීāļģ්āļĢ āļ­āļģ්āļšāļąāļē

Smell: ⎃ංāļšීāļģ්āļĢ, āļšැāļ¯ැāļŊි āļ­āļģ්āļšāļąāļē āļšිāļē⎀ීāļ¸āļ§ āˇƒāˇ„ āļ¯ෝ⎂⎄āļģāļĢāļē āļšිāļģීāļ¸āļ§ āļ…āļ´āˇ„āˇƒු ⎀ිāļē ⎄ැāļšිāļē.

āļ‹āļ¯ා⎄āļģāļĢāļē:
if ((temp > 30 && humidity < 40) || (rainDetected && windSpeed > 20)) {

  takeAction();

}
-
⎀ි⎃āļŗුāļ¸: āļšොāļą්āļ¯ේ⎃ි ⎃āļģāļŊ āļšිāļģීāļ¸ āˇƒāļŗāˇ„ා āļ‹āļ´āļšාāļģāļš āˇ්‍āļģිāļ­ āļˇා⎀ිāļ­ා āļšāļģāļą්āļą.
-
if (isHotAndDry() || isStormy()) {

  takeAction();

}
-
Code Smells ⎀⎅āļš්⎀ා āļœāļą්āļąේ āļšෙ⎃ේāļ¯?

āļ”āļļේ āļšේāļ­āļē ⎃ැāļŊ⎃ුāļ¸් āļšāļģāļą්āļą: āļŊි⎀ීāļ¸āļ§ āļ´ෙāļģ āļąිāļģ්āļ¸ාāļĢāļē āļšිāļģීāļ¸āļ§ āļšාāļŊāļē āļœāļ­ āļšāļģāļą්āļą. ⎀ි⎁ාāļŊ āļšාāļģ්āļēāļēāļą් āļšුāļŠා, āļšāˇ…āļ¸āļąාāļšāļģāļĢāļē āļšāˇ… ⎄ැāļšි ⎃ංāļģāļ āļš āˇ€āļŊāļ§ āļļෙāļ¯āļą්āļą.

⎄ොāļŗāļ¸ āļ´ි⎅ි⎀ෙāļ­් āļ…āļąුāļœāļ¸āļąāļē āļšāļģāļą්āļą: DRY (āļ”āļļāļ¸ āļąැ⎀āļ­ āļąොāļšāļģāļą්āļą) āˇƒāˇ„ SRP (āļ­āļąි ⎀āļœāļšීāļ¸් āļ¸ූāļŊāļ°āļģ්āļ¸āļē) ⎀ැāļąි āļ¸ූāļŊāļ°āļģ්āļ¸āˇ€āļŊāļ§ āļ‡āļŊී ⎃ිāļ§ිāļą්āļą.

āļąිāļ­ිāļ´āļ­ා āļ´්‍āļģāļ­ිāļąිāļģ්āļ¸ාāļĢāļē āļšāļģāļą්āļą: āļ­āļģ්āļšāļąāļē ⎃āļģāļŊ āļšිāļģීāļ¸ෙāļą් āˇƒāˇ„ āļ…āļ­ිāļģිāļš්āļ­ āļšොāļ§āˇƒ් āļ‰āˇ€āļ­් āļšිāļģීāļ¸ෙāļą් āļšේāļ­āļē āļ…āļ›āļĢ්āļŠāˇ€ ⎀ැāļŠි āļ¯ිāļēුāļĢු āļšāļģāļą්āļą.

⎃්⎀āļēං āļ´ැ⎄ැāļ¯ිāļŊි āļšිāļģීāļ¸ේ āļšේāļ­āļē āļŊිāļēāļą්āļą: āļšේāļ­āļē āļļුāļ¯්āļ°ිāļ¸āļē āļšිāļģීāļ¸āļ§ āˇ€ි⎃්āļ­āļģාāļ­්āļ¸āļš āˇ€ිāļ āļŊ්‍āļē āˇƒāˇ„ ⎁්‍āļģිāļ­ āļąāļ¸් āļˇා⎀ිāļ­ා āļšāļģāļą්āļą.

āļ‹āļ­්āļ­ෝāļŊāļą āļ¸ෙ⎀āļŊāļ¸්: code smell ⎃්⎀āļēංāļš්‍āļģීāļē⎀ ⎄āļŗුāļąා āļœැāļąීāļ¸āļ§ Lint āˇƒāˇ„ ⎃්āļŽිāļ­ිāļš āˇ€ි⎁්āļŊේ⎂āļĢ āļ¸ෙ⎀āļŊāļ¸් āļˇා⎀ිāļ­ා āļšāļģāļą්āļą.
-
āļąිāļœāļ¸āļąāļē

āļ´ිāļģි⎃ිāļ¯ු, āļąāļŠāļ­්āļ­ු āļšāˇ… ⎄ැāļšි āˇƒāˇ„ āļ´āļģිāļ¸ාāļĢāļē āļšāˇ… ⎄ැāļšි āļšේāļ­āļēāļš් āļŊි⎀ීāļ¸ āˇƒāļŗāˇ„ා code smells ⎄āļŗුāļąා āļœැāļąීāļ¸ āˇƒāˇ„ āļ†āļ¸āļą්āļ­්‍āļģāļĢāļē āļšිāļģීāļ¸ āļ‰āļ­ා ⎀ැāļ¯āļœāļ­් ⎀ේ. āļ”āļļේ āļšේāļ­āļē āļąිāļ­ිāļ´āļ­ා ⎃āļ¸ාāļŊෝāļ āļąāļē āļšිāļģීāļ¸ෙāļą්, āļąැ⎀āļ­ āˇƒāļšāˇƒ් āļšිāļģීāļ¸ෙāļą් āˇƒāˇ„ āļšේāļ­ීāļšāļģāļĢ āļ¸ූāļŊāļ°āļģ්āļ¸āˇ€āļŊāļ§ āļ…āļąුāļœāļ­ āˇ€ීāļ¸ෙāļą්, āļ”āļļāļ§ āļœැāļ§āˇ…ු ⎀⎅āļš්⎀ා āļœāļ­ āˇ„ැāļšි āļ…āļ­āļģ āļ”āļļේ ⎀්‍āļēාāļ´ෘāļ­ි ⎁āļš්āļ­ිāļ¸āļ­් āˇƒāˇ„ āļ…āļąාāļœāļ­āļēāļ§ āļ”āļģොāļ­්āļ­ු āļ¯ෙāļą āļļ⎀ āˇƒāˇ„āļ­ිāļš āļšāˇ… ⎄ැāļšිāļē.
-
āļ­ාāļ¸āļ­් āļ…āļ´ේ group āļ‘āļšේ āļąැāļ­්āļ­āļą් group āļ‘āļšāļ§ āˇƒෙāļ§් ⎀ෙāļą්āļą :⁣

https://www.facebook.com/groups/paperclipx

āļ¸ේ group āļ‘āļšේ āļ¯ාāļą āļ¯ේ⎀āļŊ් ⎄ොāļŗāļēි āļšිāļēāļŊ ⎄ිāļ­ෙāļąāˇ€āļąāļ¸් āļ•āļœොāļŊ්āļŊොāļą් āļœේ āļēාāļŊු⎀āļą්⎀āļ­් group āļ‘āļšāļ§ āļ‘āļšāļ­ු āļšāļģāļą්āļą !⁣