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

10. C# (Static Typing vs Dynamic Typing)

2026-02-08 06:33:34

0. The Real Goal of This Lesson

This lesson is not about deciding whether static typing is “better” or “worse”.

The real goal is this:

To understand when and why the C# compiler makes decisions on your behalf,
and what you gain—and give up—in return.

Once this clicks, method signatures, return types, and compiler errors stop feeling arbitrary.

1. How Humans Naturally Think About Types

Humans tend to think like this:

“I’m using a string now,
but later I might want to use a number.”

This way of thinking is completely natural.

Some languages allow this directly.

2. The Mental Model of Dynamically Typed Languages (Python Example)

x = "hello"
x = 10

Why this works:

  • The variable x has no fixed type
  • Its identity changes based on the value it holds

Mental model:

“What matters is what’s inside the variable right now.”

This is dynamic typing.

3. Why C# Refuses This

C# takes a different stance:

“This variable will have exactly one type for its entire lifetime.”

string x = "hello";
x = 10; // Compile-time error

This is static typing.

4. What Static Typing Actually Means

Static typing means:

The compiler rejects illogical reasoning
before the program is allowed to run.

Example:

string name = "Sabin";
int age = name; // Compile-time error

The compiler is effectively saying:

“This does not make sense.
Do not even try to execute it.”

This is a compile-time error, not a runtime failure.

5. Compile-Time Errors vs Runtime Errors

This distinction is critical.

Compile-time errors

  • The program does not start
  • Detected while writing code
  • Type mismatches, invalid syntax, contract violations

The compiler warns you early.

Runtime errors

  • The program starts
  • The failure happens during execution
  • Null references, unexpected values, invalid operations

These can crash the program in front of users.

The philosophy of static typing

“Fail as early as possible—
ideally before the program ever runs.”

6. Why Method Types Are So Strict

A method declaration is a contract.

static bool IsLong(string text)

This line promises:

  1. The method accepts a string
  2. The method returns a bool

Nothing more. Nothing less.

Contract violation example 1: wrong return type

static bool IsLong(string text)
{
    return "yes"; // Compile-time error
}

Compiler logic:

“You promised a boolean.
This is a string. Contract violated.”

Contract violation example 2: wrong assignment target

string result = IsLong("hello"); // Compile-time error

Reason:

  • IsLong returns bool
  • Assigning bool to string is invalid

Contract violation example 3: wrong argument type

IsLong(10); // Compile-time error

Compiler logic:

“This method expects a string.
A number does not fulfill the contract.”

7. Why This Feels Restrictive—but Isn’t

The inconvenience

  • Types must always match
  • Less room for improvisation

What you gain instead

  • Fewer runtime crashes
  • Strong guarantees in large codebases
  • Safer refactoring
  • More accurate IDE support (autocomplete, rename, refactor)

This is one reason C# is favored in large, long-lived systems.

8. Flexibility Wasn’t Removed—It Was Delayed

A common misunderstanding:

“Static typing means no flexibility.”
This is incorrect.

The truth:

C# postpones flexibility until it can be expressed safely.

Example concept (preview):

static void Feed(Animal animal)
  • Dog is allowed
  • Cat is allowed
  • Snake is allowed

This is polymorphism.

The pattern is always the same:

  1. Strict rules first
  2. Controlled flexibility later

9. Common Misunderstandings to Clear Up

Incorrect assumptions

  • “Using var makes C# dynamically typed”
  • “C# becomes loose at runtime”

Correct understanding

C# remains statically typed everywhere.

  • var still resolves to a fixed type at compile time
  • Method parameters and return values are always fixed
  • The compiler knows all types before execution

Final One-Line Summary

A statically typed language is one where the compiler actively blocks human mistakes,
and method signatures are the written contracts that make this possible.

🍪 Cookies Explained Like You're 5

2026-02-08 06:29:17

A wristband at a club

Day 44 of 149

👉 Full deep-dive with code examples

The Club Wristband

