<?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: Riyan Dhiman</title>
    <description>The latest articles on DEV Community by Riyan Dhiman (@ryand1234).</description>
    <link>https://dev.to/ryand1234</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1071243%2Fc054e2d3-44f5-4620-96db-9a8021e22cba.jpeg</url>
      <title>DEV Community: Riyan Dhiman</title>
      <link>https://dev.to/ryand1234</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ryand1234"/>
    <language>en</language>
    <item>
      <title>I watched what Claude Code does when you're not looking</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Mon, 30 Mar 2026 08:11:05 +0000</pubDate>
      <link>https://dev.to/ryand1234/i-watched-what-claude-code-does-when-youre-not-looking-2e0m</link>
      <guid>https://dev.to/ryand1234/i-watched-what-claude-code-does-when-youre-not-looking-2e0m</guid>
      <description>&lt;p&gt;I ran my AI coding agent in observe mode for a week. No blocking, no restrictions, just logging every action it took. What I found changed how I think about agent access.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I wrote a small tool that hooks into Claude Code's pre-execution layer. It logs every tool call, bash command, file read, and web request to an audit database without interfering with anything. The agent doesn't know it's being watched. Nothing gets blocked.&lt;/p&gt;

&lt;p&gt;I turned it on and kept coding normally for a week. Then I looked at the logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude did without being asked
&lt;/h2&gt;

&lt;p&gt;In a normal coding session, Claude doesn't just do what you tell it. It explores. It reads files to understand context. It runs commands to check state. Most of this is helpful. Some of it is not what you'd expect.&lt;/p&gt;

&lt;p&gt;In one session I asked it to help push a package to PyPI. It grabbed my .env file on its own to find the token. Made sense from its perspective, it needed the credential to complete the task. But now my PyPI token was sitting in the conversation context. If that had been a Stripe secret key or a database URL, same thing would have happened.&lt;/p&gt;

&lt;p&gt;Across a week of sessions, the analysis flagged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple reads to .env and credential files I never asked it to touch&lt;/li&gt;
&lt;li&gt;Shell commands I didn't prompt for, mostly harmless but some touching git config and system paths&lt;/li&gt;
&lt;li&gt;File access outside the project directory&lt;/li&gt;
&lt;li&gt;A pattern where it read a sensitive file and then made an external web request within the same session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is the one that stuck with me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern nobody talks about
&lt;/h2&gt;

&lt;p&gt;Most agent security discussions focus on blocking single actions. Don't let it run rm. Don't let it read .env. That's useful but it misses something.&lt;/p&gt;

&lt;p&gt;The real risk isn't a single action. It's a sequence. Your agent reads a credential file. Two minutes later it makes an external HTTP request. Each action on its own looks fine. Together they form an exfiltration chain.&lt;/p&gt;

&lt;p&gt;I started calling these cross-layer threats. A file read is one layer (what the agent can see). A web request is another (what the agent sends out). Individually they pass any policy. Combined within a time window, they're a problem.&lt;/p&gt;

&lt;p&gt;When I added sequence detection to the analysis, sessions that looked clean on a per-action basis suddenly had findings. Not because any single action was malicious, but because the chain of actions told a different story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 layers of agent security
&lt;/h2&gt;

&lt;p&gt;After digging into this, I started thinking about agent security as 5 distinct layers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1: What the agent can DO.&lt;/strong&gt; Destructive commands like rm, DROP TABLE, git reset --hard, force push. This is where most tools focus. It's the obvious stuff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2: What the agent can SEE.&lt;/strong&gt; Your .env, SSH keys, AWS credentials, service account files. Even if the agent doesn't do anything destructive, the fact that it read your secrets means those secrets are now in the model's context window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3: What the agent SENDS OUT.&lt;/strong&gt; Web requests, API calls, anything that leaves your machine. If the agent read a credential and then makes an outbound request, that's a potential exfiltration path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 4: What the agent REMEMBERS.&lt;/strong&gt; Context poisoning and memory injection. Research shows 87% of downstream decisions get compromised within 4 hours of memory poisoning. This one is mostly unsolved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 5: MCP supply chain.&lt;/strong&gt; Malicious MCP servers, tool poisoning. A recent audit found 71% of MCP servers scored F on security. Including Anthropic's own reference implementations.&lt;/p&gt;