You go to a club. Pay at the door. Get a wristband.

Now you can:

  • Leave and come back
  • Staff knows you already paid
  • No need to pay again

Cookies are digital wristbands!

How They Work

  1. You visit a website
  2. Website gives your browser a "cookie" (a small piece of data)
  3. Next time you visit, browser shows the cookie
  4. Website recognizes you!
Visit 1: "Here's your cookie: user=alex"
Visit 2: Browser shows cookie → "Welcome back, Alex!"

What Cookies Store

  • Login status (so you stay logged in)
  • Shopping cart items
  • Preferences (dark mode, language)
  • Tracking info (ads use this)

Types

Type What it means
Session Typically lasts for the current browsing session (but some browsers can restore them)
Persistent Has an expiry time/date; can last days/weeks/months
Third-party Set by a different site than the one you're visiting (often used for ads/analytics)

Privacy Concerns

Cookies can be used for tracking across websites. That's why many sites ask:
"Do you accept cookies?" 🍪

In One Sentence

Cookies are small pieces of data websites store in your browser to remember who you are and your preferences.

🔗 Enjoying these? Follow for daily ELI5 explanations!

Making complex tech concepts simple, one day at a time.

I Built a Client Portal That Does Less on Purpose

2026-02-08 06:28:55

Every client tool I tried wanted to run my entire business. So I built one that doesn't.

I'm a freelancer. I design things, I build things, and then I have to figure out how to actually get that work to my client.

For years my workflow looked like this: finish the work, zip it up, attach it to an email, type "Hey, here are the files — let me know what you think," and hit send. Sometimes I'd use a Google Drive link. Sometimes Dropbox. Once I even used WeTransfer like it was 2014.

None of it ever felt professional. I'd spend hours making the work look great, then deliver it through a channel that made me look like I was winging it.

So I looked into "real" tools. Dubsado. HoneyBook. Basecamp. Plutio. They all promised to solve this problem. And they did — along with about forty other problems I didn't have.

The Bloat Problem

Every client portal I evaluated came with invoicing, contracts, a CRM, scheduling, time tracking, team chat, and a dozen integrations I'd never configure. The onboarding tutorials were 30 minutes long. The pricing started at $20/month and climbed from there.

I already had an invoicing tool I liked. I didn't need a CRM for my twelve clients. I definitely didn't need "team collaboration" features as a solo freelancer.

All I wanted was a clean page where my client could see their project, download files, and read my updates. That's it. One simple thing.

I couldn't find it, so I built it.

What Delivr Actually Does

Delivr does three things:

You share files. Upload a deliverable, your client downloads it. One click. No digging through folders, no expired links, no "which version is the latest?" confusion.

You post updates. Write a quick note — "Round 1 designs are ready" or "Waiting on your feedback for the logo." Your client sees it immediately. They can reply right there.

You look professional. Your portal uses your name, your colors, your brand. When a client visits, they see your studio — not some generic tool's interface.

That's the whole product.

What Delivr Doesn't Do

This is the part I'm most proud of.

Delivr doesn't do invoicing. It doesn't do contracts. It doesn't do time tracking, scheduling, CRM, team chat, or project templates. It doesn't have a Gantt chart. It doesn't have Kanban boards. It doesn't have AI-powered anything.

And that's the point.

You already have tools for those things. Maybe you use FreshBooks for invoicing and Google Calendar for scheduling. Maybe you use Notion for your own project management. Whatever your setup is, it works. You don't need another tool trying to replace all of them.

Delivr handles the one thing those tools can't: giving your client a clean, branded place to see their work.

How It Works

The setup takes about five minutes.

You sign up, name your studio, and your portal is live. You create a project, enter your client's email, and they get a link. You upload files and post updates. Your client sees everything in one place.

No onboarding tutorial. No configuration wizard. No "getting started" checklist with 15 steps.

Your client doesn't need to learn anything either. They click a link, they see their project, they download their files. If they want to leave a reply, there's a text box. That's it.

The Technical Side

For anyone curious about the stack: Delivr is built with Next.js 14, Prisma, and PostgreSQL. Authentication runs through NextAuth with role-based access — freelancers see the dashboard, clients see the portal. Email notifications go through Resend.

I'm a solo developer running this out of my apartment. There's no team, no investors, no runway. Just a product that solves a problem I had.

Who This Is For

Delivr is for the freelancer who has 3-15 clients and wants to look more professional without adding complexity to their workflow.

You're a designer sending brand assets. A developer delivering a website. A photographer sharing edited galleries. A consultant sending reports. A videographer delivering cuts for review.

You don't need a business management suite. You need a clean way to share work and keep clients in the loop.

Try It

Delivr is live at delivr.studio. Free to start, set up in five minutes, cancel anytime.

If you're a freelancer and you've ever felt weird about emailing a zip file to a client, this is for you.

I'm building Delivr in public. If you have feedback, there's a feedback button in the app — I read everything. You can also find me on Twitter/X.

How I Built a Random Number Generator (Sort Of)

2026-02-08 06:26:59

TL;DR: I made an Hybrid Hardware Random Number Generator (HHRNG) using radio noise. You can find the full source code on my GitHub.

Generating randomness is fascinating, and I always wanted to go deeper than just importing some library into my python project and calling .random(). So I set out to build my own library with its own .random() function. Revolutionary, I know.

But I didn't want to just cobble together pseudo-random values. I wanted to build a hardware random number generator (HRNG): one that uses actual physical processes to generate entropy. Think Linux's /dev/random, which harvests entropy from environmental noise: keyboard timings, mouse movements, disk I/O patterns. Windows also have a component named CNG (Cryptography Next Generation) that uses similar inputs.

When I hear noise, the first thing that comes to mind is this:

Radio noise

For the uninitiated, this is an SDR (Software Defined Radio), a real-time visualization of the radio spectrum around me. Notice the constant flickering at the bottom? That's noise, pure and simple. Nothing is transmitting there, yet the intensity is constantly dancing. It's the same static you hear when tuning to an empty FM frequency. If we could capture and measure that movement, we'd have a source of true randomness, unpredictable and nearly impossible to manipulate.

So, based on that, I decided to get to work. Note that I will be using a SDR blog v4 to capture radio signals and compute them.

Here is a global overview of what I needed to do to get this project done:

  • ☐ Find a way of getting the radio signals on my PC
  • ☐ Process them to generate randomness
  • ☐ Create the core functions
  • ☐ Add other functions on top of that
  • ☐ Check that everything works and isn't easily affected by external events

Setting Up the Foundation

So, first of all, I needed to find a way to programmatically access my radio data, served as samples. I'd tried this on Windows before with no luck, so this time I went straight to a template that connects over the network on an rtl_tcp server running on one of my Raspberry Pis.

Once everything setup, I was able to receive samples. The code is quite simple, it uses a socket to connect to the rtl_tcp server, and then reads samples from it. Here is a part of the read_samples function, that reads and processes the signals:

codesnap

As we can see, it computes IQ samples. I and Q refer to two components of a complex baseband signal. They capture both amplitude and phase of the RF signal.

Well, anyways:

  • Find a way of getting the radio signals on my PC

Creating Randomness

The next step is building the "randomizer". It is basically a function that will take, as an input, samples from our SDR, and output a seed we will base our calculations on later.

To do this, I've tried a couple of ways (2, actually), but the most efficient method was using Phase difference.

The phase is the angle of the signal at a given moment. It can be easily calculated using both values of an IQ sample using this formula:
angle = atan2(Q, I).

We'll do this for both the current iteration value (n), and the previous one (n-1).

After getting both angles, we will retrieve the phase difference, that will tell us in which direction the signal rotated since the previous sample. It can be done like this: delta = (current_angle - previous_angle + π) % 2π - π

The wrapping in π is to ensure that the result stays between -π and +π, and doesn't make big jumps, like going from 2° to -359° just by rotating 3°.