&lt;p&gt;Most agent security tools cover layer 1. Some partially cover layer 2. Nobody covers layer 3. Layers 4 and 5 are wide open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why observing matters more than blocking
&lt;/h2&gt;

&lt;p&gt;Most developers won't install a security tool because they think they need one. They'll install it because they're curious. Observation has zero friction. It doesn't change your workflow. It doesn't block anything. It just shows you what's happening.&lt;/p&gt;

&lt;p&gt;Once you see the logs, you don't need convincing that guardrails are needed. You ask for them.&lt;/p&gt;

&lt;p&gt;The scary part isn't what gets blocked. It's what you see in the logs that you never knew was happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm doing about it
&lt;/h2&gt;

&lt;p&gt;I've been building a tool around this idea. It started as a simple policy engine for blocking dangerous actions but the observe and analyze workflow turned out to be more valuable than the blocking itself. It works with Claude Code, Codex, Cursor, and a few other agents.&lt;/p&gt;

&lt;p&gt;It's open source and still early but I've been running it on my own workflow daily.&lt;/p&gt;

&lt;p&gt;If you're curious: &lt;a href="https://github.com/riyandhiman14/Agent-Sec" rel="noopener noreferrer"&gt;https://github.com/riyandhiman14/Agent-Sec&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear if anyone else has noticed similar patterns with their agents.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built an IAM-style firewall for AI agents after Claude read my .env</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Sat, 28 Mar 2026 16:44:22 +0000</pubDate>
      <link>https://dev.to/ryand1234/i-built-an-iam-style-firewall-for-ai-agents-after-claude-read-my-env-30e1</link>
      <guid>https://dev.to/ryand1234/i-built-an-iam-style-firewall-for-ai-agents-after-claude-read-my-env-30e1</guid>
      <description>&lt;p&gt;I've been using Claude Code to build stuff for a while now. It's fast, it writes decent code, and it saves me hours. But a few days ago I had a moment that made me stop and think.&lt;/p&gt;

&lt;p&gt;The moment that got me was when Claude grabbed my .env file on its own while trying to push a package. PyPI token sitting right there in the chat. No warning, no confirmation, nothing. If that was my Stripe key or a database URL it would have been the same story.&lt;/p&gt;

&lt;p&gt;And that's the problem. These AI agents have real access to your filesystem, your shell, your git history, your secrets. They don't have bad intentions, they just don't have boundaries. If you ask it to rm -rf something, it will. If you ask it to force push to main, it will. If it decides the fastest path to completing a task involves reading a credentials file, it's going to read it.&lt;/p&gt;

&lt;p&gt;So I built agsec.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;agsec is a policy engine that sits between the AI agent and your system. Before the agent can do anything (run a command, read a file, make a web request), the action gets checked against your policies. If the policy says no, the action doesn't happen. The agent doesn't get a say.&lt;/p&gt;

&lt;p&gt;Think of it like AWS IAM but for AI agents. You write declarative YAML policies that define what's allowed, what's blocked, and what needs a human to sign off on.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent wants to act  --&amp;gt;  agsec evaluates policy  --&amp;gt;  allow / block / review  --&amp;gt;  real world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The enforcement happens at the hook level. Most AI coding agents (Claude Code, Codex, Cursor, etc.) support pre-execution hooks that fire before any tool call. agsec plugs into these hooks. The agent can't reason its way around it or write a script to bypass the check. The action simply doesn't execute unless the policy allows it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a policy looks like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0"&lt;/span&gt;
&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deny&lt;/span&gt;

&lt;span class="na"&gt;statements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;sid&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AllowReadOps"&lt;/span&gt;
    &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;allow&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.read"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.glob"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.grep"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;sid&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BlockFileDelete"&lt;/span&gt;
    &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deny&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bash.execute"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;conditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;params.command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;regex"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;brm&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;s"&lt;/span&gt;
    &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agents&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;should&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;delete&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;files"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;sid&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BlockEnvAccess"&lt;/span&gt;
    &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deny&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.read"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;conditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;params.file_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;regex"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;.env$"&lt;/span&gt;
    &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Block&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;access&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;environment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;files"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;sid&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AllowBash"&lt;/span&gt;
    &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;allow&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bash.execute"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deny always wins over allow. Same precedence as AWS IAM. If you've ever written an IAM policy, this will feel familiar.&lt;/p&gt;