We got the rotation angle, but that value is still too complex to be properly processed. We will reduce it to a simple bit. The easiest way to do this is by checking its direction:
bit = delta > 0 ? 1 : 0

Now that we got a bit, we're simply repeating this n samples times, to get a randomly generated bits array.

But there's a problem. After running the program, and logging some statistics, I observed more 1s than 0s, which isn't great, since the program would tend to go on the 1 side more than the 0 one.

Fixing that is easy, and there are plenty of methods available. I used a very simple one: XOR-ing all the values together, to spread the 1s and 0s. For those who don't know what it implies, it is a simple bit operation:

0 & 0 -> 0
0 & 1 -> 1
1 & 0 -> 1
1 & 1 -> 0

I used that to compare both bits each others, and the results were perfect: we went from a near 20% difference to a max of around 2%.

Finally, for convenience, I'm hashing the results to get an uniform seed to continue with (using SHA256).

  • Process the signals to generate randomness

Code explained in this part
code snippet

Building the Core Functionalities

We now have our random seed source, but now we have to let the user actually use it.

My first plan: every time someone calls .random(), grab fresh samples from the SDR, generate a seed, and convert it to a float.

This was painfully slow: we were hitting the hardware for every single random number.

Solution: make it hybrid. Use a fast Pseudo-Random Number Generator (PRNG) that gets periodically reseeded with fresh radio entropy, instead of hitting the SDR every time.

This was fairly straightforward to achieve:

  • We first update our seeder to update its seed each X milliseconds, using a runner thread.
  • Then, we create a Pseudo-Random Number generator. I used a simple Linear Congruential Generator (LCG), made with the help of this very good video.
  • We change our code to constantly feed the generator with our new seed.

Now the code uses the LCG as a base, but it is always reseeded with our seeds taken from our radio samples.

Now, let's build our core random class, that we will call RFDom. We will optionally pass arguments to it, such as the rtl_tcp host, frequency ranges to scan, gain, and other settings.

.random() (returns [0.0, 1.0)) was pretty simple to do, as it used the same code as the youtube tutorial, same for .randint(a: int, b: int), that returns [a, b]. I've just had to implement a include: bool parameter to the LCG API, but that was quite easy.

LCG .get_float()
code snippet

RFDom .random()
code snippet

And done !

  • Create the core functions

Adding Other Stuff

After adding .random() -> [0.0, 1.0), .uniform(a: float, b: float) -> [a, b], and .randint(a: int, b: int) -> [a, b] I've looked to the core functions of the python random library, and tried to replicate them. Some of them were really easy, some were quite a bit harder to do. I'm not going to explain all of them, since it's just a bunch of formulas, but here are two that I found quite interesting:

1. Choices

The .choices() func takes at max 4 arguments:

  • population: a sequence of objects
  • weight (optional): the probability weight of each object to get picked
  • cum_weights (optional): preprocessed cumulative weights
  • k (optional): the number of objects to pick

The way it works is pretty simple, even tho it was a bit hard to implement:

  1. Each population object has a weight, either the same for every object, or a given one for each object.
  2. If no weight (or cum_weights) has been provided, simply take a random object in the population array k times.

code snippet

  1. If a weight array is provided, we will need to build a cum_weight list, if it isn't already provided.

The cumulative weights represent the range where a number falls into an object, like this:

objects -> ["apple", "banana", "orange"]
weights -> [4,        1,       6]

cum_weights = [4,     5,       11]

=> 
apple -> [0, 4)
banana -> [4, 5)
orange -> [5, 11)
  1. Choose a random object k times, based on the weights:

we use .uniform(0, max_weight) to get a float value, get the object falling in that range, add it to the list

  1. Return the list: we return a list of k elements chosen randomly

code snippet

2. shuffle

The .shuffle() function is much simpler, but I wanted to talk about the algorithm.
It takes a list as the only argument and edits it in-place (doesn't return it, but changes the original).

To do this, we're using the Fisher-Yates algorithm:

  • Starting from the beginning of the list, for each index i, a random index j is chosen from the range [i, n - 1], and the elements at positions i and j are swapped.
  • Repeat until everything has been shuffled.

It is represented by this code:

code snippet

  • Add other functions on top of that

Trying to break the randomizer

My first idea (before even starting the project) was to try to break it out by overflowing the bandwidth using this tool.

I then made this simple code to have an eye on the values

code snippet

I ran it, first without any special radio broadcast or whatsoever.

Then, I ran the program, and I observed. No changes at all, but that was predictable. Even with the bandwidth saturated, oscillations in the signal are still there, and the phase difference still works. I also later had an AI analyze the results, which confirmed there weren't any major changes.

  • Check that everything works and isn't easily affected by external events

For the End

This project began with a simple question: where does randomness actually come from ?, and turned into a deep dive into radio physics, signal processing, entropy extraction, and practical limits.

Building this taught me that randomness isn't magic: it's trade-offs. Hardware entropy is slow but truly random. PRNGs are fast but predictable. Combining both? That's where it gets interesting.

Is this generator cryptographically secure ? Probably not. Is it faster than Python's built-in random ? Definitely not. Would I recommend using this in production (or in general) ? Absolutely not.

But that was never the point.

In the end, I won't replace the casual import random when I need randomness, but I learned how this works behind the scenes, even if it's only a fraction of the modern random generators.

If you're interested into seeing the full code, I uploaded it to my GitHub. Usage examples can be found in the /examples/ dir, and installation instructions on the README.

Questions? Ideas?

If you have any questions about the implementation, suggestions for improvements, or you've experimented with similar approaches, feel free to drop a comment below. I'm curious to hear what you think!

Additional Resources

Here are some links of videos / websites that I used to understand the subject better (not in any specific order). I might've forgotten some.

The Actual Generator

A SDR connected to a raspberry pi

CodeBehind 4.6 Released; Upgrade to .NET 10

2026-02-08 06:25:14

At Elanat, right after introducing advanced async capabilities in 4.5, we released 4.6, which included a major upgrade: migrating the CodeBehind framework from .NET 7 to .NET 10. Along with this key migration, we also upgraded the Roslyn compiler from 4.6 to 5, so that developers can benefit from the most complete set of modern tools and performance improvements.

The transition from .NET 7 to 10 brings tangible benefits to .NET-based systems (such as the CodeBehind framework). In terms of performance, deep optimizations in runtime and memory management in .NET 10 lead to a speed increase of about 20-30% and reduced latency in processing concurrent requests. In the area of ​​software development, .NET 10's companionship with newer versions of C# (such as 12) allows for the use of features such as Primary Constructors and Collection Expressions, which result in writing more concise, readable, and efficient code. Security is also improved by updating the base libraries and applying the latest patches. Finally, migrating to this stable version ensures synchronization with the ecosystem and enables access to the latest tools, libraries, and long-term support.

CodeBehind Web Framework

With a different approach to web development in .NET, CodeBehind is worth checking out because it frees developers from unnecessary complexity by focusing on the complete separation of the logic layer from the presentation. This complete separation significantly increases the maintainability and readability of the code, and allows front-end and back-end teams to collaborate in parallel without interference. In addition, its flexible architecture allows you to implement the project exactly according to your needs (from full MVC to Only-View), while automating many tasks significantly increases the speed of development.

Related links

CodeBehind on GitHub:
https://github.com/elanatframework/Code_behind

Get CodeBehind from NuGet:
https://www.nuget.org/packages/CodeBehind/

CodeBehind page:
https://elanat.net/page_content/code_behind

测试文章2Hashnode专属

2026-02-08 06:23:30

测试文章2Hashnode专属这篇文章将只发布到Hashnode平台## Hashnode特色- 支持丰富的Markdown格式- 面向技术博主- 良好的SEO优化### 代码高亮


pythondef hello_hashnode(): print('Hello Hashnode!')

专为Hashnode社区定制的内容