&lt;p&gt;You can match on action types (bash.execute, file.read, file.write, web.fetch), use regex and glob patterns on parameters, and set conditions with 12+ operators (equals, contains, regex, greater than, starts_with, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agsec
agsec init                     &lt;span class="c"&gt;# creates default policies&lt;/span&gt;
agsec &lt;span class="nb"&gt;install &lt;/span&gt;claude-code      &lt;span class="c"&gt;# activates the firewall&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Three commands and every tool call is now checked. rm blocked, .env access blocked, force push blocked, all out of the box.&lt;/p&gt;

&lt;p&gt;The default policies cover the obvious stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;01_base.yaml: default deny, allow read operations&lt;/li&gt;
&lt;li&gt;02_bash.yaml: block rm, DROP TABLE, secret access, data exfiltration&lt;/li&gt;
&lt;li&gt;03_files.yaml: block writes to .env, credentials.json, system dirs&lt;/li&gt;
&lt;li&gt;04_web.yaml: review external HTTP requests&lt;/li&gt;
&lt;li&gt;05_git.yaml: block force push, hard resets, protected branches&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Observe mode
&lt;/h2&gt;

&lt;p&gt;If you're not ready to start blocking things, you can run in observe mode first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agsec init &lt;span class="nt"&gt;--observe&lt;/span&gt;           &lt;span class="c"&gt;# log only, no blocking&lt;/span&gt;
agsec audit &lt;span class="nt"&gt;--stats&lt;/span&gt;            &lt;span class="c"&gt;# see what would have been blocked&lt;/span&gt;
agsec enforce                  &lt;span class="c"&gt;# start blocking when ready&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you see what your agent is actually doing before you put any guardrails in place. The audit trail alone is worth it. You'll be surprised how many things the agent does that you never explicitly asked for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What platforms it supports
&lt;/h2&gt;

&lt;p&gt;Right now it works with Claude Code, Codex, Cursor, Windsurf, Cline, and GitHub Copilot. Claude Code is fully tested, the others are functional but could use more community testing.&lt;/p&gt;

&lt;p&gt;It also has Python SDK integrations for LangChain, OpenAI, and Anthropic clients if you're building agent workflows in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just use the agent's built-in restrictions?
&lt;/h2&gt;

&lt;p&gt;Most agents have some form of deny rules or permission settings. The problem is these are usually stored in project config files that the agent itself can modify. And they're typically simple string matching without conditions or precedence logic.&lt;/p&gt;

&lt;p&gt;agsec policies live outside the agent's reach. The evaluation is done externally before the action runs. The agent can't edit the policy, can't skip the check, and can't convince itself that an exception is warranted.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I'm actively working on a web UI for policy management, better audit dashboards, and more platform integrations. The core policy engine is solid and I'm using it daily on my own workflow.&lt;/p&gt;

&lt;p&gt;If you're using AI agents for real work and you've ever had that "wait what did it just do" moment, give it a try. Or just run it in observe mode and look at the audit logs. That alone might change how you think about agent access.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/riyandhiman14/Agent-Sec" rel="noopener noreferrer"&gt;https://github.com/riyandhiman14/Agent-Sec&lt;/a&gt;&lt;br&gt;
PyPI: &lt;a href="https://pypi.org/project/agsec/" rel="noopener noreferrer"&gt;https://pypi.org/project/agsec/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love feedback, especially edge cases and bypass attempts. That's how this gets better.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Crafting Clear Code: A Beginner’s Guide to Writing Neat and Understandable Code</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Wed, 31 Jan 2024 05:45:07 +0000</pubDate>
      <link>https://dev.to/ryand1234/crafting-clear-code-a-beginners-guide-to-writing-neat-and-understandable-code-1co6</link>
      <guid>https://dev.to/ryand1234/crafting-clear-code-a-beginners-guide-to-writing-neat-and-understandable-code-1co6</guid>
      <description>&lt;p&gt;Hey there, fellow code enthusiasts! Today, I want to talk to you about something that’s often overlooked but incredibly crucial in the world of programming—writing clean code. Now, I know the term might sound a bit intimidating, but fear not! I’m here to guide you through the basics of clean code in a way that’s easy to understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand the Importance of Clean Code:&lt;/strong&gt;&lt;br&gt;
Imagine walking into a room with everything scattered around—books, clothes, and gadgets all over the place. It’s chaotic and confusing, right? Well, the same goes for code. Clean code is like having a well-organized room—it makes your work more manageable, understandable, and less prone to errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meaningful names matter:&lt;/strong&gt;&lt;br&gt;
Just like calling your pet dog by its actual name makes communication easier, giving your variables and functions meaningful names is key. Instead of using cryptic abbreviations, opt for descriptive names that convey the purpose of the variable or function. This simple practice makes your code self-explanatory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep It Short and Sweet:&lt;/strong&gt;&lt;br&gt;
Have you ever received a text that seemed to go on forever without getting to the point? Code can be like that too. Break down your code into smaller, logically organized functions. Each function should have a specific job, making your code more readable and easier to troubleshoot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comments—Use Wisely:&lt;/strong&gt;&lt;br&gt;
Imagine reading a book where every sentence had a footnote explaining it. Annoying, right? Similarly, while comments are helpful, they should clarify the why, not the what. Write comments sparingly and focus on explaining the reasoning behind certain choices in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency is key:&lt;/strong&gt;&lt;br&gt;
Just like having a consistent bedtime routine helps you sleep better, maintaining consistency in your code makes it more predictable. Stick to a consistent coding style, indentation, and naming conventions throughout your project. This makes collaboration smoother and your codebase more harmonious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DRY—Don't Repeat Yourself:&lt;/strong&gt;&lt;br&gt;
If you find yourself copying and pasting code, it’s time to take a step back. Duplicating code not only increases the chances of errors but also makes your codebase harder to maintain. Create reusable functions or classes instead, following the golden rule of DRY—Don't Repeat Yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
So there you have it—the basics of writing clean code. Think of coding as telling a story; make it engaging, easy to follow, and enjoyable. By incorporating these simple practices into your coding routine, you’ll not only become a better programmer but also make the coding experience more pleasant for everyone involved. Happy coding!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>designpatterns</category>
      <category>learning</category>
    </item>
    <item>
      <title>REST vs gRPC: A Comparison</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Tue, 30 Jan 2024 07:52:23 +0000</pubDate>
      <link>https://dev.to/ryand1234/rest-vs-grpc-a-comparison-3fg3</link>
      <guid>https://dev.to/ryand1234/rest-vs-grpc-a-comparison-3fg3</guid>
      <description>&lt;p&gt;When it comes to designing and implementing APIs (Application programming Interfaces), developers often face the choice between REST (Representational State Transfer) and gRPC (gRPC Remote Procedure Call). Both are widely used in the software industry for building distributed systems, but they differ in terms of architecture, communication style, and features. In this article, I will explore the key differences between REST and gRPC to help you make an informed decision based on your project requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST (Representational State Transfer)
&lt;/h2&gt;

&lt;p&gt;REST is like sending letters. Each time you want something, you write a letter (request) to the other person (server). The letter contains all the information needed, and they send you a reply. Here are the key points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Letters are Independent&lt;/strong&gt;: Each letter is separate and doesn't rely on previous ones. This makes it simple and easy to manage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Language&lt;/strong&gt;: Everyone uses the same language (HTTP methods like GET, POST, etc.). It's like having a common way to write letters so that everyone understands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy to Read&lt;/strong&gt;: The address on the envelope (URL) is human-readable, like an address in your neighborhood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexible&lt;/strong&gt;: You can use different types of mail services (protocols) like regular mail, email, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  gRPC (gRPC Remote Procedure Call)
&lt;/h2&gt;

&lt;p&gt;gRPC is like making a phone call. You and the other person can talk back and forth more efficiently. Here are the key points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Conversations&lt;/strong&gt;: Instead of sending letters, you have a live conversation. You can ask and answer questions without writing and waiting for letters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Special Language&lt;/strong&gt;: You both speak a specific language (Protocol Buffers). It's like having a secret code that makes communication faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clear Instructions&lt;/strong&gt;: You provide specific instructions, and the other person follows them. This reduces misunderstandings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automatic Translator&lt;/strong&gt;: There's a tool that translates your words into the language the other person understands (automatic code generation).&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing Between Them
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose REST if&lt;/strong&gt;: You want a simple way of communicating, like sending letters. It's widely used, and everyone understands it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose gRPC&lt;/strong&gt; if: You need a faster and more direct conversation. It's like talking on the phone – quick and to the point. If you like having clear instructions and automatic translation, gRPC is a good choice.&lt;/p&gt;

&lt;p&gt;In the end, it's like choosing between sending letters (REST) or having a quick phone call (gRPC). Both work well, but the best choice depends on how you prefer to communicate.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Fast Track to Efficient Data Retrieval: Mastering Key Strategies in Software Engineering</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Sat, 13 Jan 2024 07:52:46 +0000</pubDate>
      <link>https://dev.to/ryand1234/fast-track-to-efficient-data-retrieval-mastering-key-strategies-in-software-engineering-2e03</link>
      <guid>https://dev.to/ryand1234/fast-track-to-efficient-data-retrieval-mastering-key-strategies-in-software-engineering-2e03</guid>
      <description>&lt;p&gt;Data retrieval is a crucial step in software engineering. The speed at which we can access data significantly impacts the quality of our product. In today's fast-paced world, even a millisecond optimization in data retrieval can lead to substantial cost savings. Let's explore some commonly used techniques to optimize data retrieval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indexing
&lt;/h3&gt;

&lt;p&gt;Indexing is a fundamental technique in which we create indexes on frequently used columns. The index kind of acts as a pathway that improves query retrieval speed at the cost of write time. We can create a composite index if there are multiple columns for indexes. We should carefully analyze the query and usage pattern and decide on our indexes to improve the overall data retrieval time. We should also not blindly use any index because creating indexes increases write query time, so we should carefully select the indexes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Denormalization
&lt;/h3&gt;

&lt;p&gt;While creating a database schema, we are often advised to normalize our data. However, excessive normalization can sometimes impact our data retrieval time. The process of removing normalization and introducing redundancy in the database schema for faster retrieval is called denormalization. Denormalization reduces the number of joins in our queries, which significantly improves data retrieval time. Like any technique, it has its drawbacks. Denormalization can complicate updates and introduce data inconsistency. It's crucial to carefully assess the specific needs of your application before opting for denormalization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table View
&lt;/h3&gt;

&lt;p&gt;Sometimes, we can't denormalize our database for various reasons, and the increasing number of joins is affecting our read time. In such cases, creating a view table for a specific query can be a solution. A view table is more like a temporary table that stores the data of the query. When retrieving data, we can directly use that view table, significantly improving read time compared to the query itself. Creating views for complex queries can be beneficial, especially when dealing with frequently used or intricate query patterns. Views encapsulate complex logic, making querying more straightforward for application developers. If we are using the view mechanism, it's crucial to update the view table regularly. If the view is not updated, users will see only old data, potentially impacting the business more than a delay in the query.&lt;/p&gt;

&lt;p&gt;The above techniques are not the only ones that can improve data retrieval. There are several additional strategies such as caching, database sharding, and more, each with its own merits and applications. In future articles, we will explore these techniques to provide you with a comprehensive understanding of optimizing data retrieval. Feel free to ask any question you have!!!&lt;/p&gt;

</description>
      <category>database</category>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Tips and tricks for optimizing Python code performance (Part 1)</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Mon, 08 May 2023 06:15:25 +0000</pubDate>
      <link>https://dev.to/ryand1234/tips-and-tricks-for-optimizing-python-code-performance-part-1-4hj6</link>
      <guid>https://dev.to/ryand1234/tips-and-tricks-for-optimizing-python-code-performance-part-1-4hj6</guid>
      <description>&lt;p&gt;Python is a robust programming language that boasts a multitude of applications. Nonetheless, as is the case with any programming language, it is essential to write efficient and performant code. With this in mind, here are several useful tips and tricks for optimizing Python code performance:&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching
&lt;/h2&gt;

&lt;p&gt;Caching is a method of storing commonly used information in memory to enable swift and easy access. In Python, there are several libraries available, including LRU cache, Redis, and Memcached, that offer a straightforward and adaptable approach to caching data in your code.&lt;/p&gt;

&lt;p&gt;Redis is a commonly utilized caching solution in Python applications. It serves as an in-memory data store that can cache regularly accessed data. Below is an instance of implementing Redis for caching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import redis

# Connect to Redis server
r = redis.Redis(host='localhost', port=6379, db=0)

def expensive_function(arg1, arg2):
    # Check if result is in cache
    cache_key = str(arg1) + ':' + str(arg2)
    cached_result = r.get(cache_key)
    if cached_result is not None:
        # If result is in cache, return it
        return int(cached_result)

    # If result is not in cache, perform expensive computation
    result = arg1 * arg2

    # Store result in cache for future use
    r.set(cache_key, result)
    return result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the present instance, the Redis library is employed to establish a connection with a Redis server operating on the same machine, specifically on port 6379. The function expensive_function (Can't think of some at the time of writing) conducts a computationally expensive operation based on the input arguments arg1 and arg2.&lt;/p&gt;

&lt;p&gt;Prior to executing the computation, the function first verifies whether the Redis cache already contains the result. This is achieved by constructing a cache key that is based on the input arguments. In the event that the result is present in the cache, it is retrieved instantly. If not, the function proceeds to perform the resource-intensive computation, and subsequently stores the result in the cache for future reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memoization
&lt;/h2&gt;

&lt;p&gt;Memoization is a technique that has become quite common to optimize the performance of functions by caching the output of previous computations, which is then retrieved when the same input occurs again. This technique can be particularly helpful for expensive function calls that are frequently repeated. Python has a built-in memoization library called functools, which can be used to apply memoization in your code with ease. With the assistance of functools, it's possible to cache the results of function calls promptly and enhance the performance of your code.&lt;/p&gt;

&lt;p&gt;Memcached is a caching system that distributes data across multiple servers and stores it in memory, providing efficient handling of large volumes of read and write requests with minimal latency. Memcached is commonly used in web applications to cache frequently accessed data, including database queries, API responses, and HTML templates, allowing for rapid retrieval and delivery of this information.&lt;/p&gt;

&lt;p&gt;To use memcached, you first need to install memcached library using pip&lt;br&gt;
&lt;code&gt;pip install pymemcache&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once pymemcache has been successfully installed, you can utilize the &lt;strong&gt;pymemcache.client&lt;/strong&gt; module of the library to efficiently cache results and enhance the performance of your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from pymemcache.client.base import Client
import time

# Connect to Memcached server
client = Client(('localhost', 11211))

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

&lt;/div&gt;



&lt;p&gt;In the code snippet provided, a client object has been instantiated to establish a connection with a Memcached server that is running on the local machine and listening on port 11211. Prior to running the code, it is necessary to install the Memcached server software and launch it on the system in order to execute the example code below.&lt;/p&gt;

&lt;p&gt;To demonstrate how memoization can optimize a recursive function, I have utilized the most fundamental example of all - the Fibonacci sequence. This sequence is comprised of numbers where each subsequent number is the sum of the two preceding numbers, starting from 0 and 1.&lt;/p&gt;

&lt;p&gt;I have developed two Fibonacci functions: the first is a conventional function that is widely available on the internet (expensive_fib), while the second is an optimized Fibonacci function(cached_fib) that leverages memcached to cache the output and enhance the performance of the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def expensive_fib(n):
    if n &amp;lt;= 1:
        return n
    return expensive_fib(n-1) + expensive_fib(n-2)

def cached_fib(n):
    # Retrieve data from Memcached
    key  = str(n)
    value = client.get(key)

    if value is not None:
        # if data is present in the cache, then return it
        return value
    cur_value = int(cached_fib(n-1)) + int(cached_fib(n-2))

    # Store data in Memcached
    client.set(key, cur_value)
    return cur_value

#initial value
client.set("1", 1)
client.set("0", 0)


start_time = time.time()
result = expensive_fib(50)
end_time = time.time()
execution_time = end_time - start_time
print("Execution time of expensive fib:", execution_time)

start_time = time.time()
result = cached_fib(50)
end_time = time.time()
execution_time = end_time - start_time
print("Execution time of cached fib:", execution_time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon execution of the preceding code, the resulting output is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykooz8xu5v4x05vz8vv0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykooz8xu5v4x05vz8vv0.png" alt="Cache code output" width="688" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generators
&lt;/h2&gt;

&lt;p&gt;Python generators offer the ability to generate large data sets on-the-fly, which can be more efficient in terms of memory usage than storing the entire data set in memory at once. The generator functions utilize the yield keyword to generate a sequence of values on-the-fly, in a similar manner to how a function generates values. Upon being invoked, the generator function returns a generator object that can be iterated through to produce each value in the sequence one-by-one. This method is ideal for generating sequences of values or conducting matrix operations while optimizing memory usage.&lt;/p&gt;

&lt;p&gt;To illustrate how a generator can enhance the efficiency of a mathematical sequence, consider the following example. Suppose you wished to generate the first 100,000 prime numbers. Rather than generating the entire sequence simultaneously, which would necessitate storing all 100,000 numbers in memory, you could utilize a generator function to generate each prime number sequentially, as needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def is_prime(n):
    if n &amp;lt;= 1:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

def primes(n):
    count = 0
    i = 2
    while count &amp;lt; n:
        if is_prime(i):
            yield i
            count += 1
        i += 1


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

&lt;/div&gt;



&lt;p&gt;In the aforementioned example, the function &lt;strong&gt;primes()&lt;/strong&gt; utilizes another function, &lt;strong&gt;is_prime()&lt;/strong&gt;, to ascertain if a number is a prime number or not. Upon confirmation of the primality of a number by &lt;strong&gt;is_prime()&lt;/strong&gt;, &lt;strong&gt;primes()&lt;/strong&gt; generates the number. By calling &lt;strong&gt;primes(100000)&lt;/strong&gt;, the generation of each prime number on-the-fly replaces the necessity of storing all 100,000 numbers in memory, which consequently eliminates the need for excessive memory usage.&lt;/p&gt;

&lt;p&gt;In the next post, I will discuss more performance optimization methods such as Cython, multithreading and multiprocessing&lt;/p&gt;

</description>
      <category>python</category>
      <category>performance</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Pros and cons of cloud computing</title>
      <dc:creator>Riyan Dhiman</dc:creator>
      <pubDate>Sun, 07 May 2023 12:45:37 +0000</pubDate>
      <link>https://dev.to/ryand1234/pros-and-cons-of-cloud-computing-27kj</link>
      <guid>https://dev.to/ryand1234/pros-and-cons-of-cloud-computing-27kj</guid>
      <description>&lt;p&gt;Cloud computing has transformed the landscape of data storage and processing by providing access to a shared pool of computing resources, such as servers, storage, applications, and services, through the internet. This technology enables businesses and individuals to operate on a larger scale without being constrained by local hardware and infrastructure, resulting in significant savings of both time and money.&lt;/p&gt;

&lt;p&gt;Before making a decision about adopting cloud computing, it is important for businesses to carefully consider both the advantages and disadvantages. In the following paragraphs, we will outline the potential benefits first, followed by the potential drawbacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cost savings: Did you know that cloud computing can be a real game-changer for businesses looking to save money? By using cloud services, companies can eliminate the need for expensive hardware and instead pay for the resources they need on-demand. This means that businesses don't have to worry about investing in and maintaining their own IT infrastructure, which can be a big relief.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability: Cloud computing is a game-changer for businesses as it offers the flexibility to easily adjust IT resources based on their ever-changing needs. This means businesses can swiftly adapt to market fluctuations or surges in demand during peak seasons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accessibility: Cloud computing allows employees to access applications and data effortlessly, regardless of their location, as long as they have an internet connection. As a result, remote or dispersed teams can collaborate more efficiently and increase productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reliability: With cloud computing, you can count on providers to be there for you when you need them most!. Cloud computing providers typically offer high levels of reliability and uptime, with redundant backups and failover systems to ensure continuity of service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cons:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Security risks: When it comes to cloud computing, it's important to keep security in mind. To ensure the safety of your business's data and applications, it's essential to work with a cloud provider that has strong security protocols in place. Additionally, taking your own security measures is crucial to safeguard your information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet dependency: Cloud computing is reliant on internet connectivity, which can be a potential point of concern. If a business experiences any disruptions to their internet connection, they may encounter downtime or other issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack of control: Cloud computing providers take care of the infrastructure, which can make it difficult for businesses to control their IT environment. Companies have to depend on their provider to manage maintenance and upgrades, which can limit their ability to customize their systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data ownership and portability: Data stored in the cloud can be subject to data privacy rules and businesses may face issues regarding data ownership and transferability. Companies should make sure they have the ability to access and transfer their data, especially if they decide to switch providers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we come to the end, it's essential for businesses to weigh the benefits and drawbacks of cloud computing before transitioning. With careful consideration of their specific needs and taking measures to minimize risks, businesses can enjoy the advantages of cloud computing while safeguarding the security and integrity of their data and applications.&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>devops</category>
      <category>beginners</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
